cincplug
cincplug

Reputation: 1054

Mouseout event fires before mouse is actually out

I have a mouseover / mouseout handler. Both use Javascript timeout to delay their job. But mouseout event triggers even when mouse is still over the selector. It works normally when timeout is turned off in mouseout script. So I suppose I do something wrong about timeout. It is something like

      $('.selector').live( {mouseover : function() {
          var timeout = setTimeout(function() {
        $('.something' ).show();
          }, 1000);
    }, mouseout: function () {
          timeout = setTimeout(function() {
        $('.something' ).hide();    
          }, 2000);
    }
      });

Same thing happens if I use hover handler instead of mouseover / mouseout. And same thing if I use different variable names for two timeouts, or if I clear one timeout before calling another. What do I do wrong?

Upvotes: 0

Views: 431

Answers (2)

Esailija
Esailija

Reputation: 140236

Since it works normally without timeouts I assume mouseover/mouseout is the correct event for you instead of mouseenter/mouseleave.

You are calling multiple timeouts constantly which are firing all over the place, you need to use a single timer that is only timing a single thing at one time:

(function () {
var timeout = 0;
    $('.selector').live({
    mouseover: function () {
    window.clearTimeout( timeout );
        timeout = setTimeout(function () {
        $('.something').show();
        }, 1000);
    },
    mouseout: function () {
    window.clearTimeout( timeout );
        timeout = setTimeout(function () {
        $('.something').hide();
        }, 2000);
    }
    });
})()

window.setTimeout just returns an ordinary integer number. Each time you call window.setTimeout a new timer will be created regardless of what variable the return value is assigned to. The return value of window.setTimeout can be used to clear a specific timer.

As a side effect, you can clear timeouts that you don't even know are existing. For example:

jQuery("div").fadeOut( 15000 );

var l = 10000;

while( l-- ) window.clearTimeout( l );

You are brute forcing 10000 different timer ids and clearing them all, taking out the jQuery fx internal timer which stops the fading out. Do not use in real code, for demonstration purposes only.

Upvotes: 2

Ilia Choly
Ilia Choly

Reputation: 18557

You should clear the timeout so they don't overlap.

var timeout = null;
$('#foo').live({
    mouseover: function() {
        if(timeout !== null){ 
            clearTimeout(timeout); 
            timeout = null;
        }
        timeout = setTimeout(function() {
            $('#bar').show();
        }, 1000);
    },
    mouseout: function() {
        if(timeout !== null){ 
            clearTimeout(timeout); 
            timeout = null;
        }
        timeout = setTimeout(function() {
            $('#bar').hide();
        }, 2000);
    }
});

demo: http://jsfiddle.net/46mFc/1/

Upvotes: 0

Related Questions