name = camelCase( index );
easing = specialEasing[ name ];
if ( Array.isArray( value ) ) {
value = props[ index ] = value[ 0 ];
hooks = jQuery.cssHooks[ name ];
if ( hooks && "expand" in hooks ) {
value = hooks.expand( value );
// Not quite $.extend, this won't overwrite existing keys.
// Reusing 'index' because we have the correct "name"
if ( !( index in props ) ) {
props[ index ] = value[ index ];
specialEasing[ index ] = easing;
specialEasing[ name ] = easing;
function Animation( elem, properties, options ) {
length = Animation.prefilters.length,
deferred = jQuery.Deferred().always( function() {
// Don't match elem in the :animated selector
var currentTime = fxNow || createFxNow(),
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
// Support: Android 2.3 only
// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
temp = remaining / animation.duration || 0,
length = animation.tweens.length;
for ( ; index < length; index++ ) {
animation.tweens[ index ].run( percent );
deferred.notifyWith( elem, [ animation, percent, remaining ] );
// If there's more to do, yield
if ( percent < 1 && length ) {
// If this was an empty animation, synthesize a final progress notification
deferred.notifyWith( elem, [ animation, 1, 0 ] );
// Resolve the animation and report its conclusion
deferred.resolveWith( elem, [ animation ] );
animation = deferred.promise( {
props: jQuery.extend( {}, properties ),
opts: jQuery.extend( true, {
easing: jQuery.easing._default
originalProperties: properties,
originalOptions: options,
startTime: fxNow || createFxNow(),
duration: options.duration,
createTween: function( prop, end ) {
var tween = jQuery.Tween( elem, animation.opts, prop, end,
animation.opts.specialEasing[ prop ] || animation.opts.easing );
animation.tweens.push( tween );
stop: function( gotoEnd ) {
// If we are going to the end, we want to run all the tweens
// otherwise we skip this part
length = gotoEnd ? animation.tweens.length : 0;
for ( ; index < length; index++ ) {
animation.tweens[ index ].run( 1 );
// Resolve when we played the last frame; otherwise, reject
deferred.notifyWith( elem, [ animation, 1, 0 ] );
deferred.resolveWith( elem, [ animation, gotoEnd ] );
deferred.rejectWith( elem, [ animation, gotoEnd ] );
propFilter( props, animation.opts.specialEasing );
for ( ; index < length; index++ ) {
result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
if ( isFunction( result.stop ) ) {
jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
result.stop.bind( result );
jQuery.map( props, createTween, animation );
if ( isFunction( animation.opts.start ) ) {
animation.opts.start.call( elem, animation );
// Attach callbacks from options
.progress( animation.opts.progress )
.done( animation.opts.done, animation.opts.complete )
.fail( animation.opts.fail )
.always( animation.opts.always );
queue: animation.opts.queue
jQuery.Animation = jQuery.extend( Animation, {
"*": [ function( prop, value ) {
var tween = this.createTween( prop, value );
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
tweener: function( props, callback ) {
if ( isFunction( props ) ) {
props = props.match( rnothtmlwhite );
for ( ; index < length; index++ ) {
Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
Animation.tweeners[ prop ].unshift( callback );
prefilters: [ defaultPrefilter ],
prefilter: function( callback, prepend ) {
Animation.prefilters.unshift( callback );
Animation.prefilters.push( callback );
jQuery.speed = function( speed, easing, fn ) {
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
complete: fn || !fn && easing ||
isFunction( speed ) && speed,
easing: fn && easing || easing && !isFunction( easing ) && easing
// Go to the end state if fx are off
if ( typeof opt.duration !== "number" ) {
if ( opt.duration in jQuery.fx.speeds ) {
opt.duration = jQuery.fx.speeds[ opt.duration ];
opt.duration = jQuery.fx.speeds._default;
// Normalize opt.queue - true/undefined/null -> "fx"
if ( opt.queue == null || opt.queue === true ) {
opt.complete = function() {
if ( isFunction( opt.old ) ) {
jQuery.dequeue( this, opt.queue );
fadeTo: function( speed, to, easing, callback ) {
// Show any hidden elements after setting opacity to 0
return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
// Animate to the value specified
.end().animate( { opacity: to }, speed, easing, callback );
animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations, or finishing resolves immediately
if ( empty || dataPriv.get( this, "finish" ) ) {
doAnimation.finish = doAnimation;
return empty || optall.queue === false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
stop: function( type, clearQueue, gotoEnd ) {
var stopQueue = function( hooks ) {
if ( typeof type !== "string" ) {
this.queue( type || "fx", [] );
return this.each( function() {
index = type != null && type + "queueHooks",
data = dataPriv.get( this );
if ( data[ index ] && data[ index ].stop ) {
stopQueue( data[ index ] );
if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
stopQueue( data[ index ] );
for ( index = timers.length; index--; ) {
if ( timers[ index ].elem === this &&
( type == null || timers[ index ].queue === type ) ) {
timers[ index ].anim.stop( gotoEnd );
timers.splice( index, 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 ( dequeue || !gotoEnd ) {
jQuery.dequeue( this, type );
finish: function( type ) {
return this.each( function() {
data = dataPriv.get( this ),
queue = data[ type + "queue" ],
hooks = data[ type + "queueHooks" ],
length = queue ? queue.length : 0;
// Enable finishing flag on private data
jQuery.queue( this, type, [] );
if ( hooks && hooks.stop ) {
hooks.stop.call( this, true );
// 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
jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
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 );
// Generate shortcuts for custom animations
slideDown: genFx( "show" ),
slideUp: genFx( "hide" ),
slideToggle: genFx( "toggle" ),
fadeIn: { opacity: "show" },
fadeOut: { opacity: "hide" },
fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
jQuery.fn[ name ] = function( speed, easing, callback ) {
return this.animate( props, speed, easing, callback );
jQuery.fx.tick = function() {
for ( ; i < timers.length; i++ ) {
// Run the timer and safely remove it when done (allowing for external removal)
if ( !timer() && timers[ i ] === timer ) {
jQuery.fx.timer = function( timer ) {
jQuery.timers.push( timer );
jQuery.fx.start = function() {
jQuery.fx.stop = function() {
// Based off of the plugin by Clint Helfers, with permission.
// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
jQuery.fn.delay = function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
return this.queue( type, function( next, hooks ) {
var timeout = window.setTimeout( next, time );
hooks.stop = function() {
window.clearTimeout( timeout );
var input = document.createElement( "input" ),
select = document.createElement( "select" ),
opt = select.appendChild( document.createElement( "option" ) );
// Support: Android <=4.3 only
// Default value for a checkbox should be "on"
support.checkOn = input.value !== "";
// Must access selectedIndex to make default options select
support.optSelected = opt.selected;
// An input loses its value after becoming a radio
input = document.createElement( "input" );
support.radioValue = input.value === "t";
attrHandle = jQuery.expr.attrHandle;
attr: function( name, value ) {
return access( this, jQuery.attr, name, value, arguments.length > 1 );
removeAttr: function( name ) {
return this.each( function() {
jQuery.removeAttr( this, name );
attr: function( elem, name, value ) {
// Don't get/set attributes on text, comment and attribute nodes
if ( nType === 3 || nType === 8 || nType === 2 ) {