2

Here's my code...

 $('nav ul li').hover(function() {

    $(this).addClass('hoverIn');


  },
  function() {

    $(this).addClass('hoverOut');


  });

which works fine.

But when I add delay() and removeClass() it doesn't work, as follows...

 $('nav ul li').hover(function() {

    $(this).addClass('hoverIn').delay(800).removeClass('hoverIn');


  },
  function() {

    $(this).addClass('hoverOut').delay(800).removeClass('hoverOut');


  });

Am I doing something wrong here?

Any help would be greatly appreciated. Thanks.

user1378715
  • 139
  • 2
  • 7

3 Answers3

5

.delay() only works with jQuery methods that use the animation queue, thus is does not work with removeClass().

The removeClass() operation will still be performed, but it will be performed immediately, not after the delay time.

So, when you do:

$(this).addClass('hoverIn').delay(800).removeClass('hoverIn');

that is the same as:

$(this).addClass('hoverIn').removeClass('hoverIn');

which is the same as doing nothing, thus you see not effect.


You can solve your problem with setTimeout() like this:

 $('nav ul li').hover(function() {
    var self = $(this).addClass('hoverIn');
    setTimeout(function() {self.removeClass('hoverIn');}, 800);
  }, function() {
    var self = $(this).addClass('hoverOut');
    setTimeout(function() {self.removeClass('hoverOut');}, 800);
  });

Or, using a common function, like this:

jQuery.fn.addClassTemporary = function(cls, t) {
    var self = this.addClass(cls);
    setTimeout(function() {self.removeClass(cls);}, t);
}

 $('nav ul li').hover(function() {
     $(this).addClassTemporary('hoverIn', 800);
 }, function() {
     $(this).addClassTemporary('hoverOut', 800);
 });
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • +'d, a custom function, nice :) – Zuul Jun 10 '12 at 23:12
  • IMHO this is unnecessarily complicated. – Alnitak Jun 10 '12 at 23:12
  • @Alnitak - and your queue, dequeue custom function is less complicated? Hardly. Either can work, but I'd be surprised if folks thought your solution was less complicated than this one. – jfriend00 Jun 10 '12 at 23:40
  • @jfriend00 I was referring to your use of `setTimeout` versus `.queue`, which IMHO is the right way to run something in sequence with an animation. The jQuery plugin came later... – Alnitak Jun 11 '12 at 08:35
5

As others have mentioned, .removeClass() is not an animation function so is unaffected by any queued effects.

The simplest solution is to use .queue() to insert your call into the animation queue:

$(this).addClass('hoverIn').delay(800).queue(function() {
    $(this).removeClass('hoverIn').dequeue();
});

The .dequeue() call is important to ensure that any other queued operations still take place.

Note that using the animation queue also means that you can use .stop() to cancel the operation if it hasn't happened yet. Using timers would make that a lot more complicated.


If you want to get really fancy, this plugin I just knocked out will allow you to add any arbitrary jQuery function into the animation queue:

(function($) {
    $.fn.queued = function() {
        var self = this;
        var func = arguments[0];
        var args = [].slice.call(arguments, 1);
        return this.queue(function() {
            $.fn[func].apply(self, args).dequeue();
        });
    }
}(jQuery));

with this, the line above would become:

$(this).addClass('hoverIn').delay(800).queued('removeClass', 'hoverIn');

demo at http://jsfiddle.net/alnitak/h5nWw/

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • +'d this by being fast; simple; and my personal favorite: two lines of code are enough :) – Zuul Jun 10 '12 at 23:13
1

jQuery .delay() applies to the animation queue, it does not serve as a timer like setTimeout does...

To your goal, I can suggest you to use the hoverIntent plug-in:

See this working Fiddle Example! adjust the timeout to fit your needs

jQuery

$("nav ul li").hoverIntent({    
    sensitivity: 1, // number = sensitivity threshold (must be 1 or higher)    
    interval: 10,   // number = milliseconds for onMouseOver polling interval    
    timeout: 800,   // number = milliseconds delay before onMouseOut    
    over:function(){
        $(this).removeClass("hoverOut").toggleClass("hoverIn");
    },
    out: function(){
        $(this).removeClass("hoverIn").toggleClass("hoverOut");
    }
});
Zuul
  • 16,217
  • 6
  • 61
  • 88