Project

General

Profile

1
define( [
2
	"./core",
3
	"./var/document",
4
	"./var/rcssNum",
5
	"./var/rnothtmlwhite",
6
	"./css/var/cssExpand",
7
	"./css/var/isHiddenWithinTree",
8
	"./css/var/swap",
9
	"./css/adjustCSS",
10
	"./data/var/dataPriv",
11
	"./css/showHide",
12

    
13
	"./core/init",
14
	"./queue",
15
	"./deferred",
16
	"./traversing",
17
	"./manipulation",
18
	"./css",
19
	"./effects/Tween"
20
], function( jQuery, document, rcssNum, rnothtmlwhite, cssExpand, isHiddenWithinTree, swap,
21
	adjustCSS, dataPriv, showHide ) {
22

    
23
"use strict";
24

    
25
var
26
	fxNow, inProgress,
27
	rfxtypes = /^(?:toggle|show|hide)$/,
28
	rrun = /queueHooks$/;
29

    
30
function schedule() {
31
	if ( inProgress ) {
32
		if ( document.hidden === false && window.requestAnimationFrame ) {
33
			window.requestAnimationFrame( schedule );
34
		} else {
35
			window.setTimeout( schedule, jQuery.fx.interval );
36
		}
37

    
38
		jQuery.fx.tick();
39
	}
40
}
41

    
42
// Animations created synchronously will run synchronously
43
function createFxNow() {
44
	window.setTimeout( function() {
45
		fxNow = undefined;
46
	} );
47
	return ( fxNow = jQuery.now() );
48
}
49

    
50
// Generate parameters to create a standard animation
51
function genFx( type, includeWidth ) {
52
	var which,
53
		i = 0,
54
		attrs = { height: type };
55

    
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;
62
	}
63

    
64
	if ( includeWidth ) {
65
		attrs.opacity = attrs.width = type;
66
	}
67

    
68
	return attrs;
69
}
70

    
71
function createTween( value, prop, animation ) {
72
	var tween,
73
		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
74
		index = 0,
75
		length = collection.length;
76
	for ( ; index < length; index++ ) {
77
		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
78

    
79
			// We're done with this property
80
			return tween;
81
		}
82
	}
83
}
84

    
85
function defaultPrefilter( elem, props, opts ) {
86
	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
87
		isBox = "width" in props || "height" in props,
88
		anim = this,
89
		orig = {},
90
		style = elem.style,
91
		hidden = elem.nodeType && isHiddenWithinTree( elem ),
92
		dataShow = dataPriv.get( elem, "fxshow" );
93

    
94
	// Queue-skipping animations hijack the fx hooks
95
	if ( !opts.queue ) {
96
		hooks = jQuery._queueHooks( elem, "fx" );
97
		if ( hooks.unqueued == null ) {
98
			hooks.unqueued = 0;
99
			oldfire = hooks.empty.fire;
100
			hooks.empty.fire = function() {
101
				if ( !hooks.unqueued ) {
102
					oldfire();
103
				}
104
			};
105
		}
106
		hooks.unqueued++;
107

    
108
		anim.always( function() {
109

    
110
			// Ensure the complete handler is called before this completes
111
			anim.always( function() {
112
				hooks.unqueued--;
113
				if ( !jQuery.queue( elem, "fx" ).length ) {
114
					hooks.empty.fire();
115
				}
116
			} );
117
		} );
118
	}
119

    
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" ) ) {
127

    
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 ) {
131
					hidden = true;
132

    
133
				// Ignore all other no-op show/hide data
134
				} else {
135
					continue;
136
				}
137
			}
138
			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
139
		}
140
	}
141

    
142
	// Bail out if this is a no-op like .hide().hide()
143
	propTween = !jQuery.isEmptyObject( props );
144
	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
145
		return;
146
	}
147

    
148
	// Restrict "overflow" and "display" styles during box animations
149
	if ( isBox && elem.nodeType === 1 ) {
150

    
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 ];
155

    
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" );
160
		}
161
		display = jQuery.css( elem, "display" );
162
		if ( display === "none" ) {
163
			if ( restoreDisplay ) {
164
				display = restoreDisplay;
165
			} else {
166

    
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 ] );
172
			}
173
		}
174

    
175
		// Animate inline elements as inline-block
176
		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
177
			if ( jQuery.css( elem, "float" ) === "none" ) {
178

    
179
				// Restore the original display value at the end of pure show/hide animations
180
				if ( !propTween ) {
181
					anim.done( function() {
182
						style.display = restoreDisplay;
183
					} );
184
					if ( restoreDisplay == null ) {
185
						display = style.display;
186
						restoreDisplay = display === "none" ? "" : display;
187
					}
188
				}
189
				style.display = "inline-block";
190
			}
191
		}
192
	}
193

    
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 ];
200
		} );
201
	}
202

    
203
	// Implement show/hide animations
204
	propTween = false;
205
	for ( prop in orig ) {
206

    
207
		// General show/hide setup for this element animation
208
		if ( !propTween ) {
209
			if ( dataShow ) {
210
				if ( "hidden" in dataShow ) {
211
					hidden = dataShow.hidden;
212
				}
213
			} else {
214
				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
215
			}
216

    
217
			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
218
			if ( toggle ) {
219
				dataShow.hidden = !hidden;
220
			}
221

    
222
			// Show elements before animating them
223
			if ( hidden ) {
224
				showHide( [ elem ], true );
225
			}
226

    
227
			/* eslint-disable no-loop-func */
228

    
229
			anim.done( function() {
230

    
231
			/* eslint-enable no-loop-func */
232

    
233
				// The final step of a "hide" animation is actually hiding the element
234
				if ( !hidden ) {
235
					showHide( [ elem ] );
236
				}
237
				dataPriv.remove( elem, "fxshow" );
238
				for ( prop in orig ) {
239
					jQuery.style( elem, prop, orig[ prop ] );
240
				}
241
			} );
242
		}
243

    
244
		// Per-property setup
245
		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
246
		if ( !( prop in dataShow ) ) {
247
			dataShow[ prop ] = propTween.start;
248
			if ( hidden ) {
249
				propTween.end = propTween.start;
250
				propTween.start = 0;
251
			}
252
		}
253
	}
254
}
255

    
256
function propFilter( props, specialEasing ) {
257
	var index, name, easing, value, hooks;
258

    
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 ) ) {
265
			easing = value[ 1 ];
266
			value = props[ index ] = value[ 0 ];
267
		}
268

    
269
		if ( index !== name ) {
270
			props[ name ] = value;
271
			delete props[ index ];
272
		}
273

    
274
		hooks = jQuery.cssHooks[ name ];
275
		if ( hooks && "expand" in hooks ) {
276
			value = hooks.expand( value );
277
			delete props[ name ];
278

    
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;
285
				}
286
			}
287
		} else {
288
			specialEasing[ name ] = easing;
289
		}
290
	}
291
}
292

    
293
function Animation( elem, properties, options ) {
294
	var result,
295
		stopped,
296
		index = 0,
297
		length = Animation.prefilters.length,
298
		deferred = jQuery.Deferred().always( function() {
299

    
300
			// Don't match elem in the :animated selector
301
			delete tick.elem;
302
		} ),
303
		tick = function() {
304
			if ( stopped ) {
305
				return false;
306
			}
307
			var currentTime = fxNow || createFxNow(),
308
				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
309

    
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,
313
				percent = 1 - temp,
314
				index = 0,
315
				length = animation.tweens.length;
316

    
317
			for ( ; index < length; index++ ) {
318
				animation.tweens[ index ].run( percent );
319
			}
320

    
321
			deferred.notifyWith( elem, [ animation, percent, remaining ] );
322

    
323
			// If there's more to do, yield
324
			if ( percent < 1 && length ) {
325
				return remaining;
326
			}
327

    
328
			// If this was an empty animation, synthesize a final progress notification
329
			if ( !length ) {
330
				deferred.notifyWith( elem, [ animation, 1, 0 ] );
331
			}
332

    
333
			// Resolve the animation and report its conclusion
334
			deferred.resolveWith( elem, [ animation ] );
335
			return false;
336
		},
337
		animation = deferred.promise( {
338
			elem: elem,
339
			props: jQuery.extend( {}, properties ),
340
			opts: jQuery.extend( true, {
341
				specialEasing: {},
342
				easing: jQuery.easing._default
343
			}, options ),
344
			originalProperties: properties,
345
			originalOptions: options,
346
			startTime: fxNow || createFxNow(),
347
			duration: options.duration,
348
			tweens: [],
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 );
353
				return tween;
354
			},
355
			stop: function( gotoEnd ) {
356
				var index = 0,
357

    
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;
361
				if ( stopped ) {
362
					return this;
363
				}
364
				stopped = true;
365
				for ( ; index < length; index++ ) {
366
					animation.tweens[ index ].run( 1 );
367
				}
368

    
369
				// Resolve when we played the last frame; otherwise, reject
370
				if ( gotoEnd ) {
371
					deferred.notifyWith( elem, [ animation, 1, 0 ] );
372
					deferred.resolveWith( elem, [ animation, gotoEnd ] );
373
				} else {
374
					deferred.rejectWith( elem, [ animation, gotoEnd ] );
375
				}
376
				return this;
377
			}
378
		} ),
379
		props = animation.props;
380

    
381
	propFilter( props, animation.opts.specialEasing );
382

    
383
	for ( ; index < length; index++ ) {
384
		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
385
		if ( result ) {
386
			if ( jQuery.isFunction( result.stop ) ) {
387
				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
388
					jQuery.proxy( result.stop, result );
389
			}
390
			return result;
391
		}
392
	}
393

    
394
	jQuery.map( props, createTween, animation );
395

    
396
	if ( jQuery.isFunction( animation.opts.start ) ) {
397
		animation.opts.start.call( elem, animation );
398
	}
399

    
400
	// Attach callbacks from options
401
	animation
402
		.progress( animation.opts.progress )
403
		.done( animation.opts.done, animation.opts.complete )
404
		.fail( animation.opts.fail )
405
		.always( animation.opts.always );
406

    
407
	jQuery.fx.timer(
408
		jQuery.extend( tick, {
409
			elem: elem,
410
			anim: animation,
411
			queue: animation.opts.queue
412
		} )
413
	);
414

    
415
	return animation;
416
}
417

    
418
jQuery.Animation = jQuery.extend( Animation, {
419

    
420
	tweeners: {
421
		"*": [ function( prop, value ) {
422
			var tween = this.createTween( prop, value );
423
			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
424
			return tween;
425
		} ]
426
	},
427

    
428
	tweener: function( props, callback ) {
429
		if ( jQuery.isFunction( props ) ) {
430
			callback = props;
431
			props = [ "*" ];
432
		} else {
433
			props = props.match( rnothtmlwhite );
434
		}
435

    
436
		var prop,
437
			index = 0,
438
			length = props.length;
439

    
440
		for ( ; index < length; index++ ) {
441
			prop = props[ index ];
442
			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
443
			Animation.tweeners[ prop ].unshift( callback );
444
		}
445
	},
446

    
447
	prefilters: [ defaultPrefilter ],
448

    
449
	prefilter: function( callback, prepend ) {
450
		if ( prepend ) {
451
			Animation.prefilters.unshift( callback );
452
		} else {
453
			Animation.prefilters.push( callback );
454
		}
455
	}
456
} );
457

    
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,
462
		duration: speed,
463
		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
464
	};
465

    
466
	// Go to the end state if fx are off
467
	if ( jQuery.fx.off ) {
468
		opt.duration = 0;
469

    
470
	} else {
471
		if ( typeof opt.duration !== "number" ) {
472
			if ( opt.duration in jQuery.fx.speeds ) {
473
				opt.duration = jQuery.fx.speeds[ opt.duration ];
474

    
475
			} else {
476
				opt.duration = jQuery.fx.speeds._default;
477
			}
478
		}
479
	}
480

    
481
	// Normalize opt.queue - true/undefined/null -> "fx"
482
	if ( opt.queue == null || opt.queue === true ) {
483
		opt.queue = "fx";
484
	}
485

    
486
	// Queueing
487
	opt.old = opt.complete;
488

    
489
	opt.complete = function() {
490
		if ( jQuery.isFunction( opt.old ) ) {
491
			opt.old.call( this );
492
		}
493

    
494
		if ( opt.queue ) {
495
			jQuery.dequeue( this, opt.queue );
496
		}
497
	};
498

    
499
	return opt;
500
};
501

    
502
jQuery.fn.extend( {
503
	fadeTo: function( speed, to, easing, callback ) {
504

    
505
		// Show any hidden elements after setting opacity to 0
506
		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
507

    
508
			// Animate to the value specified
509
			.end().animate( { opacity: to }, speed, easing, callback );
510
	},
511
	animate: function( prop, speed, easing, callback ) {
512
		var empty = jQuery.isEmptyObject( prop ),
513
			optall = jQuery.speed( speed, easing, callback ),
514
			doAnimation = function() {
515

    
516
				// Operate on a copy of prop so per-property easing won't be lost
517
				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
518

    
519
				// Empty animations, or finishing resolves immediately
520
				if ( empty || dataPriv.get( this, "finish" ) ) {
521
					anim.stop( true );
522
				}
523
			};
524
			doAnimation.finish = doAnimation;
525

    
526
		return empty || optall.queue === false ?
527
			this.each( doAnimation ) :
528
			this.queue( optall.queue, doAnimation );
529
	},
530
	stop: function( type, clearQueue, gotoEnd ) {
531
		var stopQueue = function( hooks ) {
532
			var stop = hooks.stop;
533
			delete hooks.stop;
534
			stop( gotoEnd );
535
		};
536

    
537
		if ( typeof type !== "string" ) {
538
			gotoEnd = clearQueue;
539
			clearQueue = type;
540
			type = undefined;
541
		}
542
		if ( clearQueue && type !== false ) {
543
			this.queue( type || "fx", [] );
544
		}
545

    
546
		return this.each( function() {
547
			var dequeue = true,
548
				index = type != null && type + "queueHooks",
549
				timers = jQuery.timers,
550
				data = dataPriv.get( this );
551

    
552
			if ( index ) {
553
				if ( data[ index ] && data[ index ].stop ) {
554
					stopQueue( data[ index ] );
555
				}
556
			} else {
557
				for ( index in data ) {
558
					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
559
						stopQueue( data[ index ] );
560
					}
561
				}
562
			}
563

    
564
			for ( index = timers.length; index--; ) {
565
				if ( timers[ index ].elem === this &&
566
					( type == null || timers[ index ].queue === type ) ) {
567

    
568
					timers[ index ].anim.stop( gotoEnd );
569
					dequeue = false;
570
					timers.splice( index, 1 );
571
				}
572
			}
573

    
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 );
579
			}
580
		} );
581
	},
582
	finish: function( type ) {
583
		if ( type !== false ) {
584
			type = type || "fx";
585
		}
586
		return this.each( function() {
587
			var index,
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;
593

    
594
			// Enable finishing flag on private data
595
			data.finish = true;
596

    
597
			// Empty the queue first
598
			jQuery.queue( this, type, [] );
599

    
600
			if ( hooks && hooks.stop ) {
601
				hooks.stop.call( this, true );
602
			}
603

    
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 );
609
				}
610
			}
611

    
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 );
616
				}
617
			}
618

    
619
			// Turn off finishing flag
620
			delete data.finish;
621
		} );
622
	}
623
} );
624

    
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 );
631
	};
632
} );
633

    
634
// Generate shortcuts for custom animations
635
jQuery.each( {
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 );
645
	};
646
} );
647

    
648
jQuery.timers = [];
649
jQuery.fx.tick = function() {
650
	var timer,
651
		i = 0,
652
		timers = jQuery.timers;
653

    
654
	fxNow = jQuery.now();
655

    
656
	for ( ; i < timers.length; i++ ) {
657
		timer = timers[ i ];
658

    
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 );
662
		}
663
	}
664

    
665
	if ( !timers.length ) {
666
		jQuery.fx.stop();
667
	}
668
	fxNow = undefined;
669
};
670

    
671
jQuery.fx.timer = function( timer ) {
672
	jQuery.timers.push( timer );
673
	jQuery.fx.start();
674
};
675

    
676
jQuery.fx.interval = 13;
677
jQuery.fx.start = function() {
678
	if ( inProgress ) {
679
		return;
680
	}
681

    
682
	inProgress = true;
683
	schedule();
684
};
685

    
686
jQuery.fx.stop = function() {
687
	inProgress = null;
688
};
689

    
690
jQuery.fx.speeds = {
691
	slow: 600,
692
	fast: 200,
693

    
694
	// Default speed
695
	_default: 400
696
};
697

    
698
return jQuery;
699
} );
(11-11/22)