7 "./css/var/isHiddenWithinTree",
10 "./data/var/dataPriv",
20 ], function( jQuery, document, rcssNum, rnothtmlwhite, cssExpand, isHiddenWithinTree, swap,
21 adjustCSS, dataPriv, showHide ) {
27 rfxtypes = /^(?:toggle|show|hide)$/,
32 if ( document.hidden === false && window.requestAnimationFrame ) {
33 window.requestAnimationFrame( schedule );
35 window.setTimeout( schedule, jQuery.fx.interval );
42 // Animations created synchronously will run synchronously
43 function createFxNow() {
44 window.setTimeout( function() {
47 return ( fxNow = jQuery.now() );
50 // Generate parameters to create a standard animation
51 function genFx( type, includeWidth ) {
54 attrs = { height: type };
56 // If we include width, step value is 1 to do all cssExpand values,
57 // otherwise step value is 2 to skip over Left and Right
58 includeWidth = includeWidth ? 1 : 0;
59 for ( ; i < 4; i += 2 - includeWidth ) {
60 which = cssExpand[ i ];
61 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
65 attrs.opacity = attrs.width = type;
71 function createTween( value, prop, animation ) {
73 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
75 length = collection.length;
76 for ( ; index < length; index++ ) {
77 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
79 // We're done with this property
85 function defaultPrefilter( elem, props, opts ) {
86 var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
87 isBox = "width" in props || "height" in props,
91 hidden = elem.nodeType && isHiddenWithinTree( elem ),
92 dataShow = dataPriv.get( elem, "fxshow" );
94 // Queue-skipping animations hijack the fx hooks
96 hooks = jQuery._queueHooks( elem, "fx" );
97 if ( hooks.unqueued == null ) {
99 oldfire = hooks.empty.fire;
100 hooks.empty.fire = function() {
101 if ( !hooks.unqueued ) {
108 anim.always( function() {
110 // Ensure the complete handler is called before this completes
111 anim.always( function() {
113 if ( !jQuery.queue( elem, "fx" ).length ) {
120 // Detect show/hide animations
121 for ( prop in props ) {
122 value = props[ prop ];
123 if ( rfxtypes.test( value ) ) {
124 delete props[ prop ];
125 toggle = toggle || value === "toggle";
126 if ( value === ( hidden ? "hide" : "show" ) ) {
128 // Pretend to be hidden if this is a "show" and
129 // there is still data from a stopped show/hide
130 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
133 // Ignore all other no-op show/hide data
138 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
142 // Bail out if this is a no-op like .hide().hide()
143 propTween = !jQuery.isEmptyObject( props );
144 if ( !propTween && jQuery.isEmptyObject( orig ) ) {
148 // Restrict "overflow" and "display" styles during box animations
149 if ( isBox && elem.nodeType === 1 ) {
151 // Support: IE <=9 - 11, Edge 12 - 13
152 // Record all 3 overflow attributes because IE does not infer the shorthand
153 // from identically-valued overflowX and overflowY
154 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
156 // Identify a display type, preferring old show/hide data over the CSS cascade
157 restoreDisplay = dataShow && dataShow.display;
158 if ( restoreDisplay == null ) {
159 restoreDisplay = dataPriv.get( elem, "display" );
161 display = jQuery.css( elem, "display" );
162 if ( display === "none" ) {
163 if ( restoreDisplay ) {
164 display = restoreDisplay;
167 // Get nonempty value(s) by temporarily forcing visibility
168 showHide( [ elem ], true );
169 restoreDisplay = elem.style.display || restoreDisplay;
170 display = jQuery.css( elem, "display" );
171 showHide( [ elem ] );
175 // Animate inline elements as inline-block
176 if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
177 if ( jQuery.css( elem, "float" ) === "none" ) {
179 // Restore the original display value at the end of pure show/hide animations
181 anim.done( function() {
182 style.display = restoreDisplay;
184 if ( restoreDisplay == null ) {
185 display = style.display;
186 restoreDisplay = display === "none" ? "" : display;
189 style.display = "inline-block";
194 if ( opts.overflow ) {
195 style.overflow = "hidden";
196 anim.always( function() {
197 style.overflow = opts.overflow[ 0 ];
198 style.overflowX = opts.overflow[ 1 ];
199 style.overflowY = opts.overflow[ 2 ];
203 // Implement show/hide animations
205 for ( prop in orig ) {
207 // General show/hide setup for this element animation
210 if ( "hidden" in dataShow ) {
211 hidden = dataShow.hidden;
214 dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
217 // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
219 dataShow.hidden = !hidden;
222 // Show elements before animating them
224 showHide( [ elem ], true );
227 /* eslint-disable no-loop-func */
229 anim.done( function() {
231 /* eslint-enable no-loop-func */
233 // The final step of a "hide" animation is actually hiding the element
235 showHide( [ elem ] );
237 dataPriv.remove( elem, "fxshow" );
238 for ( prop in orig ) {
239 jQuery.style( elem, prop, orig[ prop ] );
244 // Per-property setup
245 propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
246 if ( !( prop in dataShow ) ) {
247 dataShow[ prop ] = propTween.start;
249 propTween.end = propTween.start;
256 function propFilter( props, specialEasing ) {
257 var index, name, easing, value, hooks;
259 // camelCase, specialEasing and expand cssHook pass
260 for ( index in props ) {
261 name = jQuery.camelCase( index );
262 easing = specialEasing[ name ];
263 value = props[ index ];
264 if ( Array.isArray( value ) ) {
266 value = props[ index ] = value[ 0 ];
269 if ( index !== name ) {
270 props[ name ] = value;
271 delete props[ index ];
274 hooks = jQuery.cssHooks[ name ];
275 if ( hooks && "expand" in hooks ) {
276 value = hooks.expand( value );
277 delete props[ name ];
279 // Not quite $.extend, this won't overwrite existing keys.
280 // Reusing 'index' because we have the correct "name"
281 for ( index in value ) {
282 if ( !( index in props ) ) {
283 props[ index ] = value[ index ];
284 specialEasing[ index ] = easing;
288 specialEasing[ name ] = easing;
293 function Animation( elem, properties, options ) {
297 length = Animation.prefilters.length,
298 deferred = jQuery.Deferred().always( function() {
300 // Don't match elem in the :animated selector
307 var currentTime = fxNow || createFxNow(),
308 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
310 // Support: Android 2.3 only
311 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
312 temp = remaining / animation.duration || 0,
315 length = animation.tweens.length;
317 for ( ; index < length; index++ ) {
318 animation.tweens[ index ].run( percent );
321 deferred.notifyWith( elem, [ animation, percent, remaining ] );
323 // If there's more to do, yield
324 if ( percent < 1 && length ) {
328 // If this was an empty animation, synthesize a final progress notification
330 deferred.notifyWith( elem, [ animation, 1, 0 ] );
333 // Resolve the animation and report its conclusion
334 deferred.resolveWith( elem, [ animation ] );
337 animation = deferred.promise( {
339 props: jQuery.extend( {}, properties ),
340 opts: jQuery.extend( true, {
342 easing: jQuery.easing._default
344 originalProperties: properties,
345 originalOptions: options,
346 startTime: fxNow || createFxNow(),
347 duration: options.duration,
349 createTween: function( prop, end ) {
350 var tween = jQuery.Tween( elem, animation.opts, prop, end,
351 animation.opts.specialEasing[ prop ] || animation.opts.easing );
352 animation.tweens.push( tween );
355 stop: function( gotoEnd ) {
358 // If we are going to the end, we want to run all the tweens
359 // otherwise we skip this part
360 length = gotoEnd ? animation.tweens.length : 0;
365 for ( ; index < length; index++ ) {
366 animation.tweens[ index ].run( 1 );
369 // Resolve when we played the last frame; otherwise, reject
371 deferred.notifyWith( elem, [ animation, 1, 0 ] );
372 deferred.resolveWith( elem, [ animation, gotoEnd ] );
374 deferred.rejectWith( elem, [ animation, gotoEnd ] );
379 props = animation.props;
381 propFilter( props, animation.opts.specialEasing );
383 for ( ; index < length; index++ ) {
384 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
386 if ( jQuery.isFunction( result.stop ) ) {
387 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
388 jQuery.proxy( result.stop, result );
394 jQuery.map( props, createTween, animation );
396 if ( jQuery.isFunction( animation.opts.start ) ) {
397 animation.opts.start.call( elem, animation );
400 // Attach callbacks from options
402 .progress( animation.opts.progress )
403 .done( animation.opts.done, animation.opts.complete )
404 .fail( animation.opts.fail )
405 .always( animation.opts.always );
408 jQuery.extend( tick, {
411 queue: animation.opts.queue
418 jQuery.Animation = jQuery.extend( Animation, {
421 "*": [ function( prop, value ) {
422 var tween = this.createTween( prop, value );
423 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
428 tweener: function( props, callback ) {
429 if ( jQuery.isFunction( props ) ) {
433 props = props.match( rnothtmlwhite );
438 length = props.length;
440 for ( ; index < length; index++ ) {
441 prop = props[ index ];
442 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
443 Animation.tweeners[ prop ].unshift( callback );
447 prefilters: [ defaultPrefilter ],
449 prefilter: function( callback, prepend ) {
451 Animation.prefilters.unshift( callback );
453 Animation.prefilters.push( callback );
458 jQuery.speed = function( speed, easing, fn ) {
459 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
460 complete: fn || !fn && easing ||
461 jQuery.isFunction( speed ) && speed,
463 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
466 // Go to the end state if fx are off
467 if ( jQuery.fx.off ) {
471 if ( typeof opt.duration !== "number" ) {
472 if ( opt.duration in jQuery.fx.speeds ) {
473 opt.duration = jQuery.fx.speeds[ opt.duration ];
476 opt.duration = jQuery.fx.speeds._default;
481 // Normalize opt.queue - true/undefined/null -> "fx"
482 if ( opt.queue == null || opt.queue === true ) {
487 opt.old = opt.complete;
489 opt.complete = function() {
490 if ( jQuery.isFunction( opt.old ) ) {
491 opt.old.call( this );
495 jQuery.dequeue( this, opt.queue );
503 fadeTo: function( speed, to, easing, callback ) {
505 // Show any hidden elements after setting opacity to 0
506 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
508 // Animate to the value specified
509 .end().animate( { opacity: to }, speed, easing, callback );
511 animate: function( prop, speed, easing, callback ) {
512 var empty = jQuery.isEmptyObject( prop ),
513 optall = jQuery.speed( speed, easing, callback ),
514 doAnimation = function() {
516 // Operate on a copy of prop so per-property easing won't be lost
517 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
519 // Empty animations, or finishing resolves immediately
520 if ( empty || dataPriv.get( this, "finish" ) ) {
524 doAnimation.finish = doAnimation;
526 return empty || optall.queue === false ?
527 this.each( doAnimation ) :
528 this.queue( optall.queue, doAnimation );
530 stop: function( type, clearQueue, gotoEnd ) {
531 var stopQueue = function( hooks ) {
532 var stop = hooks.stop;
537 if ( typeof type !== "string" ) {
538 gotoEnd = clearQueue;
542 if ( clearQueue && type !== false ) {
543 this.queue( type || "fx", [] );
546 return this.each( function() {
548 index = type != null && type + "queueHooks",
549 timers = jQuery.timers,
550 data = dataPriv.get( this );
553 if ( data[ index ] && data[ index ].stop ) {
554 stopQueue( data[ index ] );
557 for ( index in data ) {
558 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
559 stopQueue( data[ index ] );
564 for ( index = timers.length; index--; ) {
565 if ( timers[ index ].elem === this &&
566 ( type == null || timers[ index ].queue === type ) ) {
568 timers[ index ].anim.stop( gotoEnd );
570 timers.splice( index, 1 );
574 // Start the next in the queue if the last step wasn't forced.
575 // Timers currently will call their complete callbacks, which
576 // will dequeue but only if they were gotoEnd.
577 if ( dequeue || !gotoEnd ) {
578 jQuery.dequeue( this, type );
582 finish: function( type ) {
583 if ( type !== false ) {
586 return this.each( function() {
588 data = dataPriv.get( this ),
589 queue = data[ type + "queue" ],
590 hooks = data[ type + "queueHooks" ],
591 timers = jQuery.timers,
592 length = queue ? queue.length : 0;
594 // Enable finishing flag on private data
597 // Empty the queue first
598 jQuery.queue( this, type, [] );
600 if ( hooks && hooks.stop ) {
601 hooks.stop.call( this, true );
604 // Look for any active animations, and finish them
605 for ( index = timers.length; index--; ) {
606 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
607 timers[ index ].anim.stop( true );
608 timers.splice( index, 1 );
612 // Look for any animations in the old queue and finish them
613 for ( index = 0; index < length; index++ ) {
614 if ( queue[ index ] && queue[ index ].finish ) {
615 queue[ index ].finish.call( this );
619 // Turn off finishing flag
625 jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
626 var cssFn = jQuery.fn[ name ];
627 jQuery.fn[ name ] = function( speed, easing, callback ) {
628 return speed == null || typeof speed === "boolean" ?
629 cssFn.apply( this, arguments ) :
630 this.animate( genFx( name, true ), speed, easing, callback );
634 // Generate shortcuts for custom animations
636 slideDown: genFx( "show" ),
637 slideUp: genFx( "hide" ),
638 slideToggle: genFx( "toggle" ),
639 fadeIn: { opacity: "show" },
640 fadeOut: { opacity: "hide" },
641 fadeToggle: { opacity: "toggle" }
642 }, function( name, props ) {
643 jQuery.fn[ name ] = function( speed, easing, callback ) {
644 return this.animate( props, speed, easing, callback );
649 jQuery.fx.tick = function() {
652 timers = jQuery.timers;
654 fxNow = jQuery.now();
656 for ( ; i < timers.length; i++ ) {
659 // Run the timer and safely remove it when done (allowing for external removal)
660 if ( !timer() && timers[ i ] === timer ) {
661 timers.splice( i--, 1 );
665 if ( !timers.length ) {
671 jQuery.fx.timer = function( timer ) {
672 jQuery.timers.push( timer );
676 jQuery.fx.interval = 13;
677 jQuery.fx.start = function() {
686 jQuery.fx.stop = function() {