2015-08-16 06:59:58 +00:00
|
|
|
define( [
|
2013-10-15 14:40:48 +00:00
|
|
|
"./core",
|
2017-11-22 19:43:44 +00:00
|
|
|
"./core/camelCase",
|
2014-09-11 20:18:34 +00:00
|
|
|
"./var/document",
|
2017-12-13 06:43:30 +00:00
|
|
|
"./var/isFunction",
|
2015-02-04 13:10:14 +00:00
|
|
|
"./var/rcssNum",
|
2016-09-12 16:32:02 +00:00
|
|
|
"./var/rnothtmlwhite",
|
2013-10-15 14:40:48 +00:00
|
|
|
"./css/var/cssExpand",
|
2016-01-20 18:20:58 +00:00
|
|
|
"./css/var/isHiddenWithinTree",
|
2015-02-04 13:10:14 +00:00
|
|
|
"./css/adjustCSS",
|
2014-07-17 17:25:59 +00:00
|
|
|
"./data/var/dataPriv",
|
2015-04-02 20:57:33 +00:00
|
|
|
"./css/showHide",
|
2013-08-15 18:15:49 +00:00
|
|
|
|
2013-10-15 14:40:48 +00:00
|
|
|
"./core/init",
|
|
|
|
"./queue",
|
|
|
|
"./deferred",
|
2015-04-02 20:57:33 +00:00
|
|
|
"./traversing",
|
|
|
|
"./manipulation",
|
|
|
|
"./css",
|
|
|
|
"./effects/Tween"
|
2017-12-13 06:43:30 +00:00
|
|
|
], function( jQuery, camelCase, document, isFunction, rcssNum, rnothtmlwhite, cssExpand,
|
2019-05-13 20:25:11 +00:00
|
|
|
isHiddenWithinTree, adjustCSS, dataPriv, showHide ) {
|
2013-09-10 19:57:14 +00:00
|
|
|
|
2016-04-25 18:25:08 +00:00
|
|
|
"use strict";
|
|
|
|
|
2013-10-15 14:40:48 +00:00
|
|
|
var
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
fxNow, inProgress,
|
2010-09-22 13:16:28 +00:00
|
|
|
rfxtypes = /^(?:toggle|show|hide)$/,
|
2015-05-19 21:48:42 +00:00
|
|
|
rrun = /queueHooks$/;
|
2010-10-26 21:37:44 +00:00
|
|
|
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
function schedule() {
|
|
|
|
if ( inProgress ) {
|
|
|
|
if ( document.hidden === false && window.requestAnimationFrame ) {
|
|
|
|
window.requestAnimationFrame( schedule );
|
|
|
|
} else {
|
|
|
|
window.setTimeout( schedule, jQuery.fx.interval );
|
|
|
|
}
|
|
|
|
|
2014-05-09 00:21:42 +00:00
|
|
|
jQuery.fx.tick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
// Animations created synchronously will run synchronously
|
|
|
|
function createFxNow() {
|
2015-08-16 06:59:58 +00:00
|
|
|
window.setTimeout( function() {
|
2012-04-23 19:05:12 +00:00
|
|
|
fxNow = undefined;
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2017-12-11 17:39:11 +00:00
|
|
|
return ( fxNow = Date.now() );
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
2010-10-26 21:37:44 +00:00
|
|
|
|
2013-09-09 16:13:41 +00:00
|
|
|
// Generate parameters to create a standard animation
|
|
|
|
function genFx( type, includeWidth ) {
|
|
|
|
var which,
|
2013-11-06 05:23:04 +00:00
|
|
|
i = 0,
|
|
|
|
attrs = { height: type };
|
2013-09-09 16:13:41 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// If we include width, step value is 1 to do all cssExpand values,
|
|
|
|
// otherwise step value is 2 to skip over Left and Right
|
2013-09-10 19:57:14 +00:00
|
|
|
includeWidth = includeWidth ? 1 : 0;
|
2016-05-10 09:12:28 +00:00
|
|
|
for ( ; i < 4; i += 2 - includeWidth ) {
|
2013-09-09 16:13:41 +00:00
|
|
|
which = cssExpand[ i ];
|
|
|
|
attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( includeWidth ) {
|
|
|
|
attrs.opacity = attrs.width = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
return attrs;
|
|
|
|
}
|
|
|
|
|
2013-05-09 02:56:51 +00:00
|
|
|
function createTween( value, prop, animation ) {
|
|
|
|
var tween,
|
2015-05-19 21:48:42 +00:00
|
|
|
collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
|
2013-05-09 02:56:51 +00:00
|
|
|
index = 0,
|
|
|
|
length = collection.length;
|
|
|
|
for ( ; index < length; index++ ) {
|
2015-08-16 06:59:58 +00:00
|
|
|
if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
|
2012-05-18 17:48:24 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// We're done with this property
|
2013-05-09 02:56:51 +00:00
|
|
|
return tween;
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
2013-05-09 02:56:51 +00:00
|
|
|
}
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
2011-04-17 18:07:42 +00:00
|
|
|
|
2013-09-09 16:13:41 +00:00
|
|
|
function defaultPrefilter( elem, props, opts ) {
|
2015-04-02 20:57:33 +00:00
|
|
|
var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
|
|
|
|
isBox = "width" in props || "height" in props,
|
2013-09-09 16:13:41 +00:00
|
|
|
anim = this,
|
|
|
|
orig = {},
|
|
|
|
style = elem.style,
|
2016-01-20 18:20:58 +00:00
|
|
|
hidden = elem.nodeType && isHiddenWithinTree( elem ),
|
2014-07-17 17:25:59 +00:00
|
|
|
dataShow = dataPriv.get( elem, "fxshow" );
|
2013-09-09 16:13:41 +00:00
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Queue-skipping animations hijack the fx hooks
|
2013-09-09 16:13:41 +00:00
|
|
|
if ( !opts.queue ) {
|
|
|
|
hooks = jQuery._queueHooks( elem, "fx" );
|
|
|
|
if ( hooks.unqueued == null ) {
|
|
|
|
hooks.unqueued = 0;
|
|
|
|
oldfire = hooks.empty.fire;
|
|
|
|
hooks.empty.fire = function() {
|
|
|
|
if ( !hooks.unqueued ) {
|
|
|
|
oldfire();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
hooks.unqueued++;
|
|
|
|
|
2015-08-16 06:59:58 +00:00
|
|
|
anim.always( function() {
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Ensure the complete handler is called before this completes
|
2015-08-16 06:59:58 +00:00
|
|
|
anim.always( function() {
|
2013-09-09 16:13:41 +00:00
|
|
|
hooks.unqueued--;
|
|
|
|
if ( !jQuery.queue( elem, "fx" ).length ) {
|
|
|
|
hooks.empty.fire();
|
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
|
|
|
} );
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Detect show/hide animations
|
|
|
|
for ( prop in props ) {
|
|
|
|
value = props[ prop ];
|
|
|
|
if ( rfxtypes.test( value ) ) {
|
|
|
|
delete props[ prop ];
|
|
|
|
toggle = toggle || value === "toggle";
|
|
|
|
if ( value === ( hidden ? "hide" : "show" ) ) {
|
|
|
|
|
|
|
|
// Pretend to be hidden if this is a "show" and
|
|
|
|
// there is still data from a stopped show/hide
|
|
|
|
if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
|
|
|
|
hidden = true;
|
|
|
|
|
|
|
|
// Ignore all other no-op show/hide data
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bail out if this is a no-op like .hide().hide()
|
|
|
|
propTween = !jQuery.isEmptyObject( props );
|
|
|
|
if ( !propTween && jQuery.isEmptyObject( orig ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restrict "overflow" and "display" styles during box animations
|
|
|
|
if ( isBox && elem.nodeType === 1 ) {
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2017-05-15 18:37:14 +00:00
|
|
|
// Support: IE <=9 - 11, Edge 12 - 15
|
2015-04-02 20:57:33 +00:00
|
|
|
// Record all 3 overflow attributes because IE does not infer the shorthand
|
2017-05-15 18:37:14 +00:00
|
|
|
// from identically-valued overflowX and overflowY and Edge just mirrors
|
|
|
|
// the overflowX value there.
|
2013-09-09 16:13:41 +00:00
|
|
|
opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
|
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Identify a display type, preferring old show/hide data over the CSS cascade
|
|
|
|
restoreDisplay = dataShow && dataShow.display;
|
|
|
|
if ( restoreDisplay == null ) {
|
|
|
|
restoreDisplay = dataPriv.get( elem, "display" );
|
|
|
|
}
|
2013-09-10 19:57:14 +00:00
|
|
|
display = jQuery.css( elem, "display" );
|
2015-04-02 20:57:33 +00:00
|
|
|
if ( display === "none" ) {
|
2016-01-11 07:26:55 +00:00
|
|
|
if ( restoreDisplay ) {
|
|
|
|
display = restoreDisplay;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Get nonempty value(s) by temporarily forcing visibility
|
|
|
|
showHide( [ elem ], true );
|
|
|
|
restoreDisplay = elem.style.display || restoreDisplay;
|
|
|
|
display = jQuery.css( elem, "display" );
|
|
|
|
showHide( [ elem ] );
|
|
|
|
}
|
2015-04-02 20:57:33 +00:00
|
|
|
}
|
2014-04-26 17:24:05 +00:00
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Animate inline elements as inline-block
|
|
|
|
if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
|
|
|
|
if ( jQuery.css( elem, "float" ) === "none" ) {
|
|
|
|
|
|
|
|
// Restore the original display value at the end of pure show/hide animations
|
|
|
|
if ( !propTween ) {
|
2015-08-16 06:59:58 +00:00
|
|
|
anim.done( function() {
|
2015-04-02 20:57:33 +00:00
|
|
|
style.display = restoreDisplay;
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2015-04-02 20:57:33 +00:00
|
|
|
if ( restoreDisplay == null ) {
|
|
|
|
display = style.display;
|
|
|
|
restoreDisplay = display === "none" ? "" : display;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
style.display = "inline-block";
|
|
|
|
}
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( opts.overflow ) {
|
|
|
|
style.overflow = "hidden";
|
2015-08-16 06:59:58 +00:00
|
|
|
anim.always( function() {
|
2013-09-09 16:13:41 +00:00
|
|
|
style.overflow = opts.overflow[ 0 ];
|
|
|
|
style.overflowX = opts.overflow[ 1 ];
|
|
|
|
style.overflowY = opts.overflow[ 2 ];
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Implement show/hide animations
|
|
|
|
propTween = false;
|
|
|
|
for ( prop in orig ) {
|
2013-09-09 16:13:41 +00:00
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// General show/hide setup for this element animation
|
|
|
|
if ( !propTween ) {
|
|
|
|
if ( dataShow ) {
|
|
|
|
if ( "hidden" in dataShow ) {
|
|
|
|
hidden = dataShow.hidden;
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
2015-04-02 20:57:33 +00:00
|
|
|
} else {
|
|
|
|
dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
2014-03-20 07:39:36 +00:00
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
|
|
|
|
if ( toggle ) {
|
|
|
|
dataShow.hidden = !hidden;
|
|
|
|
}
|
2013-09-09 16:13:41 +00:00
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Show elements before animating them
|
|
|
|
if ( hidden ) {
|
|
|
|
showHide( [ elem ], true );
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 09:12:28 +00:00
|
|
|
/* eslint-disable no-loop-func */
|
|
|
|
|
2015-08-16 06:59:58 +00:00
|
|
|
anim.done( function() {
|
|
|
|
|
2020-05-05 08:49:27 +00:00
|
|
|
/* eslint-enable no-loop-func */
|
2016-05-10 09:12:28 +00:00
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// The final step of a "hide" animation is actually hiding the element
|
|
|
|
if ( !hidden ) {
|
|
|
|
showHide( [ elem ] );
|
|
|
|
}
|
|
|
|
dataPriv.remove( elem, "fxshow" );
|
|
|
|
for ( prop in orig ) {
|
|
|
|
jQuery.style( elem, prop, orig[ prop ] );
|
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
|
|
|
|
2015-04-02 20:57:33 +00:00
|
|
|
// Per-property setup
|
|
|
|
propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
|
|
|
|
if ( !( prop in dataShow ) ) {
|
|
|
|
dataShow[ prop ] = propTween.start;
|
|
|
|
if ( hidden ) {
|
|
|
|
propTween.end = propTween.start;
|
2016-01-19 18:48:05 +00:00
|
|
|
propTween.start = 0;
|
2013-09-09 16:13:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function propFilter( props, specialEasing ) {
|
|
|
|
var index, name, easing, value, hooks;
|
|
|
|
|
|
|
|
// camelCase, specialEasing and expand cssHook pass
|
|
|
|
for ( index in props ) {
|
2017-11-22 19:43:44 +00:00
|
|
|
name = camelCase( index );
|
2013-09-09 16:13:41 +00:00
|
|
|
easing = specialEasing[ name ];
|
|
|
|
value = props[ index ];
|
2016-08-14 10:54:16 +00:00
|
|
|
if ( Array.isArray( value ) ) {
|
2013-09-09 16:13:41 +00:00
|
|
|
easing = value[ 1 ];
|
|
|
|
value = props[ index ] = value[ 0 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( index !== name ) {
|
|
|
|
props[ name ] = value;
|
|
|
|
delete props[ index ];
|
|
|
|
}
|
|
|
|
|
|
|
|
hooks = jQuery.cssHooks[ name ];
|
|
|
|
if ( hooks && "expand" in hooks ) {
|
|
|
|
value = hooks.expand( value );
|
|
|
|
delete props[ name ];
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Not quite $.extend, this won't overwrite existing keys.
|
|
|
|
// Reusing 'index' because we have the correct "name"
|
2013-09-09 16:13:41 +00:00
|
|
|
for ( index in value ) {
|
|
|
|
if ( !( index in props ) ) {
|
|
|
|
props[ index ] = value[ index ];
|
|
|
|
specialEasing[ index ] = easing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
specialEasing[ name ] = easing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
function Animation( elem, properties, options ) {
|
|
|
|
var result,
|
2013-01-08 01:16:50 +00:00
|
|
|
stopped,
|
2012-04-23 19:05:12 +00:00
|
|
|
index = 0,
|
2015-05-19 21:48:42 +00:00
|
|
|
length = Animation.prefilters.length,
|
2012-06-22 20:03:39 +00:00
|
|
|
deferred = jQuery.Deferred().always( function() {
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Don't match elem in the :animated selector
|
2012-05-18 17:48:24 +00:00
|
|
|
delete tick.elem;
|
2015-08-16 06:59:58 +00:00
|
|
|
} ),
|
2012-05-18 17:48:24 +00:00
|
|
|
tick = function() {
|
2013-01-08 01:16:50 +00:00
|
|
|
if ( stopped ) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-05-18 17:48:24 +00:00
|
|
|
var currentTime = fxNow || createFxNow(),
|
|
|
|
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2016-03-23 14:03:06 +00:00
|
|
|
// Support: Android 2.3 only
|
2022-01-12 22:23:10 +00:00
|
|
|
// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497)
|
2012-11-08 03:29:55 +00:00
|
|
|
temp = remaining / animation.duration || 0,
|
|
|
|
percent = 1 - temp,
|
2012-05-18 17:48:24 +00:00
|
|
|
index = 0,
|
|
|
|
length = animation.tweens.length;
|
|
|
|
|
2016-05-10 09:12:28 +00:00
|
|
|
for ( ; index < length; index++ ) {
|
2012-05-18 17:48:24 +00:00
|
|
|
animation.tweens[ index ].run( percent );
|
|
|
|
}
|
|
|
|
|
2015-08-16 06:59:58 +00:00
|
|
|
deferred.notifyWith( elem, [ animation, percent, remaining ] );
|
2012-06-23 21:50:57 +00:00
|
|
|
|
2017-01-16 18:18:49 +00:00
|
|
|
// If there's more to do, yield
|
2012-05-18 17:48:24 +00:00
|
|
|
if ( percent < 1 && length ) {
|
|
|
|
return remaining;
|
|
|
|
}
|
2017-01-16 18:18:49 +00:00
|
|
|
|
|
|
|
// If this was an empty animation, synthesize a final progress notification
|
|
|
|
if ( !length ) {
|
|
|
|
deferred.notifyWith( elem, [ animation, 1, 0 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve the animation and report its conclusion
|
|
|
|
deferred.resolveWith( elem, [ animation ] );
|
|
|
|
return false;
|
2012-05-18 17:48:24 +00:00
|
|
|
},
|
2015-08-16 06:59:58 +00:00
|
|
|
animation = deferred.promise( {
|
2012-04-23 19:05:12 +00:00
|
|
|
elem: elem,
|
2012-05-11 20:20:32 +00:00
|
|
|
props: jQuery.extend( {}, properties ),
|
2015-05-05 17:24:20 +00:00
|
|
|
opts: jQuery.extend( true, {
|
|
|
|
specialEasing: {},
|
|
|
|
easing: jQuery.easing._default
|
|
|
|
}, options ),
|
2012-04-23 19:05:12 +00:00
|
|
|
originalProperties: properties,
|
|
|
|
originalOptions: options,
|
|
|
|
startTime: fxNow || createFxNow(),
|
|
|
|
duration: options.duration,
|
|
|
|
tweens: [],
|
2012-10-17 16:50:12 +00:00
|
|
|
createTween: function( prop, end ) {
|
2012-04-23 19:05:12 +00:00
|
|
|
var tween = jQuery.Tween( elem, animation.opts, prop, end,
|
2020-05-05 08:49:27 +00:00
|
|
|
animation.opts.specialEasing[ prop ] || animation.opts.easing );
|
2012-04-23 19:05:12 +00:00
|
|
|
animation.tweens.push( tween );
|
|
|
|
return tween;
|
|
|
|
},
|
|
|
|
stop: function( gotoEnd ) {
|
|
|
|
var index = 0,
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// If we are going to the end, we want to run all the tweens
|
2012-04-23 19:05:12 +00:00
|
|
|
// otherwise we skip this part
|
|
|
|
length = gotoEnd ? animation.tweens.length : 0;
|
2013-01-08 01:16:50 +00:00
|
|
|
if ( stopped ) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
stopped = true;
|
2016-05-10 09:12:28 +00:00
|
|
|
for ( ; index < length; index++ ) {
|
2012-04-23 19:05:12 +00:00
|
|
|
animation.tweens[ index ].run( 1 );
|
2009-02-09 15:58:12 +00:00
|
|
|
}
|
2012-06-22 20:03:39 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Resolve when we played the last frame; otherwise, reject
|
2012-06-22 20:03:39 +00:00
|
|
|
if ( gotoEnd ) {
|
2015-05-10 23:39:26 +00:00
|
|
|
deferred.notifyWith( elem, [ animation, 1, 0 ] );
|
2012-06-22 20:03:39 +00:00
|
|
|
deferred.resolveWith( elem, [ animation, gotoEnd ] );
|
|
|
|
} else {
|
|
|
|
deferred.rejectWith( elem, [ animation, gotoEnd ] );
|
|
|
|
}
|
2012-04-23 19:05:12 +00:00
|
|
|
return this;
|
2009-02-16 21:20:51 +00:00
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
} ),
|
2012-04-23 19:05:12 +00:00
|
|
|
props = animation.props;
|
2009-02-09 15:58:12 +00:00
|
|
|
|
2012-05-11 20:20:32 +00:00
|
|
|
propFilter( props, animation.opts.specialEasing );
|
2010-10-26 21:37:44 +00:00
|
|
|
|
2016-05-10 09:12:28 +00:00
|
|
|
for ( ; index < length; index++ ) {
|
2015-05-19 21:48:42 +00:00
|
|
|
result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
|
2012-04-23 19:05:12 +00:00
|
|
|
if ( result ) {
|
2017-12-13 06:43:30 +00:00
|
|
|
if ( isFunction( result.stop ) ) {
|
2015-05-19 21:48:42 +00:00
|
|
|
jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
|
2017-12-11 17:58:35 +00:00
|
|
|
result.stop.bind( result );
|
2015-05-19 21:48:42 +00:00
|
|
|
}
|
2012-04-23 19:05:12 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2011-04-17 18:07:42 +00:00
|
|
|
|
2013-05-09 02:56:51 +00:00
|
|
|
jQuery.map( props, createTween, animation );
|
2012-06-22 20:03:39 +00:00
|
|
|
|
2017-12-13 06:43:30 +00:00
|
|
|
if ( isFunction( animation.opts.start ) ) {
|
2012-06-22 20:03:39 +00:00
|
|
|
animation.opts.start.call( elem, animation );
|
|
|
|
}
|
2009-03-23 01:55:17 +00:00
|
|
|
|
2017-01-16 18:18:49 +00:00
|
|
|
// Attach callbacks from options
|
|
|
|
animation
|
|
|
|
.progress( animation.opts.progress )
|
|
|
|
.done( animation.opts.done, animation.opts.complete )
|
|
|
|
.fail( animation.opts.fail )
|
|
|
|
.always( animation.opts.always );
|
|
|
|
|
2012-05-18 17:48:24 +00:00
|
|
|
jQuery.fx.timer(
|
|
|
|
jQuery.extend( tick, {
|
2013-01-12 22:11:07 +00:00
|
|
|
elem: elem,
|
2012-05-18 17:48:24 +00:00
|
|
|
anim: animation,
|
2013-01-12 22:11:07 +00:00
|
|
|
queue: animation.opts.queue
|
2015-08-16 06:59:58 +00:00
|
|
|
} )
|
2012-05-18 17:48:24 +00:00
|
|
|
);
|
2012-06-22 20:03:39 +00:00
|
|
|
|
2017-01-16 18:18:49 +00:00
|
|
|
return animation;
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
2009-12-18 16:16:26 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
jQuery.Animation = jQuery.extend( Animation, {
|
|
|
|
|
2015-05-19 21:48:42 +00:00
|
|
|
tweeners: {
|
|
|
|
"*": [ function( prop, value ) {
|
|
|
|
var tween = this.createTween( prop, value );
|
|
|
|
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
|
|
|
|
return tween;
|
|
|
|
} ]
|
|
|
|
},
|
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
tweener: function( props, callback ) {
|
2017-12-13 06:43:30 +00:00
|
|
|
if ( isFunction( props ) ) {
|
2012-04-23 19:05:12 +00:00
|
|
|
callback = props;
|
|
|
|
props = [ "*" ];
|
|
|
|
} else {
|
2016-09-12 16:32:02 +00:00
|
|
|
props = props.match( rnothtmlwhite );
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var prop,
|
|
|
|
index = 0,
|
|
|
|
length = props.length;
|
|
|
|
|
2016-05-10 09:12:28 +00:00
|
|
|
for ( ; index < length; index++ ) {
|
2012-04-23 19:05:12 +00:00
|
|
|
prop = props[ index ];
|
2015-05-19 21:48:42 +00:00
|
|
|
Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
|
|
|
|
Animation.tweeners[ prop ].unshift( callback );
|
2008-12-19 18:21:12 +00:00
|
|
|
}
|
2007-01-07 21:43:38 +00:00
|
|
|
},
|
|
|
|
|
2015-05-19 21:48:42 +00:00
|
|
|
prefilters: [ defaultPrefilter ],
|
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
prefilter: function( callback, prepend ) {
|
|
|
|
if ( prepend ) {
|
2015-05-19 21:48:42 +00:00
|
|
|
Animation.prefilters.unshift( callback );
|
2012-04-23 19:05:12 +00:00
|
|
|
} else {
|
2015-05-19 21:48:42 +00:00
|
|
|
Animation.prefilters.push( callback );
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2008-05-13 01:45:58 +00:00
|
|
|
|
2013-09-09 16:13:41 +00:00
|
|
|
jQuery.speed = function( speed, easing, fn ) {
|
|
|
|
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
|
2023-09-19 22:54:40 +00:00
|
|
|
complete: fn || easing ||
|
2017-12-13 06:43:30 +00:00
|
|
|
isFunction( speed ) && speed,
|
2013-09-09 16:13:41 +00:00
|
|
|
duration: speed,
|
2017-12-13 06:43:30 +00:00
|
|
|
easing: fn && easing || easing && !isFunction( easing ) && easing
|
2013-09-09 16:13:41 +00:00
|
|
|
};
|
2012-04-23 19:05:12 +00:00
|
|
|
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
// Go to the end state if fx are off
|
|
|
|
if ( jQuery.fx.off ) {
|
2014-05-12 17:53:40 +00:00
|
|
|
opt.duration = 0;
|
|
|
|
|
|
|
|
} else {
|
2016-07-15 17:42:25 +00:00
|
|
|
if ( typeof opt.duration !== "number" ) {
|
|
|
|
if ( opt.duration in jQuery.fx.speeds ) {
|
|
|
|
opt.duration = jQuery.fx.speeds[ opt.duration ];
|
|
|
|
|
|
|
|
} else {
|
|
|
|
opt.duration = jQuery.fx.speeds._default;
|
|
|
|
}
|
|
|
|
}
|
2014-05-12 17:53:40 +00:00
|
|
|
}
|
2013-03-17 06:40:18 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Normalize opt.queue - true/undefined/null -> "fx"
|
2013-09-09 16:13:41 +00:00
|
|
|
if ( opt.queue == null || opt.queue === true ) {
|
|
|
|
opt.queue = "fx";
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 16:13:41 +00:00
|
|
|
// Queueing
|
|
|
|
opt.old = opt.complete;
|
2012-11-08 01:23:24 +00:00
|
|
|
|
2013-09-09 16:13:41 +00:00
|
|
|
opt.complete = function() {
|
2017-12-13 06:43:30 +00:00
|
|
|
if ( isFunction( opt.old ) ) {
|
2013-09-09 16:13:41 +00:00
|
|
|
opt.old.call( this );
|
2009-12-18 16:16:26 +00:00
|
|
|
}
|
2013-04-08 19:35:16 +00:00
|
|
|
|
2013-09-09 16:13:41 +00:00
|
|
|
if ( opt.queue ) {
|
|
|
|
jQuery.dequeue( this, opt.queue );
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
2012-05-29 02:25:04 +00:00
|
|
|
};
|
2013-09-09 16:13:41 +00:00
|
|
|
|
|
|
|
return opt;
|
|
|
|
};
|
2007-09-07 21:57:40 +00:00
|
|
|
|
2015-08-16 06:59:58 +00:00
|
|
|
jQuery.fn.extend( {
|
2012-04-23 19:05:12 +00:00
|
|
|
fadeTo: function( speed, to, easing, callback ) {
|
2012-05-23 02:36:55 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Show any hidden elements after setting opacity to 0
|
2016-01-20 18:20:58 +00:00
|
|
|
return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
|
2012-05-23 02:36:55 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Animate to the value specified
|
2015-08-16 06:59:58 +00:00
|
|
|
.end().animate( { opacity: to }, speed, easing, callback );
|
2012-04-23 19:05:12 +00:00
|
|
|
},
|
|
|
|
animate: function( prop, speed, easing, callback ) {
|
2012-06-22 20:03:39 +00:00
|
|
|
var empty = jQuery.isEmptyObject( prop ),
|
|
|
|
optall = jQuery.speed( speed, easing, callback ),
|
2012-04-23 19:05:12 +00:00
|
|
|
doAnimation = function() {
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2012-06-22 20:03:39 +00:00
|
|
|
// Operate on a copy of prop so per-property easing won't be lost
|
|
|
|
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
|
2013-05-25 14:18:57 +00:00
|
|
|
|
2013-01-08 01:16:50 +00:00
|
|
|
// Empty animations, or finishing resolves immediately
|
2014-07-17 17:25:59 +00:00
|
|
|
if ( empty || dataPriv.get( this, "finish" ) ) {
|
2012-06-22 20:03:39 +00:00
|
|
|
anim.stop( true );
|
|
|
|
}
|
|
|
|
};
|
2020-05-05 08:49:27 +00:00
|
|
|
|
|
|
|
doAnimation.finish = doAnimation;
|
2012-04-23 19:05:12 +00:00
|
|
|
|
2012-06-22 20:03:39 +00:00
|
|
|
return empty || optall.queue === false ?
|
2011-09-19 20:08:00 +00:00
|
|
|
this.each( doAnimation ) :
|
2011-09-28 15:55:29 +00:00
|
|
|
this.queue( optall.queue, doAnimation );
|
2007-01-07 21:43:38 +00:00
|
|
|
},
|
2011-10-12 01:21:59 +00:00
|
|
|
stop: function( type, clearQueue, gotoEnd ) {
|
2012-05-23 03:04:45 +00:00
|
|
|
var stopQueue = function( hooks ) {
|
|
|
|
var stop = hooks.stop;
|
|
|
|
delete hooks.stop;
|
|
|
|
stop( gotoEnd );
|
2012-04-23 19:05:12 +00:00
|
|
|
};
|
|
|
|
|
2011-10-12 01:21:59 +00:00
|
|
|
if ( typeof type !== "string" ) {
|
|
|
|
gotoEnd = clearQueue;
|
|
|
|
clearQueue = type;
|
|
|
|
type = undefined;
|
|
|
|
}
|
2019-05-01 12:57:55 +00:00
|
|
|
if ( clearQueue ) {
|
2011-09-28 15:55:29 +00:00
|
|
|
this.queue( type || "fx", [] );
|
2009-11-27 19:28:42 +00:00
|
|
|
}
|
2009-12-18 16:16:26 +00:00
|
|
|
|
2015-08-16 06:59:58 +00:00
|
|
|
return this.each( function() {
|
2012-05-23 03:04:45 +00:00
|
|
|
var dequeue = true,
|
|
|
|
index = type != null && type + "queueHooks",
|
2011-09-28 15:55:29 +00:00
|
|
|
timers = jQuery.timers,
|
2014-07-17 17:25:59 +00:00
|
|
|
data = dataPriv.get( this );
|
2011-09-12 23:48:44 +00:00
|
|
|
|
2012-05-23 03:04:45 +00:00
|
|
|
if ( index ) {
|
|
|
|
if ( data[ index ] && data[ index ].stop ) {
|
|
|
|
stopQueue( data[ index ] );
|
|
|
|
}
|
|
|
|
} else {
|
2011-11-11 20:05:06 +00:00
|
|
|
for ( index in data ) {
|
2012-04-23 19:05:12 +00:00
|
|
|
if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
|
2012-05-23 03:04:45 +00:00
|
|
|
stopQueue( data[ index ] );
|
2011-09-28 15:55:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-11 20:05:06 +00:00
|
|
|
for ( index = timers.length; index--; ) {
|
2014-07-17 17:25:59 +00:00
|
|
|
if ( timers[ index ].elem === this &&
|
2015-08-16 06:59:58 +00:00
|
|
|
( type == null || timers[ index ].queue === type ) ) {
|
2014-07-17 17:25:59 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
timers[ index ].anim.stop( gotoEnd );
|
2012-05-23 03:04:45 +00:00
|
|
|
dequeue = false;
|
2011-11-11 20:05:06 +00:00
|
|
|
timers.splice( index, 1 );
|
2007-11-30 21:36:49 +00:00
|
|
|
}
|
2009-11-27 19:28:42 +00:00
|
|
|
}
|
2009-12-18 16:16:26 +00:00
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// 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.
|
2012-05-23 03:04:45 +00:00
|
|
|
if ( dequeue || !gotoEnd ) {
|
2011-09-28 15:55:29 +00:00
|
|
|
jQuery.dequeue( this, type );
|
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2013-01-08 01:16:50 +00:00
|
|
|
},
|
|
|
|
finish: function( type ) {
|
|
|
|
if ( type !== false ) {
|
|
|
|
type = type || "fx";
|
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
return this.each( function() {
|
2013-01-08 01:16:50 +00:00
|
|
|
var index,
|
2014-07-17 17:25:59 +00:00
|
|
|
data = dataPriv.get( this ),
|
2013-01-08 01:16:50 +00:00
|
|
|
queue = data[ type + "queue" ],
|
|
|
|
hooks = data[ type + "queueHooks" ],
|
|
|
|
timers = jQuery.timers,
|
|
|
|
length = queue ? queue.length : 0;
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Enable finishing flag on private data
|
2013-01-08 01:16:50 +00:00
|
|
|
data.finish = true;
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Empty the queue first
|
2013-01-08 01:16:50 +00:00
|
|
|
jQuery.queue( this, type, [] );
|
|
|
|
|
2013-05-25 14:18:57 +00:00
|
|
|
if ( hooks && hooks.stop ) {
|
|
|
|
hooks.stop.call( this, true );
|
2013-01-08 01:16:50 +00:00
|
|
|
}
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Look for any active animations, and finish them
|
2013-01-08 01:16:50 +00:00
|
|
|
for ( index = timers.length; index--; ) {
|
|
|
|
if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
|
|
|
|
timers[ index ].anim.stop( true );
|
|
|
|
timers.splice( index, 1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Look for any animations in the old queue and finish them
|
2013-01-08 01:16:50 +00:00
|
|
|
for ( index = 0; index < length; index++ ) {
|
|
|
|
if ( queue[ index ] && queue[ index ].finish ) {
|
|
|
|
queue[ index ].finish.call( this );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 22:26:36 +00:00
|
|
|
// Turn off finishing flag
|
2013-01-08 01:16:50 +00:00
|
|
|
delete data.finish;
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2007-01-07 21:43:38 +00:00
|
|
|
}
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2007-01-07 21:43:38 +00:00
|
|
|
|
2019-05-13 20:25:11 +00:00
|
|
|
jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
|
2013-09-09 16:13:41 +00:00
|
|
|
var cssFn = jQuery.fn[ name ];
|
|
|
|
jQuery.fn[ name ] = function( speed, easing, callback ) {
|
|
|
|
return speed == null || typeof speed === "boolean" ?
|
|
|
|
cssFn.apply( this, arguments ) :
|
|
|
|
this.animate( genFx( name, true ), speed, easing, callback );
|
|
|
|
};
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2011-04-17 18:08:52 +00:00
|
|
|
|
2008-07-03 22:54:12 +00:00
|
|
|
// Generate shortcuts for custom animations
|
2015-08-16 06:59:58 +00:00
|
|
|
jQuery.each( {
|
|
|
|
slideDown: genFx( "show" ),
|
|
|
|
slideUp: genFx( "hide" ),
|
|
|
|
slideToggle: genFx( "toggle" ),
|
2008-07-03 22:54:12 +00:00
|
|
|
fadeIn: { opacity: "show" },
|
2010-10-17 18:26:32 +00:00
|
|
|
fadeOut: { opacity: "hide" },
|
|
|
|
fadeToggle: { opacity: "toggle" }
|
2009-12-22 00:58:13 +00:00
|
|
|
}, function( name, props ) {
|
Added full support for easing in all shorthand effects methods (hide, show, toggle, fadeTo, slideUp, etc.). Previously, these methods could only be used with two of the three (speed, easing, callback) arguments, or, in the case of fadeTo, 3 of the 4 (speed, opacity, easing, callback) arguments. Added three more sets of tests to the series of "Chain" tests. Fixes #7014
2010-09-08 20:31:32 +00:00
|
|
|
jQuery.fn[ name ] = function( speed, easing, callback ) {
|
|
|
|
return this.animate( props, speed, easing, callback );
|
2008-07-03 22:54:12 +00:00
|
|
|
};
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|
2008-07-03 22:54:12 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
jQuery.timers = [];
|
|
|
|
jQuery.fx.tick = function() {
|
|
|
|
var timer,
|
2013-11-06 05:23:04 +00:00
|
|
|
i = 0,
|
|
|
|
timers = jQuery.timers;
|
2012-04-23 19:05:12 +00:00
|
|
|
|
2017-12-11 17:39:11 +00:00
|
|
|
fxNow = Date.now();
|
2012-11-08 01:22:14 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
for ( ; i < timers.length; i++ ) {
|
|
|
|
timer = timers[ i ];
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2017-01-16 18:18:49 +00:00
|
|
|
// Run the timer and safely remove it when done (allowing for external removal)
|
2012-04-23 19:05:12 +00:00
|
|
|
if ( !timer() && timers[ i ] === timer ) {
|
|
|
|
timers.splice( i--, 1 );
|
2009-11-27 19:28:42 +00:00
|
|
|
}
|
2012-04-23 19:05:12 +00:00
|
|
|
}
|
2010-10-05 18:38:19 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
if ( !timers.length ) {
|
|
|
|
jQuery.fx.stop();
|
|
|
|
}
|
2012-11-08 01:22:14 +00:00
|
|
|
fxNow = undefined;
|
2012-04-23 19:05:12 +00:00
|
|
|
};
|
2010-10-05 18:38:19 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
jQuery.fx.timer = function( timer ) {
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
jQuery.timers.push( timer );
|
|
|
|
jQuery.fx.start();
|
2012-04-23 19:05:12 +00:00
|
|
|
};
|
2010-10-05 18:38:19 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
jQuery.fx.interval = 13;
|
2012-11-08 06:02:14 +00:00
|
|
|
jQuery.fx.start = function() {
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
if ( inProgress ) {
|
|
|
|
return;
|
2012-11-08 06:02:14 +00:00
|
|
|
}
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
|
|
|
|
inProgress = true;
|
|
|
|
schedule();
|
2012-11-08 06:02:14 +00:00
|
|
|
};
|
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
jQuery.fx.stop = function() {
|
Effects: stabilize rAF logic & align timeout logic with it
rAF logic was introduced almost three years ago relative to this commit,
as a primary method for scheduling animation (see gh-1578 pull).
With it there was two substantial changes - one was explicitly mentioned
and the other was not.
First, if browser window was hidden aka `document.hidden === true`
it would immediately execute all scheduled animation without waiting
for time pass i.e. tick time become `0` instead of 13 ms of a default value.
Which created possibility for circular executions in case if `complete`
method executed the same animation (see gh-3434 issue).
And the second one - since then there was two ways of scheduling animation:
with `setInterval` and `requestAnimationFrame`, but there was a
difference in their execution.
In case of `setInterval` it waited default `jQuery.fx.interval` value before
actually starting the new tick, not counting the first step which wasn't
set to be executed through tick method (aka `jQuery.fx.tick`).
Whereas `requestAnimationFrame` first scheduled the call and executed
the `step` method right after that, counting the first call of
`jQuery.fx.timer`, `tick` was happening twice in one frame.
But since tests explicitly disabled rAF method i.e.
`requestAnimationFrame = null` and checking only `setInterval` logic,
since it's impossible to do it otherwise - we missed that change.
Faulty logic also was presented with `cancelAnimationFrame`, which couldn't
clear any timers since `raf` scheduler didn't define new `timerId` value.
Because that change was so subtle, apparently no user noticed it proving
that both `cancelAnimationFrame` and `clearInterval` code paths are redundant.
Since `cancelAnimationFrame` didn't work properly and rAF is and was a primary
used code path, plus the same approach is used in other popular animation libs.
Therefore those code paths were removed.
These changes also replace two different functions which schedule the animation
with one, which checks what type of logic should be used and executes it
appropriatley, but for secondary path it now uses `setTimeout` making it more
consistent with rAF path.
Since ticks are happening globally we also don't require to listen
`visibilitychange` event.
It also changes the way how first call is scheduled so execution of
animation will not happen twice in one frame.
No new tests were not introduced, since now `setTimeout` logic should be
equivalent to the rAF one, but one test was changed since now we actually
execute animation at the first tick.
Fixes gh-3434
Closes gh-3559
2017-03-06 01:06:10 +00:00
|
|
|
inProgress = null;
|
2012-04-23 19:05:12 +00:00
|
|
|
};
|
2008-05-13 01:45:58 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
jQuery.fx.speeds = {
|
|
|
|
slow: 600,
|
|
|
|
fast: 200,
|
2015-08-16 06:59:58 +00:00
|
|
|
|
2012-04-23 19:05:12 +00:00
|
|
|
// Default speed
|
|
|
|
_default: 400
|
|
|
|
};
|
2009-10-26 22:07:57 +00:00
|
|
|
|
2013-09-09 01:25:27 +00:00
|
|
|
return jQuery;
|
2015-08-16 06:59:58 +00:00
|
|
|
} );
|