mirror of
https://github.com/jquery/jquery.git
synced 2026-04-20 03:01:22 -04:00
Optimizations to animation queue/promise logic, closes gh-776.
This commit is contained in:
committed by
Dave Methvin
parent
ae20e732f0
commit
4621a0131b
125
src/queue.js
125
src/queue.js
@@ -1,68 +1,22 @@
|
||||
(function( jQuery ) {
|
||||
|
||||
function handleQueueMarkDefer( elem, type, src ) {
|
||||
var deferDataKey = type + "defer",
|
||||
queueDataKey = type + "queue",
|
||||
markDataKey = type + "mark",
|
||||
defer = jQuery._data( elem, deferDataKey );
|
||||
if ( defer &&
|
||||
( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
|
||||
( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
|
||||
// Give room for hard-coded callbacks to fire first
|
||||
// and eventually mark/queue something else on the element
|
||||
setTimeout( function() {
|
||||
if ( !jQuery._data( elem, queueDataKey ) &&
|
||||
!jQuery._data( elem, markDataKey ) ) {
|
||||
jQuery.removeData( elem, deferDataKey, true );
|
||||
defer.fire();
|
||||
}
|
||||
}, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
jQuery.extend({
|
||||
|
||||
_mark: function( elem, type ) {
|
||||
if ( elem ) {
|
||||
type = ( type || "fx" ) + "mark";
|
||||
jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
|
||||
}
|
||||
},
|
||||
|
||||
_unmark: function( force, elem, type ) {
|
||||
if ( force !== true ) {
|
||||
type = elem;
|
||||
elem = force;
|
||||
force = false;
|
||||
}
|
||||
if ( elem ) {
|
||||
type = type || "fx";
|
||||
var key = type + "mark",
|
||||
count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
|
||||
if ( count ) {
|
||||
jQuery._data( elem, key, count );
|
||||
} else {
|
||||
jQuery.removeData( elem, key, true );
|
||||
handleQueueMarkDefer( elem, type, "mark" );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
queue: function( elem, type, data ) {
|
||||
var q;
|
||||
var queue;
|
||||
|
||||
if ( elem ) {
|
||||
type = ( type || "fx" ) + "queue";
|
||||
q = jQuery._data( elem, type );
|
||||
queue = jQuery._data( elem, type );
|
||||
|
||||
// Speed up dequeue by getting out quickly if this is just a lookup
|
||||
if ( data ) {
|
||||
if ( !q || jQuery.isArray(data) ) {
|
||||
q = jQuery._data( elem, type, jQuery.makeArray(data) );
|
||||
if ( !queue || jQuery.isArray(data) ) {
|
||||
queue = jQuery._data( elem, type, jQuery.makeArray(data) );
|
||||
} else {
|
||||
q.push( data );
|
||||
queue.push( data );
|
||||
}
|
||||
}
|
||||
return q || [];
|
||||
return queue || [];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -71,7 +25,10 @@ jQuery.extend({
|
||||
|
||||
var queue = jQuery.queue( elem, type ),
|
||||
fn = queue.shift(),
|
||||
hooks = {};
|
||||
hooks = jQuery._queueHooks( elem, type ),
|
||||
next = function() {
|
||||
jQuery.dequeue( elem, type );
|
||||
};
|
||||
|
||||
// If the fx queue is dequeued, always remove the progress sentinel
|
||||
if ( fn === "inprogress" ) {
|
||||
@@ -79,22 +36,31 @@ jQuery.extend({
|
||||
}
|
||||
|
||||
if ( fn ) {
|
||||
|
||||
// Add a progress sentinel to prevent the fx queue from being
|
||||
// automatically dequeued
|
||||
if ( type === "fx" ) {
|
||||
queue.unshift( "inprogress" );
|
||||
}
|
||||
|
||||
jQuery._data( elem, type + ".run", hooks );
|
||||
fn.call( elem, function() {
|
||||
jQuery.dequeue( elem, type );
|
||||
}, hooks );
|
||||
// clear up the last queue stop function
|
||||
delete hooks.stop;
|
||||
fn.call( elem, next, hooks );
|
||||
}
|
||||
if ( !queue.length && hooks ) {
|
||||
hooks.empty.fire();
|
||||
}
|
||||
},
|
||||
|
||||
if ( !queue.length ) {
|
||||
jQuery.removeData( elem, type + "queue " + type + ".run", true );
|
||||
handleQueueMarkDefer( elem, type, "queue" );
|
||||
}
|
||||
// not intended for public consumption - generates a queueHooks object, or returns the current one
|
||||
_queueHooks: function( elem, type ) {
|
||||
var key = type + "queueHooks";
|
||||
return jQuery._data( elem, key ) || jQuery._data( elem, key, {
|
||||
empty: jQuery.Callbacks("once memory").add(function() {
|
||||
jQuery.removeData( elem, type + "queue", true );
|
||||
jQuery.removeData( elem, key, true );
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -117,6 +83,9 @@ jQuery.fn.extend({
|
||||
this.each(function() {
|
||||
var queue = jQuery.queue( this, type, data );
|
||||
|
||||
// ensure a hooks for this queue
|
||||
jQuery._queueHooks( this, type );
|
||||
|
||||
if ( type === "fx" && queue[0] !== "inprogress" ) {
|
||||
jQuery.dequeue( this, type );
|
||||
}
|
||||
@@ -146,31 +115,27 @@ jQuery.fn.extend({
|
||||
// Get a promise resolved when queues of a certain type
|
||||
// are emptied (fx is the type by default)
|
||||
promise: function( type, object ) {
|
||||
var tmp,
|
||||
count = 1,
|
||||
defer = jQuery.Deferred(),
|
||||
elements = this,
|
||||
i = this.length,
|
||||
resolve = function() {
|
||||
if ( !( --count ) ) {
|
||||
defer.resolveWith( elements, [ elements ] );
|
||||
}
|
||||
};
|
||||
|
||||
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",
|
||||
markDataKey = type + "mark",
|
||||
tmp;
|
||||
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 ], markDataKey, undefined, true ) ) &&
|
||||
jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
|
||||
if ( (tmp = jQuery._data( elements[ i ], type + "queueHooks" )) && tmp.empty ) {
|
||||
count++;
|
||||
tmp.add( resolve );
|
||||
tmp.empty.add( resolve );
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
|
||||
Reference in New Issue
Block a user