Adds fn.promise as a mean to observe the completion of animations on a set of elements. Only queued animations are handled for now, non-queued animations support coming soon. Effects unit tests updated to test the feature (needs more testing though).

This commit is contained in:
jaubourg 2011-04-07 06:00:52 +02:00
parent bb99899ca0
commit 4552d135f4
2 changed files with 67 additions and 19 deletions

View file

@ -28,7 +28,8 @@ jQuery.extend({
type = type || "fx";
var queue = jQuery.queue( elem, type ),
fn = queue.shift();
fn = queue.shift(),
defer;
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
@ -49,6 +50,17 @@ jQuery.extend({
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true );
// Look if we have observers and resolve if needed
if (( defer = jQuery.data( elem, type + "defer", undefined, true ) )) {
// Give room for hard-coded callbacks to fire first
// and eventually add another animation on the element
setTimeout( function() {
if ( !jQuery.data( elem, type + "queue", undefined, true ) ) {
jQuery.removeData( elem, type + "defer", true );
defer.resolve();
}
}, 0 );
}
}
}
});
@ -93,6 +105,37 @@ jQuery.fn.extend({
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// Get a promise resolved when queues of a certain type
// are emptied (fx is the type by default)
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
type = undefined;
}
type = type || "fx";
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type + "defer",
queueDataKey = type + "queue";
function resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
jQuery.data( elements[ i ], queueDataKey, undefined, true ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
count++;
tmp.done( resolve );
}
}
resolve();
return defer.promise();
}
});