Pablo
Pablo

Reputation: 29519

How to group 2 jQuery animation's complete callbacks?

My function has different paths of execution, where one or multiple .animate jQuery methods might be called. These animation should start at the same time and shouldn't be serialized. For example:

function moveDown()
{
    busy = true;
    if(some condition)
    {
        $(".selFrame").animate({top: $("#row" + currentSelRowIndex).offset().top});
    }
    else
    {
        $(".container").animate({scrollTop: $("#row" + currentRowIndex).offset().top - $("#row0").offset().top});
        $(".selFrame").animate({top: ($(".selFrame").offset().top + ch - remaining)});
    }
}

My goal is not detect using some busy variable whether all animations have been finished, no matter through which exacution path we went. For one animation call it's easy to reset busy variable on animation complete. However, I'm not sure how to combine 2 or more animations into one event, where I can reset busy variable, to make sure that all animations are completed.

UPDATE

Unfortunately filtering solution didn't gave good results after thorough testing.

document.addEventListener('keydown', function(e) {
    var runningAnimations = $(".container, .selFrame").filter(":animated").length;
    if(runningAnimations == 0)
    {
        switch(e.keyCode)
        {
        case 40: 
            moveDown();
            break;

It works much better than without, but sometimes, on double animation cases allowing re-entrance.

I'm going to try second method with promise.

Upvotes: 1

Views: 120

Answers (2)

KAD
KAD

Reputation: 11122

You can use an integer holding the number of animations and subtract one on the callback of each animation or check if its value is 1:

    if(some condition)
    {
        busy = 1;
        $(".selFrame").animate({top: $("#row" + currentSelRowIndex).offset().top} , function(){
             busy--;
        });
    }
    else
    {
        busy = 2;
        $(".container").animate({scrollTop: $("#row" + currentRowIndex).offset().top - $("#row0").offset().top}, function(){
             if(busy == 1) // all the animations have ended
             busy--;
        });

        $(".selFrame").animate({top: ($(".selFrame").offset().top + ch - remaining), function(){
             if(busy == 1) // all the animations have ended
             busy--;
        }});
    }

You can also use the :animated selector with setTimeOut:

setTimeOut(function(){
    var runningAnimations = $( ".container, .selFrame" ).filter( ":animated" ).length;
   }, 500);

Upvotes: 1

Denys Séguret
Denys Séguret

Reputation: 382334

When you want to be notified when all animations related to a collection of elements have finished, you may use promise:

$(".container, .selFrame").promise().then(function(){
      // all finished
      // we may change a boolean but usually we would call a callback
});

This can for example come just after your if/else.

Upvotes: 1

Related Questions