Test Failed
Branch master (45c182)
by Julien
04:02
created

resources/assets/jquery/src/effects.js   F

Complexity

Total Complexity 155
Complexity/F 3.88

Size

Lines of Code 693
Function Count 40

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 155
dl 0
loc 693
rs 2.2557
c 1
b 0
f 0
cc 0
nc 0
mnd 6
bc 133
fnc 40
bpm 3.325
cpm 3.875
noi 4

How to fix   Complexity   

Complexity

Complex classes like resources/assets/jquery/src/effects.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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, timerId,
27
	rfxtypes = /^(?:toggle|show|hide)$/,
28
	rrun = /queueHooks$/;
29
30
function raf() {
31
	if ( timerId ) {
32
		window.requestAnimationFrame( raf );
33
		jQuery.fx.tick();
34
	}
35
}
36
37
// Animations created synchronously will run synchronously
38
function createFxNow() {
39
	window.setTimeout( function() {
40
		fxNow = undefined;
41
	} );
42
	return ( fxNow = jQuery.now() );
43
}
44
45
// Generate parameters to create a standard animation
46
function genFx( type, includeWidth ) {
47
	var which,
48
		i = 0,
49
		attrs = { height: type };
50
51
	// If we include width, step value is 1 to do all cssExpand values,
52
	// otherwise step value is 2 to skip over Left and Right
53
	includeWidth = includeWidth ? 1 : 0;
54
	for ( ; i < 4; i += 2 - includeWidth ) {
55
		which = cssExpand[ i ];
56
		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
57
	}
58
59
	if ( includeWidth ) {
60
		attrs.opacity = attrs.width = type;
61
	}
62
63
	return attrs;
64
}
65
66
function createTween( value, prop, animation ) {
67
	var tween,
68
		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
69
		index = 0,
70
		length = collection.length;
71
	for ( ; index < length; index++ ) {
72
		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
73
74
			// We're done with this property
75
			return tween;
76
		}
77
	}
78
}
79
80
function defaultPrefilter( elem, props, opts ) {
81
	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
82
		isBox = "width" in props || "height" in props,
83
		anim = this,
84
		orig = {},
85
		style = elem.style,
86
		hidden = elem.nodeType && isHiddenWithinTree( elem ),
87
		dataShow = dataPriv.get( elem, "fxshow" );
88
89
	// Queue-skipping animations hijack the fx hooks
90
	if ( !opts.queue ) {
91
		hooks = jQuery._queueHooks( elem, "fx" );
92
		if ( hooks.unqueued == null ) {
93
			hooks.unqueued = 0;
94
			oldfire = hooks.empty.fire;
95
			hooks.empty.fire = function() {
96
				if ( !hooks.unqueued ) {
97
					oldfire();
98
				}
99
			};
100
		}
101
		hooks.unqueued++;
102
103
		anim.always( function() {
104
105
			// Ensure the complete handler is called before this completes
106
			anim.always( function() {
107
				hooks.unqueued--;
108
				if ( !jQuery.queue( elem, "fx" ).length ) {
109
					hooks.empty.fire();
110
				}
111
			} );
112
		} );
113
	}
114
115
	// Detect show/hide animations
116
	for ( prop in props ) {
117
		value = props[ prop ];
118
		if ( rfxtypes.test( value ) ) {
119
			delete props[ prop ];
120
			toggle = toggle || value === "toggle";
121
			if ( value === ( hidden ? "hide" : "show" ) ) {
122
123
				// Pretend to be hidden if this is a "show" and
124
				// there is still data from a stopped show/hide
125
				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
126
					hidden = true;
127
128
				// Ignore all other no-op show/hide data
129
				} else {
130
					continue;
131
				}
132
			}
133
			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
134
		}
135
	}
136
137
	// Bail out if this is a no-op like .hide().hide()
138
	propTween = !jQuery.isEmptyObject( props );
139
	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
140
		return;
141
	}
142
143
	// Restrict "overflow" and "display" styles during box animations
144
	if ( isBox && elem.nodeType === 1 ) {
145
146
		// Support: IE <=9 - 11, Edge 12 - 13
147
		// Record all 3 overflow attributes because IE does not infer the shorthand
148
		// from identically-valued overflowX and overflowY
149
		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
150
151
		// Identify a display type, preferring old show/hide data over the CSS cascade
152
		restoreDisplay = dataShow && dataShow.display;
153
		if ( restoreDisplay == null ) {
154
			restoreDisplay = dataPriv.get( elem, "display" );
155
		}
156
		display = jQuery.css( elem, "display" );
157
		if ( display === "none" ) {
158
			if ( restoreDisplay ) {
159
				display = restoreDisplay;
160
			} else {
161
162
				// Get nonempty value(s) by temporarily forcing visibility
163
				showHide( [ elem ], true );
164
				restoreDisplay = elem.style.display || restoreDisplay;
165
				display = jQuery.css( elem, "display" );
166
				showHide( [ elem ] );
167
			}
168
		}
169
170
		// Animate inline elements as inline-block
171
		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
172
			if ( jQuery.css( elem, "float" ) === "none" ) {
173
174
				// Restore the original display value at the end of pure show/hide animations
175
				if ( !propTween ) {
176
					anim.done( function() {
177
						style.display = restoreDisplay;
178
					} );
179
					if ( restoreDisplay == null ) {
180
						display = style.display;
181
						restoreDisplay = display === "none" ? "" : display;
182
					}
183
				}
184
				style.display = "inline-block";
185
			}
186
		}
187
	}
188
189
	if ( opts.overflow ) {
190
		style.overflow = "hidden";
191
		anim.always( function() {
192
			style.overflow = opts.overflow[ 0 ];
193
			style.overflowX = opts.overflow[ 1 ];
194
			style.overflowY = opts.overflow[ 2 ];
195
		} );
196
	}
197
198
	// Implement show/hide animations
199
	propTween = false;
200
	for ( prop in orig ) {
201
202
		// General show/hide setup for this element animation
203
		if ( !propTween ) {
204
			if ( dataShow ) {
205
				if ( "hidden" in dataShow ) {
206
					hidden = dataShow.hidden;
207
				}
208
			} else {
209
				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
210
			}
211
212
			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
213
			if ( toggle ) {
214
				dataShow.hidden = !hidden;
215
			}
216
217
			// Show elements before animating them
218
			if ( hidden ) {
219
				showHide( [ elem ], true );
220
			}
221
222
			/* eslint-disable no-loop-func */
223
224
			anim.done( function() {
225
226
			/* eslint-enable no-loop-func */
227
228
				// The final step of a "hide" animation is actually hiding the element
229
				if ( !hidden ) {
230
					showHide( [ elem ] );
231
				}
232
				dataPriv.remove( elem, "fxshow" );
233
				for ( prop in orig ) {
234
					jQuery.style( elem, prop, orig[ prop ] );
235
				}
236
			} );
237
		}
238
239
		// Per-property setup
240
		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
241
		if ( !( prop in dataShow ) ) {
242
			dataShow[ prop ] = propTween.start;
243
			if ( hidden ) {
244
				propTween.end = propTween.start;
245
				propTween.start = 0;
246
			}
247
		}
248
	}
249
}
250
251
function propFilter( props, specialEasing ) {
252
	var index, name, easing, value, hooks;
253
254
	// camelCase, specialEasing and expand cssHook pass
255
	for ( index in props ) {
256
		name = jQuery.camelCase( index );
257
		easing = specialEasing[ name ];
258
		value = props[ index ];
259
		if ( jQuery.isArray( value ) ) {
260
			easing = value[ 1 ];
261
			value = props[ index ] = value[ 0 ];
262
		}
263
264
		if ( index !== name ) {
265
			props[ name ] = value;
266
			delete props[ index ];
267
		}
268
269
		hooks = jQuery.cssHooks[ name ];
270
		if ( hooks && "expand" in hooks ) {
271
			value = hooks.expand( value );
272
			delete props[ name ];
273
274
			// Not quite $.extend, this won't overwrite existing keys.
275
			// Reusing 'index' because we have the correct "name"
276
			for ( index in value ) {
277
				if ( !( index in props ) ) {
278
					props[ index ] = value[ index ];
279
					specialEasing[ index ] = easing;
280
				}
281
			}
282
		} else {
283
			specialEasing[ name ] = easing;
284
		}
285
	}
286
}
287
288
function Animation( elem, properties, options ) {
289
	var result,
290
		stopped,
291
		index = 0,
292
		length = Animation.prefilters.length,
293
		deferred = jQuery.Deferred().always( function() {
294
295
			// Don't match elem in the :animated selector
296
			delete tick.elem;
297
		} ),
298
		tick = function() {
299
			if ( stopped ) {
300
				return false;
301
			}
302
			var currentTime = fxNow || createFxNow(),
303
				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
304
305
				// Support: Android 2.3 only
306
				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
307
				temp = remaining / animation.duration || 0,
308
				percent = 1 - temp,
309
				index = 0,
310
				length = animation.tweens.length;
311
312
			for ( ; index < length; index++ ) {
313
				animation.tweens[ index ].run( percent );
314
			}
315
316
			deferred.notifyWith( elem, [ animation, percent, remaining ] );
317
318
			if ( percent < 1 && length ) {
319
				return remaining;
320
			} else {
321
				deferred.resolveWith( elem, [ animation ] );
322
				return false;
323
			}
324
		},
325
		animation = deferred.promise( {
326
			elem: elem,
327
			props: jQuery.extend( {}, properties ),
328
			opts: jQuery.extend( true, {
329
				specialEasing: {},
330
				easing: jQuery.easing._default
331
			}, options ),
332
			originalProperties: properties,
333
			originalOptions: options,
334
			startTime: fxNow || createFxNow(),
335
			duration: options.duration,
336
			tweens: [],
337
			createTween: function( prop, end ) {
338
				var tween = jQuery.Tween( elem, animation.opts, prop, end,
339
						animation.opts.specialEasing[ prop ] || animation.opts.easing );
340
				animation.tweens.push( tween );
341
				return tween;
342
			},
343
			stop: function( gotoEnd ) {
344
				var index = 0,
345
346
					// If we are going to the end, we want to run all the tweens
347
					// otherwise we skip this part
348
					length = gotoEnd ? animation.tweens.length : 0;
349
				if ( stopped ) {
350
					return this;
351
				}
352
				stopped = true;
353
				for ( ; index < length; index++ ) {
354
					animation.tweens[ index ].run( 1 );
355
				}
356
357
				// Resolve when we played the last frame; otherwise, reject
358
				if ( gotoEnd ) {
359
					deferred.notifyWith( elem, [ animation, 1, 0 ] );
360
					deferred.resolveWith( elem, [ animation, gotoEnd ] );
361
				} else {
362
					deferred.rejectWith( elem, [ animation, gotoEnd ] );
363
				}
364
				return this;
365
			}
366
		} ),
367
		props = animation.props;
368
369
	propFilter( props, animation.opts.specialEasing );
370
371
	for ( ; index < length; index++ ) {
372
		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
373
		if ( result ) {
374
			if ( jQuery.isFunction( result.stop ) ) {
375
				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
376
					jQuery.proxy( result.stop, result );
377
			}
378
			return result;
379
		}
380
	}
381
382
	jQuery.map( props, createTween, animation );
383
384
	if ( jQuery.isFunction( animation.opts.start ) ) {
385
		animation.opts.start.call( elem, animation );
386
	}
387
388
	jQuery.fx.timer(
389
		jQuery.extend( tick, {
390
			elem: elem,
391
			anim: animation,
392
			queue: animation.opts.queue
393
		} )
394
	);
395
396
	// attach callbacks from options
397
	return animation.progress( animation.opts.progress )
398
		.done( animation.opts.done, animation.opts.complete )
399
		.fail( animation.opts.fail )
400
		.always( animation.opts.always );
401
}
402
403
jQuery.Animation = jQuery.extend( Animation, {
404
405
	tweeners: {
406
		"*": [ function( prop, value ) {
407
			var tween = this.createTween( prop, value );
408
			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
409
			return tween;
410
		} ]
411
	},
412
413
	tweener: function( props, callback ) {
414
		if ( jQuery.isFunction( props ) ) {
415
			callback = props;
416
			props = [ "*" ];
417
		} else {
418
			props = props.match( rnothtmlwhite );
419
		}
420
421
		var prop,
422
			index = 0,
423
			length = props.length;
424
425
		for ( ; index < length; index++ ) {
426
			prop = props[ index ];
427
			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
428
			Animation.tweeners[ prop ].unshift( callback );
429
		}
430
	},
431
432
	prefilters: [ defaultPrefilter ],
433
434
	prefilter: function( callback, prepend ) {
435
		if ( prepend ) {
436
			Animation.prefilters.unshift( callback );
437
		} else {
438
			Animation.prefilters.push( callback );
439
		}
440
	}
441
} );
442
443
jQuery.speed = function( speed, easing, fn ) {
444
	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
445
		complete: fn || !fn && easing ||
446
			jQuery.isFunction( speed ) && speed,
447
		duration: speed,
448
		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
449
	};
450
451
	// Go to the end state if fx are off or if document is hidden
452
	if ( jQuery.fx.off || document.hidden ) {
453
		opt.duration = 0;
454
455
	} else {
456
		if ( typeof opt.duration !== "number" ) {
457
			if ( opt.duration in jQuery.fx.speeds ) {
458
				opt.duration = jQuery.fx.speeds[ opt.duration ];
459
460
			} else {
461
				opt.duration = jQuery.fx.speeds._default;
462
			}
463
		}
464
	}
465
466
	// Normalize opt.queue - true/undefined/null -> "fx"
467
	if ( opt.queue == null || opt.queue === true ) {
468
		opt.queue = "fx";
469
	}
470
471
	// Queueing
472
	opt.old = opt.complete;
473
474
	opt.complete = function() {
475
		if ( jQuery.isFunction( opt.old ) ) {
476
			opt.old.call( this );
477
		}
478
479
		if ( opt.queue ) {
480
			jQuery.dequeue( this, opt.queue );
481
		}
482
	};
483
484
	return opt;
485
};
486
487
jQuery.fn.extend( {
488
	fadeTo: function( speed, to, easing, callback ) {
489
490
		// Show any hidden elements after setting opacity to 0
491
		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
492
493
			// Animate to the value specified
494
			.end().animate( { opacity: to }, speed, easing, callback );
495
	},
496
	animate: function( prop, speed, easing, callback ) {
497
		var empty = jQuery.isEmptyObject( prop ),
498
			optall = jQuery.speed( speed, easing, callback ),
499
			doAnimation = function() {
500
501
				// Operate on a copy of prop so per-property easing won't be lost
502
				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
503
504
				// Empty animations, or finishing resolves immediately
505
				if ( empty || dataPriv.get( this, "finish" ) ) {
506
					anim.stop( true );
507
				}
508
			};
509
			doAnimation.finish = doAnimation;
510
511
		return empty || optall.queue === false ?
512
			this.each( doAnimation ) :
513
			this.queue( optall.queue, doAnimation );
514
	},
515
	stop: function( type, clearQueue, gotoEnd ) {
516
		var stopQueue = function( hooks ) {
517
			var stop = hooks.stop;
518
			delete hooks.stop;
519
			stop( gotoEnd );
520
		};
521
522
		if ( typeof type !== "string" ) {
523
			gotoEnd = clearQueue;
524
			clearQueue = type;
525
			type = undefined;
526
		}
527
		if ( clearQueue && type !== false ) {
528
			this.queue( type || "fx", [] );
529
		}
530
531
		return this.each( function() {
532
			var dequeue = true,
533
				index = type != null && type + "queueHooks",
534
				timers = jQuery.timers,
535
				data = dataPriv.get( this );
536
537
			if ( index ) {
538
				if ( data[ index ] && data[ index ].stop ) {
539
					stopQueue( data[ index ] );
540
				}
541
			} else {
542
				for ( index in data ) {
543
					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
544
						stopQueue( data[ index ] );
545
					}
546
				}
547
			}
548
549
			for ( index = timers.length; index--; ) {
550
				if ( timers[ index ].elem === this &&
551
					( type == null || timers[ index ].queue === type ) ) {
552
553
					timers[ index ].anim.stop( gotoEnd );
554
					dequeue = false;
555
					timers.splice( index, 1 );
556
				}
557
			}
558
559
			// Start the next in the queue if the last step wasn't forced.
560
			// Timers currently will call their complete callbacks, which
561
			// will dequeue but only if they were gotoEnd.
562
			if ( dequeue || !gotoEnd ) {
563
				jQuery.dequeue( this, type );
564
			}
565
		} );
566
	},
567
	finish: function( type ) {
568
		if ( type !== false ) {
569
			type = type || "fx";
570
		}
571
		return this.each( function() {
572
			var index,
573
				data = dataPriv.get( this ),
574
				queue = data[ type + "queue" ],
575
				hooks = data[ type + "queueHooks" ],
576
				timers = jQuery.timers,
577
				length = queue ? queue.length : 0;
578
579
			// Enable finishing flag on private data
580
			data.finish = true;
581
582
			// Empty the queue first
583
			jQuery.queue( this, type, [] );
584
585
			if ( hooks && hooks.stop ) {
586
				hooks.stop.call( this, true );
587
			}
588
589
			// Look for any active animations, and finish them
590
			for ( index = timers.length; index--; ) {
591
				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
592
					timers[ index ].anim.stop( true );
593
					timers.splice( index, 1 );
594
				}
595
			}
596
597
			// Look for any animations in the old queue and finish them
598
			for ( index = 0; index < length; index++ ) {
599
				if ( queue[ index ] && queue[ index ].finish ) {
600
					queue[ index ].finish.call( this );
601
				}
602
			}
603
604
			// Turn off finishing flag
605
			delete data.finish;
606
		} );
607
	}
608
} );
609
610
jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
611
	var cssFn = jQuery.fn[ name ];
612
	jQuery.fn[ name ] = function( speed, easing, callback ) {
613
		return speed == null || typeof speed === "boolean" ?
614
			cssFn.apply( this, arguments ) :
615
			this.animate( genFx( name, true ), speed, easing, callback );
616
	};
617
} );
618
619
// Generate shortcuts for custom animations
620
jQuery.each( {
621
	slideDown: genFx( "show" ),
622
	slideUp: genFx( "hide" ),
623
	slideToggle: genFx( "toggle" ),
624
	fadeIn: { opacity: "show" },
625
	fadeOut: { opacity: "hide" },
626
	fadeToggle: { opacity: "toggle" }
627
}, function( name, props ) {
628
	jQuery.fn[ name ] = function( speed, easing, callback ) {
629
		return this.animate( props, speed, easing, callback );
630
	};
631
} );
632
633
jQuery.timers = [];
634
jQuery.fx.tick = function() {
635
	var timer,
636
		i = 0,
637
		timers = jQuery.timers;
638
639
	fxNow = jQuery.now();
640
641
	for ( ; i < timers.length; i++ ) {
642
		timer = timers[ i ];
643
644
		// Checks the timer has not already been removed
645
		if ( !timer() && timers[ i ] === timer ) {
646
			timers.splice( i--, 1 );
647
		}
648
	}
649
650
	if ( !timers.length ) {
651
		jQuery.fx.stop();
652
	}
653
	fxNow = undefined;
654
};
655
656
jQuery.fx.timer = function( timer ) {
657
	jQuery.timers.push( timer );
658
	if ( timer() ) {
659
		jQuery.fx.start();
660
	} else {
661
		jQuery.timers.pop();
662
	}
663
};
664
665
jQuery.fx.interval = 13;
666
jQuery.fx.start = function() {
667
	if ( !timerId ) {
668
		timerId = window.requestAnimationFrame ?
669
			window.requestAnimationFrame( raf ) :
670
			window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
671
	}
672
};
673
674
jQuery.fx.stop = function() {
675
	if ( window.cancelAnimationFrame ) {
676
		window.cancelAnimationFrame( timerId );
677
	} else {
678
		window.clearInterval( timerId );
679
	}
680
681
	timerId = null;
682
};
683
684
jQuery.fx.speeds = {
685
	slow: 600,
686
	fast: 200,
687
688
	// Default speed
689
	_default: 400
690
};
691
692
return jQuery;
693
} );
694