1
\$\begingroup\$

I'm trying to hover over over the img then use Greensock Tweenmax on hover to control the speed and opacity of the text within the span. The opacity will change on mouseover and mouseout.

The problem is that I'm having to repeat the same exact same effect on several div's and it's becoming repetitive. Each one will be unique to the image being hovered. I don't want them all to appear at the same time when I hover over one div. I could give them all the same class then use .hover but then that would activate all of them instead of individually.

They are only to appear respective to that particular div being hovered. It works just fine, but I would like to simplify it since I will be doing this to about 20 different divs.

I need some help simplifying the code below. It works just fine, but maybe there is an easier way.

<a href="#click-for-modal" data-toggle="modal">
    <div class="test">
    <img src="img/image.png"><span>Here is some text</span>
    </div>
</a>

<a href="#click-for-another-modal" data-toggle="modal">
    <div class="testx">
    <img src="img/image.png"><span>Here is some other text</span>
    </div>
</a>


/* tweenmax hover animations */
 $('.test img').hover(
    function(){
     /*mouseover function*/
     TweenLite.to(".test span", 1.5, {opacity:1});
    }, 
    function(){
    /*mouseout function*/
     TweenLite.to(".test span", 1.5, {opacity:0});
 });

 $('.testx img').hover(
    function(){
     /*mouseover function*/
     TweenLite.to(".testx span", 1.5, {opacity:1});
    }, 
    function(){
    /*mouseout function*/
     TweenLite.to(".testx span", 1.5, {opacity:0});
 });

 $('.testxy img').hover(
    function(){
     /*mouseover function*/
     TweenLite.to(".testxy span", 1.5, {opacity:1});
    }, 
    function(){
    /*mouseout function*/
     TweenLite.to(".testxy span", 1.5, {opacity:0});
 });

 $('.testxyz img').hover(
    function(){
     /*mouseover function*/
     TweenLite.to(".testxyz span", 1.5, {opacity:1});
    }, 
    function(){
    /*mouseout function*/
     TweenLite.to(".testxyz span", 1.5, {opacity:0});
 });
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to Code Review! To make life easier for reviewers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. See also this meta question \$\endgroup\$ Commented Jul 17, 2014 at 22:04
  • \$\begingroup\$ Just use closures. \$\endgroup\$
    – rds
    Commented Jul 17, 2014 at 22:10
  • \$\begingroup\$ Thanks @SimonAndréForsberg I'll review the link and update the answer. \$\endgroup\$ Commented Jul 17, 2014 at 22:20

2 Answers 2

1
\$\begingroup\$

The recommended way is to use event delegation:

$('.test, .testx, .testxy, .testxyz')
  .on('mouseover', 'img', function (e) {
    TweenLite.to($(e.delegateTarget).find('span'), 1.5, {opacity:1});
  }).on('mouseout', 'img', function (e) {
    TweenLite.to($(e.delegateTarget).find('span'), 1.5, {opacity:0});
  });

This will add the mouseover and mouseout events to all img tags within your parent elements. When the event is fired e.delegateTarget will be the parent element, so we can easily search for the span.

\$\endgroup\$
7
  • \$\begingroup\$ I believe this would assume that the spans are inside the img. \$\endgroup\$
    – RoToRa
    Commented Jul 18, 2014 at 10:13
  • 1
    \$\begingroup\$ @RoToRa Whoops, you are right. It should be using the delegateTarget. \$\endgroup\$
    – Jivings
    Commented Jul 18, 2014 at 10:14
  • \$\begingroup\$ This won't handle the cases where there are 2+ .testx and the user clicks one \$\endgroup\$
    – megawac
    Commented Jul 18, 2014 at 14:10
  • \$\begingroup\$ @megawac The original code posted also doesn't cater for that. \$\endgroup\$
    – Jivings
    Commented Jul 18, 2014 at 14:34
  • \$\begingroup\$ @Jivings Thank you for your answer, let me update my question as per Simons request to further clarify my question \$\endgroup\$ Commented Jul 18, 2014 at 15:36
0
\$\begingroup\$

Considering you are assigning the same functionality to all of those elements, you should assign them all the same class, eg:

<div class="test my-hover">...</div>
<div class="testx my-hover">...</div>
<div class="testxy my-hover">...</div>
<!-- etc. -->

and then use $(".my-hover").

(BTW, my-hover is just an example, and is probably a bad choice for a class name. Use a class name that expresses why they get that hover effect, not that they get a hover effect.)

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for you input, but this solution wouldn't work because then the hover would trigger all the events at the same time. As opposed to individually. \$\endgroup\$ Commented Jul 18, 2014 at 15:34
  • \$\begingroup\$ @user1222186 No, it wouldn't. The class name just defines which elements the event handlers apply to. The use of this/event.target (or in the case of Jivings solution event.delegateTarget) inside the handler decides which elements the effects are applied to. \$\endgroup\$
    – RoToRa
    Commented Jul 19, 2014 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.