0

I have this function and I am wondering why the setTimeout is not working:

$(document).ready(function() {      
    $('.sliding .text').css("top","130px")     

    $('.sliding').mouseenter(function() {       
        mouseOverTimer = setTimeout(function() {
            $(this).find('.text').animate({"top": "0"}, 200);             
        }, 500);       
    })
    .mouseleave(function() { 
        $(this).find('.text').delay(500).animate({"top": "130px"}, 400); 
    });       
});     

I tried wrapping the mouseenter event in the timeout, but that didn't seem like a great idea. I just want the animation on mouseenter to only work after the mouse has been over it for at least half a second.

Alternatively, is there a better way of doing it in jQuery?

4 Answers 4

3

The this value inside your timeout handler will not be what you think it'll be. Add an explicit variable:

   $('.sliding').mouseenter(function() {   
        var self = this;    
        mouseOverTimer = setTimeout(function() {
            $(self).find('.text').animate({"top": "0"}, 200);             
        }, 500);       
    })

Also you should declare "mouseOverTimer" as a local variable outside the handler setup code (that is, as a local variable of the "ready" handler) and then cancel the timeout in the "mouseleave" handler:

    var mouseOverTimer = null;

   $('.sliding').mouseenter(function() {   
        var self = this;    
        mouseOverTimer = setTimeout(function() {
            $(self).find('.text').animate({"top": "0"}, 200);             
        }, 500);       
    })
   .mouseleave(function() { 
        $(this).find('.text').delay(500).animate({"top": "130px"}, 400); 
        cancelTimeout(mouseOverTimer);
    });       

As I look at this, I'm pretty sure that the "mouseleave" code isn't really what you want; specifically I think the delay is probably unnecessary. I'm not 100% sure about what you want things to look like, however.

Sign up to request clarification or add additional context in comments.

3 Comments

The answer is here... However you may also want to look at ben alman's throttle/debounce jQuery plugin: benalman.com/projects/jquery-throttle-debounce-plugin
Oh I see. Thank you for the answer. Not being able select $(self) then becomes a problem because I have multiple elements on a single page using this function.
nevermind, I can set a variable outside of the setTimeout, thank you!
0

I would perhaps simplify the problem this way: On mouseover I would instantiate a new Date(), getTime() on it and stash it into a var. Then on mouseleave you take another date, grabbing the timestamp again. In that same mouseleave, do an evaluation: if the difference between date 1 and date 2 is greater than 1/2 second, you fire your action. Else, you reset date 1.

2 Comments

I was thinking the same thing, but the OP may want the animation to proceed even if a user doesn't leave the element.
Great minds think alike. :) The OP said "I just want the animation on mouseenter to only work after the mouse has been over it for at least half a second," which, if I'm reading that literally and correctly, seems to jibe with the above.
0

you could try this instead of using setTimeout:

$(document).ready(function() {      
    $('.sliding .text').css("top","130px")     

    $('.sliding').mouseenter(function() {       
        $(this).find('.text').stop().delay(500).animate({"top": "0"}, 200);             
    })
    .mouseleave(function() { 
        $(this).find('.text').stop().animate({"top": "130px"}, 400); 
    });       
});

This will delay the mouseover animation by 500ms. If you mouse out, it calls stop(), which would kill the pending animation and then animate back to the starting position. If it never moved, the mouseout animation will also not happen (correctly - it has nowhere to go).

2 Comments

Nice idea, this would have been ideal, the stop doesn't seem to work however.
Huh, I wasn't expecting that. Does it work any differently if you don't chain the two event handlers?
0

Another way to do this

mouseIn = false;
$(document).ready(function() {      
    $('.sliding .text').css("top","130px")     

    $('.sliding').mouseenter(function() {   
        mouseIn = true;  
        mouseOverTimer = setTimeout(function() {
            if(mouseIn==true)
                 $(this).find('.text').animate({"top": "0"}, 200);             
        }, 500);       
    })
    .mouseleave(function() {
        mouseIn=false;
        $(this).find('.text').delay(500).animate({"top": "130px"}, 400); 
    });       
});

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.