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

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

Complexity

Total Complexity 161
Complexity/F 4.74

Size

Lines of Code 745
Function Count 34

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 161
dl 0
loc 745
rs 2.1818
c 1
b 0
f 0
cc 0
nc 0
mnd 6
bc 113
fnc 34
bpm 3.3235
cpm 4.7352
noi 13

How to fix   Complexity   

Complexity

Complex classes like resources/assets/jquery/src/event.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/documentElement",
5
	"./var/rnothtmlwhite",
6
	"./var/slice",
7
	"./data/var/dataPriv",
8
9
	"./core/init",
10
	"./selector"
11
], function( jQuery, document, documentElement, rnothtmlwhite, slice, dataPriv ) {
12
13
"use strict";
14
15
var
16
	rkeyEvent = /^key/,
17
	rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
18
	rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
19
20
function returnTrue() {
21
	return true;
22
}
23
24
function returnFalse() {
25
	return false;
26
}
27
28
// Support: IE <=9 only
29
// See #13393 for more info
30
function safeActiveElement() {
31
	try {
32
		return document.activeElement;
33
	} catch ( err ) { }
34
}
35
36
function on( elem, types, selector, data, fn, one ) {
37
	var origFn, type;
38
39
	// Types can be a map of types/handlers
40
	if ( typeof types === "object" ) {
41
42
		// ( types-Object, selector, data )
43
		if ( typeof selector !== "string" ) {
44
45
			// ( types-Object, data )
46
			data = data || selector;
47
			selector = undefined;
48
		}
49
		for ( type in types ) {
50
			on( elem, type, selector, data, types[ type ], one );
51
		}
52
		return elem;
53
	}
54
55
	if ( data == null && fn == null ) {
56
57
		// ( types, fn )
58
		fn = selector;
59
		data = selector = undefined;
60
	} else if ( fn == null ) {
61
		if ( typeof selector === "string" ) {
62
63
			// ( types, selector, fn )
64
			fn = data;
65
			data = undefined;
66
		} else {
67
68
			// ( types, data, fn )
69
			fn = data;
70
			data = selector;
71
			selector = undefined;
72
		}
73
	}
74
	if ( fn === false ) {
75
		fn = returnFalse;
76
	} else if ( !fn ) {
77
		return elem;
78
	}
79
80
	if ( one === 1 ) {
81
		origFn = fn;
82
		fn = function( event ) {
83
84
			// Can use an empty set, since event contains the info
85
			jQuery().off( event );
86
			return origFn.apply( this, arguments );
87
		};
88
89
		// Use same guid so caller can remove using origFn
90
		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
91
	}
92
	return elem.each( function() {
93
		jQuery.event.add( this, types, fn, data, selector );
94
	} );
95
}
96
97
/*
98
 * Helper functions for managing events -- not part of the public interface.
99
 * Props to Dean Edwards' addEvent library for many of the ideas.
100
 */
101
jQuery.event = {
102
103
	global: {},
104
105
	add: function( elem, types, handler, data, selector ) {
106
107
		var handleObjIn, eventHandle, tmp,
108
			events, t, handleObj,
109
			special, handlers, type, namespaces, origType,
110
			elemData = dataPriv.get( elem );
111
112
		// Don't attach events to noData or text/comment nodes (but allow plain objects)
113
		if ( !elemData ) {
114
			return;
115
		}
116
117
		// Caller can pass in an object of custom data in lieu of the handler
118
		if ( handler.handler ) {
119
			handleObjIn = handler;
120
			handler = handleObjIn.handler;
121
			selector = handleObjIn.selector;
122
		}
123
124
		// Ensure that invalid selectors throw exceptions at attach time
125
		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
126
		if ( selector ) {
127
			jQuery.find.matchesSelector( documentElement, selector );
128
		}
129
130
		// Make sure that the handler has a unique ID, used to find/remove it later
131
		if ( !handler.guid ) {
132
			handler.guid = jQuery.guid++;
133
		}
134
135
		// Init the element's event structure and main handler, if this is the first
136
		if ( !( events = elemData.events ) ) {
137
			events = elemData.events = {};
138
		}
139
		if ( !( eventHandle = elemData.handle ) ) {
140
			eventHandle = elemData.handle = function( e ) {
141
142
				// Discard the second event of a jQuery.event.trigger() and
143
				// when an event is called after a page has unloaded
144
				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
145
					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
146
			};
147
		}
148
149
		// Handle multiple events separated by a space
150
		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
151
		t = types.length;
152
		while ( t-- ) {
153
			tmp = rtypenamespace.exec( types[ t ] ) || [];
154
			type = origType = tmp[ 1 ];
155
			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
156
157
			// There *must* be a type, no attaching namespace-only handlers
158
			if ( !type ) {
159
				continue;
160
			}
161
162
			// If event changes its type, use the special event handlers for the changed type
163
			special = jQuery.event.special[ type ] || {};
164
165
			// If selector defined, determine special event api type, otherwise given type
166
			type = ( selector ? special.delegateType : special.bindType ) || type;
167
168
			// Update special based on newly reset type
169
			special = jQuery.event.special[ type ] || {};
170
171
			// handleObj is passed to all event handlers
172
			handleObj = jQuery.extend( {
173
				type: type,
174
				origType: origType,
175
				data: data,
176
				handler: handler,
177
				guid: handler.guid,
178
				selector: selector,
179
				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
180
				namespace: namespaces.join( "." )
181
			}, handleObjIn );
182
183
			// Init the event handler queue if we're the first
184
			if ( !( handlers = events[ type ] ) ) {
185
				handlers = events[ type ] = [];
186
				handlers.delegateCount = 0;
187
188
				// Only use addEventListener if the special events handler returns false
189
				if ( !special.setup ||
190
					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
191
192
					if ( elem.addEventListener ) {
193
						elem.addEventListener( type, eventHandle );
194
					}
195
				}
196
			}
197
198
			if ( special.add ) {
199
				special.add.call( elem, handleObj );
200
201
				if ( !handleObj.handler.guid ) {
202
					handleObj.handler.guid = handler.guid;
203
				}
204
			}
205
206
			// Add to the element's handler list, delegates in front
207
			if ( selector ) {
208
				handlers.splice( handlers.delegateCount++, 0, handleObj );
209
			} else {
210
				handlers.push( handleObj );
211
			}
212
213
			// Keep track of which events have ever been used, for event optimization
214
			jQuery.event.global[ type ] = true;
215
		}
216
217
	},
218
219
	// Detach an event or set of events from an element
220
	remove: function( elem, types, handler, selector, mappedTypes ) {
221
222
		var j, origCount, tmp,
223
			events, t, handleObj,
224
			special, handlers, type, namespaces, origType,
225
			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
226
227
		if ( !elemData || !( events = elemData.events ) ) {
228
			return;
229
		}
230
231
		// Once for each type.namespace in types; type may be omitted
232
		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
233
		t = types.length;
234
		while ( t-- ) {
235
			tmp = rtypenamespace.exec( types[ t ] ) || [];
236
			type = origType = tmp[ 1 ];
237
			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
238
239
			// Unbind all events (on this namespace, if provided) for the element
240
			if ( !type ) {
241
				for ( type in events ) {
242
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
243
				}
244
				continue;
245
			}
246
247
			special = jQuery.event.special[ type ] || {};
248
			type = ( selector ? special.delegateType : special.bindType ) || type;
249
			handlers = events[ type ] || [];
250
			tmp = tmp[ 2 ] &&
251
				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
252
253
			// Remove matching events
254
			origCount = j = handlers.length;
255
			while ( j-- ) {
256
				handleObj = handlers[ j ];
257
258
				if ( ( mappedTypes || origType === handleObj.origType ) &&
259
					( !handler || handler.guid === handleObj.guid ) &&
260
					( !tmp || tmp.test( handleObj.namespace ) ) &&
261
					( !selector || selector === handleObj.selector ||
262
						selector === "**" && handleObj.selector ) ) {
263
					handlers.splice( j, 1 );
264
265
					if ( handleObj.selector ) {
266
						handlers.delegateCount--;
267
					}
268
					if ( special.remove ) {
269
						special.remove.call( elem, handleObj );
270
					}
271
				}
272
			}
273
274
			// Remove generic event handler if we removed something and no more handlers exist
275
			// (avoids potential for endless recursion during removal of special event handlers)
276
			if ( origCount && !handlers.length ) {
277
				if ( !special.teardown ||
278
					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
279
280
					jQuery.removeEvent( elem, type, elemData.handle );
281
				}
282
283
				delete events[ type ];
284
			}
285
		}
286
287
		// Remove data and the expando if it's no longer used
288
		if ( jQuery.isEmptyObject( events ) ) {
289
			dataPriv.remove( elem, "handle events" );
290
		}
291
	},
292
293
	dispatch: function( nativeEvent ) {
294
295
		// Make a writable jQuery.Event from the native event object
296
		var event = jQuery.event.fix( nativeEvent );
297
298
		var i, j, ret, matched, handleObj, handlerQueue,
299
			args = new Array( arguments.length ),
300
			handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
301
			special = jQuery.event.special[ event.type ] || {};
302
303
		// Use the fix-ed jQuery.Event rather than the (read-only) native event
304
		args[ 0 ] = event;
305
306
		for ( i = 1; i < arguments.length; i++ ) {
307
			args[ i ] = arguments[ i ];
308
		}
309
310
		event.delegateTarget = this;
311
312
		// Call the preDispatch hook for the mapped type, and let it bail if desired
313
		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
314
			return;
315
		}
316
317
		// Determine handlers
318
		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
319
320
		// Run delegates first; they may want to stop propagation beneath us
321
		i = 0;
322
		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
323
			event.currentTarget = matched.elem;
324
325
			j = 0;
326
			while ( ( handleObj = matched.handlers[ j++ ] ) &&
327
				!event.isImmediatePropagationStopped() ) {
328
329
				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
330
				// a subset or equal to those in the bound event (both can have no namespace).
331
				if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
332
333
					event.handleObj = handleObj;
334
					event.data = handleObj.data;
335
336
					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
337
						handleObj.handler ).apply( matched.elem, args );
338
339
					if ( ret !== undefined ) {
340
						if ( ( event.result = ret ) === false ) {
341
							event.preventDefault();
342
							event.stopPropagation();
343
						}
344
					}
345
				}
346
			}
347
		}
348
349
		// Call the postDispatch hook for the mapped type
350
		if ( special.postDispatch ) {
351
			special.postDispatch.call( this, event );
352
		}
353
354
		return event.result;
355
	},
356
357
	handlers: function( event, handlers ) {
358
		var i, handleObj, sel, matchedHandlers, matchedSelectors,
359
			handlerQueue = [],
360
			delegateCount = handlers.delegateCount,
361
			cur = event.target;
362
363
		// Find delegate handlers
364
		if ( delegateCount &&
365
366
			// Support: IE <=9
367
			// Black-hole SVG <use> instance trees (trac-13180)
368
			cur.nodeType &&
369
370
			// Support: Firefox <=42
371
			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
372
			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
373
			// Support: IE 11 only
374
			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
375
			!( event.type === "click" && event.button >= 1 ) ) {
376
377
			for ( ; cur !== this; cur = cur.parentNode || this ) {
378
379
				// Don't check non-elements (#13208)
380
				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
381
				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
382
					matchedHandlers = [];
383
					matchedSelectors = {};
384
					for ( i = 0; i < delegateCount; i++ ) {
385
						handleObj = handlers[ i ];
386
387
						// Don't conflict with Object.prototype properties (#13203)
388
						sel = handleObj.selector + " ";
389
390
						if ( matchedSelectors[ sel ] === undefined ) {
391
							matchedSelectors[ sel ] = handleObj.needsContext ?
392
								jQuery( sel, this ).index( cur ) > -1 :
393
								jQuery.find( sel, this, null, [ cur ] ).length;
394
						}
395
						if ( matchedSelectors[ sel ] ) {
396
							matchedHandlers.push( handleObj );
397
						}
398
					}
399
					if ( matchedHandlers.length ) {
400
						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
401
					}
402
				}
403
			}
404
		}
405
406
		// Add the remaining (directly-bound) handlers
407
		cur = this;
408
		if ( delegateCount < handlers.length ) {
409
			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
410
		}
411
412
		return handlerQueue;
413
	},
414
415
	addProp: function( name, hook ) {
416
		Object.defineProperty( jQuery.Event.prototype, name, {
417
			enumerable: true,
418
			configurable: true,
419
420
			get: jQuery.isFunction( hook ) ?
421
				function() {
422
					if ( this.originalEvent ) {
423
							return hook( this.originalEvent );
424
					}
425
				} :
426
				function() {
427
					if ( this.originalEvent ) {
428
							return this.originalEvent[ name ];
429
					}
430
				},
431
432
			set: function( value ) {
433
				Object.defineProperty( this, name, {
434
					enumerable: true,
435
					configurable: true,
436
					writable: true,
437
					value: value
438
				} );
439
			}
440
		} );
441
	},
442
443
	fix: function( originalEvent ) {
444
		return originalEvent[ jQuery.expando ] ?
445
			originalEvent :
446
			new jQuery.Event( originalEvent );
447
	},
448
449
	special: {
450
		load: {
451
452
			// Prevent triggered image.load events from bubbling to window.load
453
			noBubble: true
454
		},
455
		focus: {
456
457
			// Fire native event if possible so blur/focus sequence is correct
458
			trigger: function() {
459
				if ( this !== safeActiveElement() && this.focus ) {
460
					this.focus();
461
					return false;
462
				}
463
			},
464
			delegateType: "focusin"
465
		},
466
		blur: {
467
			trigger: function() {
468
				if ( this === safeActiveElement() && this.blur ) {
469
					this.blur();
470
					return false;
471
				}
472
			},
473
			delegateType: "focusout"
474
		},
475
		click: {
476
477
			// For checkbox, fire native event so checked state will be right
478
			trigger: function() {
479
				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
480
					this.click();
481
					return false;
482
				}
483
			},
484
485
			// For cross-browser consistency, don't fire native .click() on links
486
			_default: function( event ) {
487
				return jQuery.nodeName( event.target, "a" );
488
			}
489
		},
490
491
		beforeunload: {
492
			postDispatch: function( event ) {
493
494
				// Support: Firefox 20+
495
				// Firefox doesn't alert if the returnValue field is not set.
496
				if ( event.result !== undefined && event.originalEvent ) {
497
					event.originalEvent.returnValue = event.result;
498
				}
499
			}
500
		}
501
	}
502
};
503
504
jQuery.removeEvent = function( elem, type, handle ) {
505
506
	// This "if" is needed for plain objects
507
	if ( elem.removeEventListener ) {
508
		elem.removeEventListener( type, handle );
509
	}
510
};
511
512
jQuery.Event = function( src, props ) {
513
514
	// Allow instantiation without the 'new' keyword
515
	if ( !( this instanceof jQuery.Event ) ) {
516
		return new jQuery.Event( src, props );
517
	}
518
519
	// Event object
520
	if ( src && src.type ) {
521
		this.originalEvent = src;
522
		this.type = src.type;
523
524
		// Events bubbling up the document may have been marked as prevented
525
		// by a handler lower down the tree; reflect the correct value.
526
		this.isDefaultPrevented = src.defaultPrevented ||
527
				src.defaultPrevented === undefined &&
528
529
				// Support: Android <=2.3 only
530
				src.returnValue === false ?
531
			returnTrue :
532
			returnFalse;
533
534
		// Create target properties
535
		// Support: Safari <=6 - 7 only
536
		// Target should not be a text node (#504, #13143)
537
		this.target = ( src.target && src.target.nodeType === 3 ) ?
538
			src.target.parentNode :
539
			src.target;
540
541
		this.currentTarget = src.currentTarget;
542
		this.relatedTarget = src.relatedTarget;
543
544
	// Event type
545
	} else {
546
		this.type = src;
547
	}
548
549
	// Put explicitly provided properties onto the event object
550
	if ( props ) {
551
		jQuery.extend( this, props );
552
	}
553
554
	// Create a timestamp if incoming event doesn't have one
555
	this.timeStamp = src && src.timeStamp || jQuery.now();
556
557
	// Mark it as fixed
558
	this[ jQuery.expando ] = true;
559
};
560
561
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
562
// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
563
jQuery.Event.prototype = {
564
	constructor: jQuery.Event,
565
	isDefaultPrevented: returnFalse,
566
	isPropagationStopped: returnFalse,
567
	isImmediatePropagationStopped: returnFalse,
568
	isSimulated: false,
569
570
	preventDefault: function() {
571
		var e = this.originalEvent;
572
573
		this.isDefaultPrevented = returnTrue;
574
575
		if ( e && !this.isSimulated ) {
576
			e.preventDefault();
577
		}
578
	},
579
	stopPropagation: function() {
580
		var e = this.originalEvent;
581
582
		this.isPropagationStopped = returnTrue;
583
584
		if ( e && !this.isSimulated ) {
585
			e.stopPropagation();
586
		}
587
	},
588
	stopImmediatePropagation: function() {
589
		var e = this.originalEvent;
590
591
		this.isImmediatePropagationStopped = returnTrue;
592
593
		if ( e && !this.isSimulated ) {
594
			e.stopImmediatePropagation();
595
		}
596
597
		this.stopPropagation();
598
	}
599
};
600
601
// Includes all common event props including KeyEvent and MouseEvent specific props
602
jQuery.each( {
603
	altKey: true,
604
	bubbles: true,
605
	cancelable: true,
606
	changedTouches: true,
607
	ctrlKey: true,
608
	detail: true,
609
	eventPhase: true,
610
	metaKey: true,
611
	pageX: true,
612
	pageY: true,
613
	shiftKey: true,
614
	view: true,
615
	"char": true,
616
	charCode: true,
617
	key: true,
618
	keyCode: true,
619
	button: true,
620
	buttons: true,
621
	clientX: true,
622
	clientY: true,
623
	offsetX: true,
624
	offsetY: true,
625
	pointerId: true,
626
	pointerType: true,
627
	screenX: true,
628
	screenY: true,
629
	targetTouches: true,
630
	toElement: true,
631
	touches: true,
632
633
	which: function( event ) {
634
		var button = event.button;
635
636
		// Add which for key events
637
		if ( event.which == null && rkeyEvent.test( event.type ) ) {
638
			return event.charCode != null ? event.charCode : event.keyCode;
639
		}
640
641
		// Add which for click: 1 === left; 2 === middle; 3 === right
642
		if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
643
			if ( button & 1 ) {
644
				return 1;
645
			}
646
647
			if ( button & 2 ) {
648
				return 3;
649
			}
650
651
			if ( button & 4 ) {
652
				return 2;
653
			}
654
655
			return 0;
656
		}
657
658
		return event.which;
659
	}
660
}, jQuery.event.addProp );
661
662
// Create mouseenter/leave events using mouseover/out and event-time checks
663
// so that event delegation works in jQuery.
664
// Do the same for pointerenter/pointerleave and pointerover/pointerout
665
//
666
// Support: Safari 7 only
667
// Safari sends mouseenter too often; see:
668
// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
669
// for the description of the bug (it existed in older Chrome versions as well).
670
jQuery.each( {
671
	mouseenter: "mouseover",
672
	mouseleave: "mouseout",
673
	pointerenter: "pointerover",
674
	pointerleave: "pointerout"
675
}, function( orig, fix ) {
676
	jQuery.event.special[ orig ] = {
677
		delegateType: fix,
678
		bindType: fix,
679
680
		handle: function( event ) {
681
			var ret,
682
				target = this,
683
				related = event.relatedTarget,
684
				handleObj = event.handleObj;
685
686
			// For mouseenter/leave call the handler if related is outside the target.
687
			// NB: No relatedTarget if the mouse left/entered the browser window
688
			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
689
				event.type = handleObj.origType;
690
				ret = handleObj.handler.apply( this, arguments );
691
				event.type = fix;
692
			}
693
			return ret;
694
		}
695
	};
696
} );
697
698
jQuery.fn.extend( {
699
700
	on: function( types, selector, data, fn ) {
701
		return on( this, types, selector, data, fn );
702
	},
703
	one: function( types, selector, data, fn ) {
704
		return on( this, types, selector, data, fn, 1 );
705
	},
706
	off: function( types, selector, fn ) {
707
		var handleObj, type;
708
		if ( types && types.preventDefault && types.handleObj ) {
709
710
			// ( event )  dispatched jQuery.Event
711
			handleObj = types.handleObj;
712
			jQuery( types.delegateTarget ).off(
713
				handleObj.namespace ?
714
					handleObj.origType + "." + handleObj.namespace :
715
					handleObj.origType,
716
				handleObj.selector,
717
				handleObj.handler
718
			);
719
			return this;
720
		}
721
		if ( typeof types === "object" ) {
722
723
			// ( types-object [, selector] )
724
			for ( type in types ) {
725
				this.off( type, selector, types[ type ] );
726
			}
727
			return this;
728
		}
729
		if ( selector === false || typeof selector === "function" ) {
730
731
			// ( types [, fn] )
732
			fn = selector;
733
			selector = undefined;
734
		}
735
		if ( fn === false ) {
736
			fn = returnFalse;
737
		}
738
		return this.each( function() {
739
			jQuery.event.remove( this, types, fn, selector );
740
		} );
741
	}
742
} );
743
744
return jQuery;
745
} );
746