2 rfxtypes = /^(?:toggle|show|hide)$/,
3 rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
5 animationPrefilters = [ defaultPrefilter ],
7 "*": [function( prop, value ) {
9 tween = this.createTween( prop, value ),
10 parts = rfxnum.exec( value ),
18 unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
20 // We need to compute starting value
21 if ( unit !== "px" && start ) {
22 // Iteratively approximate from a nonzero starting point
23 // Prefer the current property, because this process will be trivial if it uses the same units
24 // Fallback to end or a simple constant
25 start = jQuery.css( tween.elem, prop, true ) || end || 1;
28 // If previous iteration zeroed out, double until we get *something*
29 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
30 scale = scale || ".5";
33 start = start / scale;
34 jQuery.style( tween.elem, prop, start + unit );
36 // Update scale, tolerating zero or NaN from tween.cur()
37 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
38 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
43 // If a +=/-= token was provided, we're doing a relative animation
44 tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
50 // Animations created synchronously will run synchronously
51 function createFxNow() {
52 setTimeout(function() {
55 return ( fxNow = jQuery.now() );
58 function createTweens( animation, props ) {
59 jQuery.each( props, function( prop, value ) {
60 var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
62 length = collection.length;
63 for ( ; index < length; index++ ) {
64 if ( collection[ index ].call( animation, prop, value ) ) {
66 // we're done with this property
73 function Animation( elem, properties, options ) {
77 length = animationPrefilters.length,
78 deferred = jQuery.Deferred().always( function() {
79 // don't match elem in the :animated selector
86 var currentTime = fxNow || createFxNow(),
87 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
88 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
89 temp = remaining / animation.duration || 0,
92 length = animation.tweens.length;
94 for ( ; index < length ; index++ ) {
95 animation.tweens[ index ].run( percent );
98 deferred.notifyWith( elem, [ animation, percent, remaining ]);
100 if ( percent < 1 && length ) {
103 deferred.resolveWith( elem, [ animation ] );
107 animation = deferred.promise({
109 props: jQuery.extend( {}, properties ),
110 opts: jQuery.extend( true, { specialEasing: {} }, options ),
111 originalProperties: properties,
112 originalOptions: options,
113 startTime: fxNow || createFxNow(),
114 duration: options.duration,
116 createTween: function( prop, end ) {
117 var tween = jQuery.Tween( elem, animation.opts, prop, end,
118 animation.opts.specialEasing[ prop ] || animation.opts.easing );
119 animation.tweens.push( tween );
122 stop: function( gotoEnd ) {
124 // if we are going to the end, we want to run all the tweens
125 // otherwise we skip this part
126 length = gotoEnd ? animation.tweens.length : 0;
131 for ( ; index < length ; index++ ) {
132 animation.tweens[ index ].run( 1 );
135 // resolve when we played the last frame
138 deferred.resolveWith( elem, [ animation, gotoEnd ] );
140 deferred.rejectWith( elem, [ animation, gotoEnd ] );
145 props = animation.props;
147 propFilter( props, animation.opts.specialEasing );
149 for ( ; index < length ; index++ ) {
150 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
156 createTweens( animation, props );
158 if ( jQuery.isFunction( animation.opts.start ) ) {
159 animation.opts.start.call( elem, animation );
163 jQuery.extend( tick, {
166 queue: animation.opts.queue
170 // attach callbacks from options
171 return animation.progress( animation.opts.progress )
172 .done( animation.opts.done, animation.opts.complete )
173 .fail( animation.opts.fail )
174 .always( animation.opts.always );
177 function propFilter( props, specialEasing ) {
178 var value, name, index, easing, hooks;
180 // camelCase, specialEasing and expand cssHook pass
181 for ( index in props ) {
182 name = jQuery.camelCase( index );
183 easing = specialEasing[ name ];
184 value = props[ index ];
185 if ( jQuery.isArray( value ) ) {
187 value = props[ index ] = value[ 0 ];
190 if ( index !== name ) {
191 props[ name ] = value;
192 delete props[ index ];
195 hooks = jQuery.cssHooks[ name ];
196 if ( hooks && "expand" in hooks ) {
197 value = hooks.expand( value );
198 delete props[ name ];
200 // not quite $.extend, this wont overwrite keys already present.
201 // also - reusing 'index' from above because we have the correct "name"
202 for ( index in value ) {
203 if ( !( index in props ) ) {
204 props[ index ] = value[ index ];
205 specialEasing[ index ] = easing;
209 specialEasing[ name ] = easing;
214 jQuery.Animation = jQuery.extend( Animation, {
216 tweener: function( props, callback ) {
217 if ( jQuery.isFunction( props ) ) {
221 props = props.split(" ");
226 length = props.length;
228 for ( ; index < length ; index++ ) {
229 prop = props[ index ];
230 tweeners[ prop ] = tweeners[ prop ] || [];
231 tweeners[ prop ].unshift( callback );
235 prefilter: function( callback, prepend ) {
237 animationPrefilters.unshift( callback );
239 animationPrefilters.push( callback );
244 function defaultPrefilter( elem, props, opts ) {
245 /*jshint validthis:true */
246 var prop, index, length,
247 value, dataShow, toggle,
248 tween, hooks, oldfire,
253 hidden = elem.nodeType && isHidden( elem );
255 // handle queue: false promises
257 hooks = jQuery._queueHooks( elem, "fx" );
258 if ( hooks.unqueued == null ) {
260 oldfire = hooks.empty.fire;
261 hooks.empty.fire = function() {
262 if ( !hooks.unqueued ) {
269 anim.always(function() {
270 // doing this makes sure that the complete handler will be called
271 // before this completes
272 anim.always(function() {
274 if ( !jQuery.queue( elem, "fx" ).length ) {
281 // height/width overflow pass
282 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
283 // Make sure that nothing sneaks out
284 // Record all 3 overflow attributes because IE does not
285 // change the overflow attribute when overflowX and
286 // overflowY are set to the same value
287 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
289 // Set display property to inline-block for height/width
290 // animations on inline elements that are having width/height animated
291 if ( jQuery.css( elem, "display" ) === "inline" &&
292 jQuery.css( elem, "float" ) === "none" ) {
294 // inline-level elements accept inline-block;
295 // block-level elements need to be inline with layout
296 if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
297 style.display = "inline-block";
305 if ( opts.overflow ) {
306 style.overflow = "hidden";
307 if ( !jQuery.support.shrinkWrapBlocks ) {
308 anim.always(function() {
309 style.overflow = opts.overflow[ 0 ];
310 style.overflowX = opts.overflow[ 1 ];
311 style.overflowY = opts.overflow[ 2 ];
318 for ( index in props ) {
319 value = props[ index ];
320 if ( rfxtypes.exec( value ) ) {
321 delete props[ index ];
322 toggle = toggle || value === "toggle";
323 if ( value === ( hidden ? "hide" : "show" ) ) {
326 handled.push( index );
330 length = handled.length;
332 dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
333 if ( "hidden" in dataShow ) {
334 hidden = dataShow.hidden;
337 // store state if its toggle - enables .stop().toggle() to "reverse"
339 dataShow.hidden = !hidden;
342 jQuery( elem ).show();
344 anim.done(function() {
345 jQuery( elem ).hide();
348 anim.done(function() {
350 jQuery._removeData( elem, "fxshow" );
351 for ( prop in orig ) {
352 jQuery.style( elem, prop, orig[ prop ] );
355 for ( index = 0 ; index < length ; index++ ) {
356 prop = handled[ index ];
357 tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
358 orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
360 if ( !( prop in dataShow ) ) {
361 dataShow[ prop ] = tween.start;
363 tween.end = tween.start;
364 tween.start = prop === "width" || prop === "height" ? 1 : 0;
371 function Tween( elem, options, prop, end, easing ) {
372 return new Tween.prototype.init( elem, options, prop, end, easing );
374 jQuery.Tween = Tween;
378 init: function( elem, options, prop, end, easing, unit ) {
381 this.easing = easing || "swing";
382 this.options = options;
383 this.start = this.now = this.cur();
385 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
388 var hooks = Tween.propHooks[ this.prop ];
390 return hooks && hooks.get ?
392 Tween.propHooks._default.get( this );
394 run: function( percent ) {
396 hooks = Tween.propHooks[ this.prop ];
398 if ( this.options.duration ) {
399 this.pos = eased = jQuery.easing[ this.easing ](
400 percent, this.options.duration * percent, 0, 1, this.options.duration
403 this.pos = eased = percent;
405 this.now = ( this.end - this.start ) * eased + this.start;
407 if ( this.options.step ) {
408 this.options.step.call( this.elem, this.now, this );
411 if ( hooks && hooks.set ) {
414 Tween.propHooks._default.set( this );
420 Tween.prototype.init.prototype = Tween.prototype;
424 get: function( tween ) {
427 if ( tween.elem[ tween.prop ] != null &&
428 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
429 return tween.elem[ tween.prop ];
432 // passing an empty string as a 3rd parameter to .css will automatically
433 // attempt a parseFloat and fallback to a string if the parse fails
434 // so, simple values such as "10px" are parsed to Float.
435 // complex values such as "rotate(1rad)" are returned as is.
436 result = jQuery.css( tween.elem, tween.prop, "" );
437 // Empty strings, null, undefined and "auto" are converted to 0.
438 return !result || result === "auto" ? 0 : result;
440 set: function( tween ) {
441 // use step hook for back compat - use cssHook if its there - use .style if its
442 // available and use plain properties where available
443 if ( jQuery.fx.step[ tween.prop ] ) {
444 jQuery.fx.step[ tween.prop ]( tween );
445 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
446 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
448 tween.elem[ tween.prop ] = tween.now;
454 // Remove in 2.0 - this supports IE8's panic based approach
455 // to setting things on disconnected nodes
457 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
458 set: function( tween ) {
459 if ( tween.elem.nodeType && tween.elem.parentNode ) {
460 tween.elem[ tween.prop ] = tween.now;
465 jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
466 var cssFn = jQuery.fn[ name ];
467 jQuery.fn[ name ] = function( speed, easing, callback ) {
468 return speed == null || typeof speed === "boolean" ?
469 cssFn.apply( this, arguments ) :
470 this.animate( genFx( name, true ), speed, easing, callback );
475 fadeTo: function( speed, to, easing, callback ) {
477 // show any hidden elements after setting opacity to 0
478 return this.filter( isHidden ).css( "opacity", 0 ).show()
480 // animate to the value specified
481 .end().animate({ opacity: to }, speed, easing, callback );
483 animate: function( prop, speed, easing, callback ) {
484 var empty = jQuery.isEmptyObject( prop ),
485 optall = jQuery.speed( speed, easing, callback ),
486 doAnimation = function() {
487 // Operate on a copy of prop so per-property easing won't be lost
488 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
489 doAnimation.finish = function() {
492 // Empty animations, or finishing resolves immediately
493 if ( empty || jQuery._data( this, "finish" ) ) {
497 doAnimation.finish = doAnimation;
499 return empty || optall.queue === false ?
500 this.each( doAnimation ) :
501 this.queue( optall.queue, doAnimation );
503 stop: function( type, clearQueue, gotoEnd ) {
504 var stopQueue = function( hooks ) {
505 var stop = hooks.stop;
510 if ( typeof type !== "string" ) {
511 gotoEnd = clearQueue;
515 if ( clearQueue && type !== false ) {
516 this.queue( type || "fx", [] );
519 return this.each(function() {
521 index = type != null && type + "queueHooks",
522 timers = jQuery.timers,
523 data = jQuery._data( this );
526 if ( data[ index ] && data[ index ].stop ) {
527 stopQueue( data[ index ] );
530 for ( index in data ) {
531 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
532 stopQueue( data[ index ] );
537 for ( index = timers.length; index--; ) {
538 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
539 timers[ index ].anim.stop( gotoEnd );
541 timers.splice( index, 1 );
545 // start the next in the queue if the last step wasn't forced
546 // timers currently will call their complete callbacks, which will dequeue
547 // but only if they were gotoEnd
548 if ( dequeue || !gotoEnd ) {
549 jQuery.dequeue( this, type );
553 finish: function( type ) {
554 if ( type !== false ) {
557 return this.each(function() {
559 data = jQuery._data( this ),
560 queue = data[ type + "queue" ],
561 hooks = data[ type + "queueHooks" ],
562 timers = jQuery.timers,
563 length = queue ? queue.length : 0;
565 // enable finishing flag on private data
568 // empty the queue first
569 jQuery.queue( this, type, [] );
571 if ( hooks && hooks.cur && hooks.cur.finish ) {
572 hooks.cur.finish.call( this );
575 // look for any active animations, and finish them
576 for ( index = timers.length; index--; ) {
577 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
578 timers[ index ].anim.stop( true );
579 timers.splice( index, 1 );
583 // look for any animations in the old queue and finish them
584 for ( index = 0; index < length; index++ ) {
585 if ( queue[ index ] && queue[ index ].finish ) {
586 queue[ index ].finish.call( this );
590 // turn off finishing flag
596 // Generate parameters to create a standard animation
597 function genFx( type, includeWidth ) {
599 attrs = { height: type },
602 // if we include width, step value is 1 to do all cssExpand values,
603 // if we don't include width, step value is 2 to skip over Left and Right
604 includeWidth = includeWidth? 1 : 0;
605 for( ; i < 4 ; i += 2 - includeWidth ) {
606 which = cssExpand[ i ];
607 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
610 if ( includeWidth ) {
611 attrs.opacity = attrs.width = type;
617 // Generate shortcuts for custom animations
619 slideDown: genFx("show"),
620 slideUp: genFx("hide"),
621 slideToggle: genFx("toggle"),
622 fadeIn: { opacity: "show" },
623 fadeOut: { opacity: "hide" },
624 fadeToggle: { opacity: "toggle" }
625 }, function( name, props ) {
626 jQuery.fn[ name ] = function( speed, easing, callback ) {
627 return this.animate( props, speed, easing, callback );
631 jQuery.speed = function( speed, easing, fn ) {
632 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
633 complete: fn || !fn && easing ||
634 jQuery.isFunction( speed ) && speed,
636 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
639 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
640 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
642 // normalize opt.queue - true/undefined/null -> "fx"
643 if ( opt.queue == null || opt.queue === true ) {
648 opt.old = opt.complete;
650 opt.complete = function() {
651 if ( jQuery.isFunction( opt.old ) ) {
652 opt.old.call( this );
656 jQuery.dequeue( this, opt.queue );
664 linear: function( p ) {
667 swing: function( p ) {
668 return 0.5 - Math.cos( p*Math.PI ) / 2;
673 jQuery.fx = Tween.prototype.init;
674 jQuery.fx.tick = function() {
676 timers = jQuery.timers,
679 fxNow = jQuery.now();
681 for ( ; i < timers.length; i++ ) {
683 // Checks the timer has not already been removed
684 if ( !timer() && timers[ i ] === timer ) {
685 timers.splice( i--, 1 );
689 if ( !timers.length ) {
695 jQuery.fx.timer = function( timer ) {
696 if ( timer() && jQuery.timers.push( timer ) ) {
701 jQuery.fx.interval = 13;
703 jQuery.fx.start = function() {
705 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
709 jQuery.fx.stop = function() {
710 clearInterval( timerId );
721 // Back Compat <1.8 extension point
724 if ( jQuery.expr && jQuery.expr.filters ) {
725 jQuery.expr.filters.animated = function( elem ) {
726 return jQuery.grep(jQuery.timers, function( fn ) {
727 return elem === fn.elem;