Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jquery .when with multiple animations

i'm new to jquery and to js so maybe it is a stupid question.

I have two animations:

$(foo2).fadeOut(1000);
$(foo1).fadeOut(2000);

and i want a callback called when they have finished in some elegant way (scalable to any number of animation with different - and not known duration - possibly using .when)

till now i call .when only in the longest animation:

function different_animation() {

  effect = function() {

   foo1 = 'div'; //this is an example that selects multiple elements
   foo2 = 'p'; //this is an example that selects multiple elements

    var ret1 = $(foo1).fadeOut(1000);
    var ret2 = $(foo2).fadeOut(2000);

    var seconds = new Date().getTime() / 1000;
    console.log('fade out at'+seconds);

    // i know that to ret2 there is attached a longer animation is longer then ret1
    return ret2; 
  }

  $.when( effect() ).done(function() {
    var seconds = new Date().getTime() / 1000;
    console.log('done at '+seconds);
  });
}

but what if there are more animation and i don't know the timing of each ones? i need something that could join the rets.

like image 890
nkint Avatar asked Mar 06 '26 21:03

nkint


2 Answers

You can do this by leveraging $.Deferred and the callback functionality of fadeOut:

var deferred1 = $.Deferred();
var deferred2 = $.Deferred();
$(foo1).fadeOut(1000, function() { deferred1.resolve(); } );
$(foo2).fadeOut(2000, function() { deferred2.resolve(); } );

$.when(deferred1, deferred2).done(function() {
    console.log("both animations have completed");
});

This can easily scale to any number of animations (and promises in general). You can place as many promises or deferreds into an array and use

$.when.apply(null, arrayOfPromises).done(callback);

to fire callback when all of them are completed.

See it in action.

like image 66
Jon Avatar answered Mar 08 '26 12:03

Jon


The .animate() and other effect methods of jQuery returns an object usable in the .when() method, so it's not necessary to manually create and resolve the deferred objects.

var promises = [];
promises.push($("#foo1").fadeOut(1000));
promises.push($("#foo2").fadeOut(2000));
$.when.apply(null, promises).done(function() { /* all done */ }); 

As can be seen in this version of Jons jsfiddle: http://jsfiddle.net/2sJVX/55/

like image 37
Torin Finnemann Avatar answered Mar 08 '26 10:03

Torin Finnemann