mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Landing pull request 514. 1.7 - queue refactoring to handle delay stop - Fixes #6150.
More Details: - https://github.com/jquery/jquery/pull/514 - http://bugs.jquery.com/ticket/6150
This commit is contained in:
parent
a74cbb2b91
commit
a3b59d7f92
66
src/effects.js
vendored
66
src/effects.js
vendored
@ -200,6 +200,7 @@ jQuery.fn.extend({
|
||||
val = prop[ p ];
|
||||
|
||||
if ( rfxtypes.test( val ) ) {
|
||||
|
||||
// Tracks whether to show or hide based on private
|
||||
// data attached to the element
|
||||
method = jQuery._data( this, "toggle" + p ) || (val === "toggle" ? hidden ? "show" : "hide" : 0);
|
||||
@ -244,42 +245,62 @@ jQuery.fn.extend({
|
||||
|
||||
return optall.queue === false ?
|
||||
this.each( doAnimation ) :
|
||||
this.queue( optall.queue || "fx", doAnimation );
|
||||
this.queue( optall.queue, doAnimation );
|
||||
},
|
||||
|
||||
stop: function( clearQueue, gotoEnd ) {
|
||||
if ( clearQueue ) {
|
||||
this.queue([]);
|
||||
stop: function( clearQueue, gotoEnd, type ) {
|
||||
if ( clearQueue && type !== false ) {
|
||||
this.queue( type || "fx", [] );
|
||||
}
|
||||
|
||||
this.each(function() {
|
||||
var timers = jQuery.timers,
|
||||
i = timers.length;
|
||||
return this.each(function() {
|
||||
var i,
|
||||
hadTimers = false,
|
||||
timers = jQuery.timers,
|
||||
data = jQuery._data( this );
|
||||
|
||||
// clear marker counters if we know they won't be
|
||||
if ( !gotoEnd ) {
|
||||
jQuery._unmark( true, this );
|
||||
}
|
||||
while ( i-- ) {
|
||||
if ( timers[ i ].elem === this ) {
|
||||
|
||||
function stopQueue( elem, data, i ) {
|
||||
var runner = data[ i ];
|
||||
jQuery.removeData( elem, i, true );
|
||||
runner.stop( gotoEnd );
|
||||
}
|
||||
|
||||
if ( type == null ) {
|
||||
for ( i in data ) {
|
||||
if ( data[ i ].stop && i.indexOf(".run") === i.length - 4 ) {
|
||||
stopQueue( this, data, i );
|
||||
}
|
||||
}
|
||||
} else if ( data[ i = type + ".run" ] && data[ i ].stop ){
|
||||
stopQueue( this, data, i );
|
||||
}
|
||||
|
||||
for ( i = timers.length; i--; ) {
|
||||
if ( timers[ i ].elem === this && (type == null || timers[ i ].queue === type) ) {
|
||||
if ( gotoEnd ) {
|
||||
|
||||
// force the next step to be the last
|
||||
timers[ i ]( true );
|
||||
} else {
|
||||
timers[ i ].saveState();
|
||||
}
|
||||
|
||||
hadTimers = true;
|
||||
timers.splice( i, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// start the next in the queue if the last step wasn't forced
|
||||
// timers currently will call their complete callbacks, which will dequeue
|
||||
// but only if they were gotoEnd
|
||||
if ( !( gotoEnd && hadTimers ) ) {
|
||||
jQuery.dequeue( this, type );
|
||||
}
|
||||
});
|
||||
|
||||
// start the next in the queue if the last step wasn't forced
|
||||
if ( !gotoEnd ) {
|
||||
this.dequeue();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
@ -331,15 +352,21 @@ jQuery.extend({
|
||||
opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
|
||||
opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
|
||||
|
||||
// if undefined, set to fx
|
||||
if ( opt.queue == null ) {
|
||||
opt.queue = "fx";
|
||||
}
|
||||
|
||||
// Queueing
|
||||
opt.old = opt.complete;
|
||||
|
||||
opt.complete = function( noUnmark ) {
|
||||
if ( jQuery.isFunction( opt.old ) ) {
|
||||
opt.old.call( this );
|
||||
}
|
||||
|
||||
if ( opt.queue !== false ) {
|
||||
jQuery.dequeue( this, opt.queue || "fx" );
|
||||
if ( opt.queue ) {
|
||||
jQuery.dequeue( this, opt.queue );
|
||||
} else if ( noUnmark !== false ) {
|
||||
jQuery._unmark( this );
|
||||
}
|
||||
@ -408,6 +435,7 @@ jQuery.fx.prototype = {
|
||||
return self.step( gotoEnd );
|
||||
}
|
||||
|
||||
t.queue = this.options.queue;
|
||||
t.elem = this.elem;
|
||||
t.saveState = function() {
|
||||
if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
|
||||
|
22
src/queue.js
22
src/queue.js
@ -70,7 +70,8 @@ jQuery.extend({
|
||||
type = type || "fx";
|
||||
|
||||
var queue = jQuery.queue( elem, type ),
|
||||
fn = queue.shift();
|
||||
fn = queue.shift(),
|
||||
runner = {};
|
||||
|
||||
// If the fx queue is dequeued, always remove the progress sentinel
|
||||
if ( fn === "inprogress" ) {
|
||||
@ -81,16 +82,17 @@ jQuery.extend({
|
||||
// Add a progress sentinel to prevent the fx queue from being
|
||||
// automatically dequeued
|
||||
if ( type === "fx" ) {
|
||||
queue.unshift("inprogress");
|
||||
queue.unshift( "inprogress" );
|
||||
}
|
||||
|
||||
fn.call(elem, function() {
|
||||
jQuery._data( elem, type + ".run", runner );
|
||||
fn.call( elem, function() {
|
||||
jQuery.dequeue( elem, type );
|
||||
});
|
||||
}, runner );
|
||||
}
|
||||
|
||||
if ( !queue.length ) {
|
||||
jQuery.removeData( elem, type + "queue", true );
|
||||
jQuery.removeData( elem, type + "queue " + type + ".run", true );
|
||||
handleQueueMarkDefer( elem, type, "queue" );
|
||||
}
|
||||
}
|
||||
@ -125,11 +127,11 @@ jQuery.fn.extend({
|
||||
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
|
||||
type = type || "fx";
|
||||
|
||||
return this.queue( type, function() {
|
||||
var elem = this;
|
||||
setTimeout(function() {
|
||||
jQuery.dequeue( elem, type );
|
||||
}, time );
|
||||
return this.queue( type, function( next, runner ) {
|
||||
var timeout = setTimeout( next, time );
|
||||
runner.stop = function() {
|
||||
clearTimeout( timeout );
|
||||
};
|
||||
});
|
||||
},
|
||||
clearQueue: function( type ) {
|
||||
|
54
test/unit/effects.js
vendored
54
test/unit/effects.js
vendored
@ -357,9 +357,26 @@ test("animate option (queue === false)", function () {
|
||||
});
|
||||
*/
|
||||
|
||||
asyncTest( "animate option { queue: false }", function() {
|
||||
expect( 2 );
|
||||
var foo = jQuery( "#foo" );
|
||||
|
||||
foo.animate({
|
||||
fontSize: "2em"
|
||||
}, {
|
||||
queue: false,
|
||||
duration: 10,
|
||||
complete: function() {
|
||||
ok( true, "Animation Completed" );
|
||||
start();
|
||||
}
|
||||
});
|
||||
|
||||
equals( foo.queue().length, 0, "Queue is empty" );
|
||||
});
|
||||
|
||||
asyncTest( "animate option { queue: 'name' }", function() {
|
||||
expect( 5 );
|
||||
|
||||
var foo = jQuery( "#foo" ),
|
||||
origWidth = foo.width(),
|
||||
order = [];
|
||||
@ -608,6 +625,41 @@ test("stop(clearQueue, gotoEnd)", function() {
|
||||
}, 100);
|
||||
});
|
||||
|
||||
asyncTest( "stop( ..., ..., queue ) - Stop single queues", function() {
|
||||
expect( 3 );
|
||||
var foo = jQuery( "#foo" ),
|
||||
saved;
|
||||
|
||||
foo.width( 200 ).height( 200 );
|
||||
foo.animate({
|
||||
width: 400
|
||||
},{
|
||||
duration: 1000,
|
||||
complete: function() {
|
||||
equals( foo.width(), 400, "Animation completed for standard queue" );
|
||||
equals( foo.height(), saved, "Height was not changed after the second stop")
|
||||
start();
|
||||
}
|
||||
});
|
||||
|
||||
foo.animate({
|
||||
height: 400
|
||||
},{
|
||||
duration: 1000,
|
||||
queue: "height"
|
||||
}).dequeue( "height" ).stop( false, true, "height" );
|
||||
|
||||
equals( foo.height(), 400, "Height was stopped with gotoEnd" );
|
||||
|
||||
foo.animate({
|
||||
height: 200
|
||||
},{
|
||||
duration: 1000,
|
||||
queue: "height"
|
||||
}).dequeue( "height" ).stop( false, false, "height" );
|
||||
saved = foo.height();
|
||||
})
|
||||
|
||||
test("toggle()", function() {
|
||||
expect(6);
|
||||
var x = jQuery("#foo");
|
||||
|
@ -130,6 +130,44 @@ test("delay()", function() {
|
||||
equals( run, 0, "The delay delayed the next function from running." );
|
||||
});
|
||||
|
||||
test("delay() can be stopped", function() {
|
||||
expect( 3 );
|
||||
stop();
|
||||
|
||||
var foo = jQuery({}), run = 0;
|
||||
|
||||
foo
|
||||
.queue( "alternate", function( next ) {
|
||||
run++;
|
||||
ok( true, "This first function was dequeued" );
|
||||
next();
|
||||
})
|
||||
.delay( 100, "alternate" )
|
||||
.queue( "alternate", function() {
|
||||
run++;
|
||||
ok( true, "The function was dequeued immediately, the delay was stopped" );
|
||||
})
|
||||
.dequeue( "alternate" )
|
||||
|
||||
// stop( false ) will NOT clear the queue, so it should automatically dequeue the next
|
||||
.stop( false, false, "alternate" )
|
||||
|
||||
// this test
|
||||
.delay( 100 )
|
||||
.queue(function() {
|
||||
run++;
|
||||
ok( false, "This queue should never run" );
|
||||
})
|
||||
|
||||
// stop( clearQueue ) should clear the queue
|
||||
.stop( true, false );
|
||||
|
||||
equal( run, 2, "Queue ran the proper functions" );
|
||||
|
||||
setTimeout( start, 200 );
|
||||
});
|
||||
|
||||
|
||||
test("clearQueue(name) clears the queue", function() {
|
||||
expect(2);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user