mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Fix #13103. Add .finish() method. Cherry picked from b6abb31df4
.
This commit is contained in:
parent
4e0bc169df
commit
c27d8e2988
59
src/effects.js
vendored
59
src/effects.js
vendored
@ -72,6 +72,7 @@ function createTweens( animation, props ) {
|
|||||||
|
|
||||||
function Animation( elem, properties, options ) {
|
function Animation( elem, properties, options ) {
|
||||||
var result,
|
var result,
|
||||||
|
stopped,
|
||||||
index = 0,
|
index = 0,
|
||||||
length = animationPrefilters.length,
|
length = animationPrefilters.length,
|
||||||
deferred = jQuery.Deferred().always( function() {
|
deferred = jQuery.Deferred().always( function() {
|
||||||
@ -79,6 +80,9 @@ function Animation( elem, properties, options ) {
|
|||||||
delete tick.elem;
|
delete tick.elem;
|
||||||
}),
|
}),
|
||||||
tick = function() {
|
tick = function() {
|
||||||
|
if ( stopped ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var currentTime = fxNow || createFxNow(),
|
var currentTime = fxNow || createFxNow(),
|
||||||
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
|
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
|
||||||
// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
|
// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
|
||||||
@ -120,7 +124,10 @@ function Animation( elem, properties, options ) {
|
|||||||
// if we are going to the end, we want to run all the tweens
|
// if we are going to the end, we want to run all the tweens
|
||||||
// otherwise we skip this part
|
// otherwise we skip this part
|
||||||
length = gotoEnd ? animation.tweens.length : 0;
|
length = gotoEnd ? animation.tweens.length : 0;
|
||||||
|
if ( stopped ) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
stopped = true;
|
||||||
for ( ; index < length ; index++ ) {
|
for ( ; index < length ; index++ ) {
|
||||||
animation.tweens[ index ].run( 1 );
|
animation.tweens[ index ].run( 1 );
|
||||||
}
|
}
|
||||||
@ -477,12 +484,15 @@ jQuery.fn.extend({
|
|||||||
doAnimation = function() {
|
doAnimation = function() {
|
||||||
// Operate on a copy of prop so per-property easing won't be lost
|
// Operate on a copy of prop so per-property easing won't be lost
|
||||||
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
|
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
|
||||||
|
doAnimation.finish = function() {
|
||||||
// Empty animations resolve immediately
|
anim.stop( true );
|
||||||
if ( empty ) {
|
};
|
||||||
|
// Empty animations, or finishing resolves immediately
|
||||||
|
if ( empty || jQuery._data( this, "finish" ) ) {
|
||||||
anim.stop( true );
|
anim.stop( true );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
doAnimation.finish = doAnimation;
|
||||||
|
|
||||||
return empty || optall.queue === false ?
|
return empty || optall.queue === false ?
|
||||||
this.each( doAnimation ) :
|
this.each( doAnimation ) :
|
||||||
@ -537,6 +547,47 @@ jQuery.fn.extend({
|
|||||||
jQuery.dequeue( this, type );
|
jQuery.dequeue( this, type );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
finish: function( type ) {
|
||||||
|
if ( type !== false ) {
|
||||||
|
type = type || "fx";
|
||||||
|
}
|
||||||
|
return this.each(function() {
|
||||||
|
var index,
|
||||||
|
data = jQuery._data( this ),
|
||||||
|
queue = data[ type + "queue" ],
|
||||||
|
hooks = data[ type + "queueHooks" ],
|
||||||
|
timers = jQuery.timers,
|
||||||
|
length = queue ? queue.length : 0;
|
||||||
|
|
||||||
|
// enable finishing flag on private data
|
||||||
|
data.finish = true;
|
||||||
|
|
||||||
|
// empty the queue first
|
||||||
|
jQuery.queue( this, type, [] );
|
||||||
|
|
||||||
|
if ( hooks && hooks.cur && hooks.cur.finish ) {
|
||||||
|
hooks.cur.finish.call( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for any active animations, and finish them
|
||||||
|
for ( index = timers.length; index--; ) {
|
||||||
|
if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
|
||||||
|
timers[ index ].anim.stop( true );
|
||||||
|
timers.splice( index, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for any animations in the old queue and finish them
|
||||||
|
for ( index = 0; index < length; index++ ) {
|
||||||
|
if ( queue[ index ] && queue[ index ].finish ) {
|
||||||
|
queue[ index ].finish.call( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// turn off finishing flag
|
||||||
|
delete data.finish;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ jQuery.extend({
|
|||||||
startLength--;
|
startLength--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hooks.cur = fn;
|
||||||
if ( fn ) {
|
if ( fn ) {
|
||||||
|
|
||||||
// Add a progress sentinel to prevent the fx queue from being
|
// Add a progress sentinel to prevent the fx queue from being
|
||||||
|
49
test/unit/effects.js
vendored
49
test/unit/effects.js
vendored
@ -1904,4 +1904,53 @@ test( "jQuery.fx.start & jQuery.fx.stop hook points", function() {
|
|||||||
jQuery.fx.stop = oldStop;
|
jQuery.fx.stop = oldStop;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test( ".finish() completes all queued animations", function() {
|
||||||
|
var animations = {
|
||||||
|
top: 100,
|
||||||
|
left: 100,
|
||||||
|
height: 100,
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
div = jQuery("<div>");
|
||||||
|
|
||||||
|
expect( 11 );
|
||||||
|
|
||||||
|
jQuery.each( animations, function( prop, value ) {
|
||||||
|
var anim = {};
|
||||||
|
anim[ prop ] = value;
|
||||||
|
// the delay shouldn't matter at all!
|
||||||
|
div.css( prop, 1 ).animate( anim, function() {
|
||||||
|
ok( true, "Called animation callback" );
|
||||||
|
}).delay( 100 );
|
||||||
|
});
|
||||||
|
equal( div.queue().length, 8, "8 animations in the queue" );
|
||||||
|
div.finish();
|
||||||
|
jQuery.each( animations, function( prop, value ) {
|
||||||
|
equal( parseFloat( div.css( prop ) ), value, prop + " finished at correct value" );
|
||||||
|
});
|
||||||
|
equal( div.queue().length, 0, "empty queue when done" );
|
||||||
|
equal( div.is(":animated"), false, ":animated doesn't match" );
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
div.remove();
|
||||||
|
// leaves a "shadow timer" which does nothing around, need to force a tick
|
||||||
|
jQuery.fx.tick();
|
||||||
|
});
|
||||||
|
|
||||||
|
test( ".finish() calls finish of custom queue functions", function() {
|
||||||
|
function queueTester( next ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var div = jQuery( "<div>" );
|
||||||
|
|
||||||
|
expect( 3 );
|
||||||
|
queueTester.finish = function() {
|
||||||
|
ok( true, "Finish called on custom queue function" );
|
||||||
|
};
|
||||||
|
|
||||||
|
div.queue( queueTester ).queue( queueTester ).queue( queueTester ).finish();
|
||||||
|
|
||||||
|
div.remove();
|
||||||
|
});
|
||||||
|
|
||||||
} // if ( jQuery.fx )
|
} // if ( jQuery.fx )
|
||||||
|
Loading…
Reference in New Issue
Block a user