2

This is the situation: I have a product list with 4 product in a row. When you hover one of the products, a tooltip is shown. My concern is that if you move your mouse quickly from left to right or whatever over the products, you get all of the tooltips shown for a few seconds. I wonder if I can say to jQuery to start the animation only if the mouse is over the product for 2 seconds. So if you let your mouse over the product for 1 sec. and then mouse out, the animation won't start at all. I'm using jQuery 1.2.6 and this is my code for the tooltips:

$(document).ready(function(){
$('.thumb-image').hover(function() {
    $(".thumb-image").mousemove(function(e){
        $(this).find(".t-desc").filter(":not(:animated)").fadeIn(500);
            $(this).find(".t-desc").css({
                top: (e.pageY + 27) + "px",
                left: (e.pageX - 20) + "px"     });
    }); 
    }, function() {
        $(this).find(".t-desc", this).fadeOut(250);             
}); 
});
casperOne
  • 73,706
  • 19
  • 184
  • 253
memario
  • 23
  • 1
  • 8

4 Answers4

4

This my friend is what you need: jQuery HoverIntent plugin

Moin Zaman
  • 25,281
  • 6
  • 70
  • 74
1

Set a timer when you hover and only show the tip if the hover lasts for more than that time. If you leave the current object before the timer fires, you cancel the outstanding timer. If you leave the current object after the tip is showing, you fade it out.

I also added a couple .stop(true, true) method calls in case any previous animation is underway so that can be stopped and accelerated to the end position. This could happen if the mouse leaves before the fadeIn completes. It probably isn't required for the fadeOut because of the 2 second delay, but it doesn't hurt and might protect against some edge case.

You can do that like this:

$(document).ready(function(){
    var tipTimer = null;
    $('.thumb-image').hover(function() {
        var self = this;
        if (tipTimer) {
            clearTimeout(tipTimer);
            tipTimer = null;
        }
        tipTimer = setTimeout(function() {
            tipTimer = null;
            $(self).find(".t-desc").filter(":not(:animated)").stop(true, true).fadeIn(500);
                $(self).find(".t-desc").css({
                    top: (e.pageY + 27) + "px",
                    left: (e.pageX - 20) + "px"});
            }, 2000);
        }, function() {
            if (tipTimer) {
                clearTimeout(tipTimer);
                tipTimer = null;
            }
            $(this).find(".t-desc", this).stop(true, true).fadeOut(250);             
    }); 
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • The concept is solid. There could be a syntax error somewhere, but without a working code example, it's hard for us to help with that. When you say "doesn't work", what do you see? Are there JS errors in the error console? Does it pop up after 2 seconds? What happens? – jfriend00 Oct 23 '11 at 20:57
  • OK so for now the problem is the using of (this) $(this).find ... fadeIn(500); $(this).find(".t-desc").css({ if I replace $(this) with $('.thumb-image') the script works, but the only problem is that after 2 seconds, it shows all of the products tooltips, because I don't have the $(this) statement anymore I guess. – memario Oct 23 '11 at 21:06
  • did you try jquery hover intent plugin – kobe Oct 23 '11 at 21:08
  • I've modified it to fix the issue with `this` which is not valid inside the timer callback. – jfriend00 Oct 23 '11 at 21:10
  • This works now, the only thing left is that the ".mousemove" function is missing in the code that you gave me. So the tooltip is not following the mouse. – memario Oct 23 '11 at 21:26
  • I figure you can add the mousemove code yourself, no? You will have to unbind the .mousemove event handler when you stop hovering over that element, otherwise you pile up multiple handlers on the same object and you don't want it in action after you stop hovering either. – jfriend00 Oct 23 '11 at 21:30
  • Damn I hate to say it but I still need help. I added the mousemove code, but I don't know how to do the unbind moment. I also noticed something weird now. If I move my mouse over the .thum-image and wait, nothing happens unless I move the mouse again even with a millimeter. – memario Oct 23 '11 at 21:42
0

You should use mouseenter and mouseleave.

On mouseenter, start a setTimeout delaying your animation for 2sec. On mouseleave, clear your timeout.

So if the mouse hover less than 2s, nothing will show.

Please ask if you need a practical example.

Edit : So, I would try this :

$(document).ready(function(){

    var timer;
    $('.thumb-image').bind('mouseenter',enter).bind('mouseleave',leave);

    function enter(){
        var $this = $(this);
        clearTimeout(timer);
        timer = setTimeout(function()
        {
                $this.find(".t-desc").filter(":not(:animated)").fadeIn(500);
                $this.find(".t-desc").css({
                    top: (e.pageY + 27) + "px",
                    left: (e.pageX - 20) + "px"     });
            },2000);
    }); 

    function leave() {
        var $this = $(this);
        clearTimeout(timer);
        $this.find(".t-desc", this).fadeOut(250);             
    }); 

});

... but I can't be sure it'll work without looking at your code.

mddw
  • 5,570
  • 1
  • 30
  • 32
0

Ok so a friend of mine helped me on this and here is the final code which is working perfectly:

$(document).ready(function(){
var tipTimer = null;
$(".thumb-image").mouseover(function(){
    var self = this;
    $(self).bind('mousemove', function(e){                
        $(self).find(".t-desc").css({
            top: (e.pageY + 27) + "px",
            left: (e.pageX - 20) + "px"
        }); 
    });
    if (tipTimer) {
        clearTimeout(tipTimer);
        tipTimer = null;
    }
    tipTimer = setTimeout(function() {
        tipTimer = null;
        $(self).find(".t-desc").filter(":not(:animated)").stop(true, true).fadeIn(500);
        }, 600);      

}).mouseout(function(){
        $(this).unbind('mousemove');
        if (tipTimer) {
            clearTimeout(tipTimer);
            tipTimer = null;
        }
        $(this).find(".t-desc", this).stop(true, true).fadeOut(250);
});

});

memario
  • 23
  • 1
  • 8