user3185872
user3185872

Reputation: 25

jQuery wait for first animation to finish before starting next one

Need to make DOM elements fade in one after another with jQuery, obviously i need loop as i have 20 elements, i don't know proper way to make loop in jQuery so i did following.

However callback does not work properly, all elements fade in at same time, it supposed to wait for first animation to finish and only then run animate_element() again.

If there's better way to do it i'd like to know it, however i also wonder why below code does not work?

$('div').css("display", "none");
$('div').addClass("needs_animation");

function animate_element(){
    if ( $("div[class='needs_animation']:first").length ) {

        $("div[class='needs_animation']:first").removeClass("needs_animation");

        $("div[class='needs_animation']:first").fadeIn(2000, animate_element());

    }
}

animate_element();

Example: http://jsfiddle.net/m7PWT/1/

EDIT: Fixed thanks to John S response, however i used my own code even though its performance not the best, as its more clear for me at this point.

$('div').css("opacity", "0");
$('div').addClass("needs_animation");

function animate_element(){
    if ( $("div[class='needs_animation']").length ) {

        $("div[class='needs_animation']:first").animate({opacity:1}, 100, function() {
            $("div[class='needs_animation']:first").removeClass("needs_animation");
            animate_element()
        });

    }
}

animate_element();

Working fiddle http://jsfiddle.net/m7PWT/6/

Upvotes: 2

Views: 577

Answers (1)

John S
John S

Reputation: 21482

You were pretty close with what you had. You just had two mistakes:

(1) You should have stored off the result of $("div[class='needs_animation']:first") in a variable. Not only is that more efficient, but in this case, you do not want to re-execute that after you remove the class because you will get a different result.

(2) When you supplied the callback function to .animate(), you should not have included the parentheses after it. You were actually calling it.

Here is what the code could look like:

$('div').css("opacity", "0");
$('div').addClass('needs_animation');

(function animate_element(){
    var $div = $('div.needs_animation:first');
    if ($div.length) {
        $div.removeClass('needs_animation');
        $div.animate({ opacity: 1 }, 2000, animate_element);
    }
})();

jsfiddle

And one more thing: When selecting elements by class, use 'div.needs_animation', rather than 'div[class="needs_animation"]'. The former will work even if the elements have more than one class.

Upvotes: 3

Related Questions