Shyam Mohan Shyam Mohan - 2 months ago 8
jQuery Question

Do something after the last elemnt animation in an each function

I want do something after the last element animation in the each function.
I tried below code but it seems not working.

$(".menu").click(function() {
var elems = $('.top-menu ul li'),
i = 0;
elems.each(function(i) {
i += 1;
$(this).delay(70*i).fadeIn(300);
if(i == elems.length) {
$('.bodyWrapper').addClass('noBodyScroll');
}
});
});

Answer

You're fairly close, just move it into the fadeIn callback, and don't manage i yourself; jQuery provides it as the first argument to your each callback already:

$(".menu").click(function() {
    var elems = $('.top-menu ul li');
    elems.each(function(i) {
        $(this).delay(70*i).fadeIn(300, function() {       // ***
          if(i == elems.length - 1) {                      // *** note the - 1
            $('.bodyWrapper').addClass('noBodyScroll');
          }
        });
    });
});

That doesn't have the callbacks-in-a-loop problem because each call to the each callback gets its own i argument, which doesn't get updated.

Note that I left i alone before the first 70*i. If it's important that the first element get delayed by those 70ms, you probably want to go ahead and increment i (which will only happen once):

$(".menu").click(function() {
    var elems = $('.top-menu ul li');
    elems.each(function(i) {
        ++i;                                            // ***
        $(this).delay(70*i).fadeIn(300, function() {
          if(i == elems.length) {                       // *** note the - 1 is gone
            $('.bodyWrapper').addClass('noBodyScroll');
          }
        });
    });
});