1 import jQuery from "./core.js";
2 import document from "./var/document.js";
3 import documentElement from "./var/documentElement.js";
4 import rnothtmlwhite from "./var/rnothtmlwhite.js";
5 import rcheckableType from "./var/rcheckableType.js";
6 import slice from "./var/slice.js";
7 import acceptData from "./data/var/acceptData.js";
8 import dataPriv from "./data/var/dataPriv.js";
9 import nodeName from "./core/nodeName.js";
11 import "./core/init.js";
12 import "./selector.js";
14 var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
16 function returnTrue() {
20 function returnFalse() {
24 // Support: IE <=9 - 11+
25 // focus() and blur() are asynchronous, except when they are no-op.
26 // So expect focus to be synchronous when the element is already active,
27 // and blur to be synchronous when the element is not already active.
28 // (focus and blur are always synchronous in other supported browsers,
29 // this just defines when we can count on it).
30 function expectSync( elem, type ) {
31 return ( elem === document.activeElement ) === ( type === "focus" );
34 function on( elem, types, selector, data, fn, one ) {
37 // Types can be a map of types/handlers
38 if ( typeof types === "object" ) {
40 // ( types-Object, selector, data )
41 if ( typeof selector !== "string" ) {
43 // ( types-Object, data )
44 data = data || selector;
47 for ( type in types ) {
48 on( elem, type, selector, data, types[ type ], one );
53 if ( data == null && fn == null ) {
57 data = selector = undefined;
58 } else if ( fn == null ) {
59 if ( typeof selector === "string" ) {
61 // ( types, selector, fn )
66 // ( types, data, fn )
80 fn = function( event ) {
82 // Can use an empty set, since event contains the info
83 jQuery().off( event );
84 return origFn.apply( this, arguments );
87 // Use same guid so caller can remove using origFn
88 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
90 return elem.each( function() {
91 jQuery.event.add( this, types, fn, data, selector );
96 * Helper functions for managing events -- not part of the public interface.
97 * Props to Dean Edwards' addEvent library for many of the ideas.
101 add: function( elem, types, handler, data, selector ) {
103 var handleObjIn, eventHandle, tmp,
104 events, t, handleObj,
105 special, handlers, type, namespaces, origType,
106 elemData = dataPriv.get( elem );
108 // Only attach events to objects that accept data
109 if ( !acceptData( elem ) ) {
113 // Caller can pass in an object of custom data in lieu of the handler
114 if ( handler.handler ) {
115 handleObjIn = handler;
116 handler = handleObjIn.handler;
117 selector = handleObjIn.selector;
120 // Ensure that invalid selectors throw exceptions at attach time
121 // Evaluate against documentElement in case elem is a non-element node (e.g., document)
123 jQuery.find.matchesSelector( documentElement, selector );
126 // Make sure that the handler has a unique ID, used to find/remove it later
127 if ( !handler.guid ) {
128 handler.guid = jQuery.guid++;
131 // Init the element's event structure and main handler, if this is the first
132 if ( !( events = elemData.events ) ) {
133 events = elemData.events = Object.create( null );
135 if ( !( eventHandle = elemData.handle ) ) {
136 eventHandle = elemData.handle = function( e ) {
138 // Discard the second event of a jQuery.event.trigger() and
139 // when an event is called after a page has unloaded
140 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
141 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
145 // Handle multiple events separated by a space
146 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
149 tmp = rtypenamespace.exec( types[ t ] ) || [];
150 type = origType = tmp[ 1 ];
151 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
153 // There *must* be a type, no attaching namespace-only handlers
158 // If event changes its type, use the special event handlers for the changed type
159 special = jQuery.event.special[ type ] || {};
161 // If selector defined, determine special event api type, otherwise given type
162 type = ( selector ? special.delegateType : special.bindType ) || type;
164 // Update special based on newly reset type
165 special = jQuery.event.special[ type ] || {};
167 // handleObj is passed to all event handlers
168 handleObj = jQuery.extend( {
175 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
176 namespace: namespaces.join( "." )
179 // Init the event handler queue if we're the first
180 if ( !( handlers = events[ type ] ) ) {
181 handlers = events[ type ] = [];
182 handlers.delegateCount = 0;
184 // Only use addEventListener if the special events handler returns false
185 if ( !special.setup ||
186 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
188 if ( elem.addEventListener ) {
189 elem.addEventListener( type, eventHandle );
195 special.add.call( elem, handleObj );
197 if ( !handleObj.handler.guid ) {
198 handleObj.handler.guid = handler.guid;
202 // Add to the element's handler list, delegates in front
204 handlers.splice( handlers.delegateCount++, 0, handleObj );
206 handlers.push( handleObj );
212 // Detach an event or set of events from an element
213 remove: function( elem, types, handler, selector, mappedTypes ) {
215 var j, origCount, tmp,
216 events, t, handleObj,
217 special, handlers, type, namespaces, origType,
218 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
220 if ( !elemData || !( events = elemData.events ) ) {
224 // Once for each type.namespace in types; type may be omitted
225 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
228 tmp = rtypenamespace.exec( types[ t ] ) || [];
229 type = origType = tmp[ 1 ];
230 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
232 // Unbind all events (on this namespace, if provided) for the element
234 for ( type in events ) {
235 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
240 special = jQuery.event.special[ type ] || {};
241 type = ( selector ? special.delegateType : special.bindType ) || type;
242 handlers = events[ type ] || [];
244 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
246 // Remove matching events
247 origCount = j = handlers.length;
249 handleObj = handlers[ j ];
251 if ( ( mappedTypes || origType === handleObj.origType ) &&
252 ( !handler || handler.guid === handleObj.guid ) &&
253 ( !tmp || tmp.test( handleObj.namespace ) ) &&
254 ( !selector || selector === handleObj.selector ||
255 selector === "**" && handleObj.selector ) ) {
256 handlers.splice( j, 1 );
258 if ( handleObj.selector ) {
259 handlers.delegateCount--;
261 if ( special.remove ) {
262 special.remove.call( elem, handleObj );
267 // Remove generic event handler if we removed something and no more handlers exist
268 // (avoids potential for endless recursion during removal of special event handlers)
269 if ( origCount && !handlers.length ) {
270 if ( !special.teardown ||
271 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
273 jQuery.removeEvent( elem, type, elemData.handle );
276 delete events[ type ];
280 // Remove data and the expando if it's no longer used
281 if ( jQuery.isEmptyObject( events ) ) {
282 dataPriv.remove( elem, "handle events" );
286 dispatch: function( nativeEvent ) {
288 var i, j, ret, matched, handleObj, handlerQueue,
289 args = new Array( arguments.length ),
291 // Make a writable jQuery.Event from the native event object
292 event = jQuery.event.fix( nativeEvent ),
295 dataPriv.get( this, "events" ) || Object.create( null )
296 )[ event.type ] || [],
297 special = jQuery.event.special[ event.type ] || {};
299 // Use the fix-ed jQuery.Event rather than the (read-only) native event
302 for ( i = 1; i < arguments.length; i++ ) {
303 args[ i ] = arguments[ i ];
306 event.delegateTarget = this;
308 // Call the preDispatch hook for the mapped type, and let it bail if desired
309 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
313 // Determine handlers
314 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
316 // Run delegates first; they may want to stop propagation beneath us
318 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
319 event.currentTarget = matched.elem;
322 while ( ( handleObj = matched.handlers[ j++ ] ) &&
323 !event.isImmediatePropagationStopped() ) {
325 // If the event is namespaced, then each handler is only invoked if it is
326 // specially universal or its namespaces are a superset of the event's.
327 if ( !event.rnamespace || handleObj.namespace === false ||
328 event.rnamespace.test( handleObj.namespace ) ) {
330 event.handleObj = handleObj;
331 event.data = handleObj.data;
333 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
334 handleObj.handler ).apply( matched.elem, args );
336 if ( ret !== undefined ) {
337 if ( ( event.result = ret ) === false ) {
338 event.preventDefault();
339 event.stopPropagation();
346 // Call the postDispatch hook for the mapped type
347 if ( special.postDispatch ) {
348 special.postDispatch.call( this, event );
354 handlers: function( event, handlers ) {
355 var i, handleObj, sel, matchedHandlers, matchedSelectors,
357 delegateCount = handlers.delegateCount,
360 // Find delegate handlers
361 if ( delegateCount &&
363 // Support: Firefox <=42 - 66+
364 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
365 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
367 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
368 !( event.type === "click" && event.button >= 1 ) ) {
370 for ( ; cur !== this; cur = cur.parentNode || this ) {
372 // Don't check non-elements (#13208)
373 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
374 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
375 matchedHandlers = [];
376 matchedSelectors = {};
377 for ( i = 0; i < delegateCount; i++ ) {
378 handleObj = handlers[ i ];
380 // Don't conflict with Object.prototype properties (#13203)
381 sel = handleObj.selector + " ";
383 if ( matchedSelectors[ sel ] === undefined ) {
384 matchedSelectors[ sel ] = handleObj.needsContext ?
385 jQuery( sel, this ).index( cur ) > -1 :
386 jQuery.find( sel, this, null, [ cur ] ).length;
388 if ( matchedSelectors[ sel ] ) {
389 matchedHandlers.push( handleObj );
392 if ( matchedHandlers.length ) {
393 handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
399 // Add the remaining (directly-bound) handlers
401 if ( delegateCount < handlers.length ) {
402 handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
408 addProp: function( name, hook ) {
409 Object.defineProperty( jQuery.Event.prototype, name, {
413 get: typeof hook === "function" ?
415 if ( this.originalEvent ) {
416 return hook( this.originalEvent );
420 if ( this.originalEvent ) {
421 return this.originalEvent[ name ];
425 set: function( value ) {
426 Object.defineProperty( this, name, {
436 fix: function( originalEvent ) {
437 return originalEvent[ jQuery.expando ] ?
439 new jQuery.Event( originalEvent );
445 // Prevent triggered image.load events from bubbling to window.load
450 // Utilize native event to ensure correct state for checkable inputs
451 setup: function( data ) {
453 // For mutual compressibility with _default, replace `this` access with a local var.
454 // `|| data` is dead code meant only to preserve the variable through minification.
455 var el = this || data;
457 // Claim the first handler
458 if ( rcheckableType.test( el.type ) &&
459 el.click && nodeName( el, "input" ) ) {
461 // dataPriv.set( el, "click", ... )
462 leverageNative( el, "click", returnTrue );
465 // Return false to allow normal processing in the caller
468 trigger: function( data ) {
470 // For mutual compressibility with _default, replace `this` access with a local var.
471 // `|| data` is dead code meant only to preserve the variable through minification.
472 var el = this || data;
474 // Force setup before triggering a click
475 if ( rcheckableType.test( el.type ) &&
476 el.click && nodeName( el, "input" ) ) {
478 leverageNative( el, "click" );
481 // Return non-false to allow normal event-path propagation
485 // For cross-browser consistency, suppress native .click() on links
486 // Also prevent it if we're currently inside a leveraged native-event stack
487 _default: function( event ) {
488 var target = event.target;
489 return rcheckableType.test( target.type ) &&
490 target.click && nodeName( target, "input" ) &&
491 dataPriv.get( target, "click" ) ||
492 nodeName( target, "a" );
497 postDispatch: function( event ) {
499 // Support: Chrome <=73+
500 // Chrome doesn't alert on `event.preventDefault()`
501 // as the standard mandates.
502 if ( event.result !== undefined && event.originalEvent ) {
503 event.originalEvent.returnValue = event.result;
510 // Ensure the presence of an event listener that handles manually-triggered
511 // synthetic events by interrupting progress until reinvoked in response to
512 // *native* events that it fires directly, ensuring that state changes have
513 // already occurred before other listeners are invoked.
514 function leverageNative( el, type, expectSync ) {
516 // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
518 if ( dataPriv.get( el, type ) === undefined ) {
519 jQuery.event.add( el, type, returnTrue );
524 // Register the controller as a special universal handler for all event namespaces
525 dataPriv.set( el, type, false );
526 jQuery.event.add( el, type, {
528 handler: function( event ) {
529 var notAsync, result,
530 saved = dataPriv.get( this, type );
532 if ( ( event.isTrigger & 1 ) && this[ type ] ) {
534 // Interrupt processing of the outer synthetic .trigger()ed event
535 // Saved data should be false in such cases, but might be a leftover capture object
536 // from an async native handler (gh-4350)
537 if ( !saved.length ) {
539 // Store arguments for use when handling the inner native event
540 // There will always be at least one argument (an event object), so this array
541 // will not be confused with a leftover capture object.
542 saved = slice.call( arguments );
543 dataPriv.set( this, type, saved );
545 // Trigger the native event and capture its result
546 // Support: IE <=9 - 11+
547 // focus() and blur() are asynchronous
548 notAsync = expectSync( this, type );
550 result = dataPriv.get( this, type );
551 if ( saved !== result || notAsync ) {
552 dataPriv.set( this, type, false );
556 if ( saved !== result ) {
558 // Cancel the outer synthetic event
559 event.stopImmediatePropagation();
560 event.preventDefault();
562 // Support: Chrome 86+
563 // In Chrome, if an element having a focusout handler is blurred by
564 // clicking outside of it, it invokes the handler synchronously. If
565 // that handler calls `.remove()` on the element, the data is cleared,
566 // leaving `result` undefined. We need to guard against this.
567 return result && result.value;
570 // If this is an inner synthetic event for an event with a bubbling surrogate
571 // (focus or blur), assume that the surrogate already propagated from triggering the
572 // native event and prevent that from happening again here.
573 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
574 // bubbling surrogate propagates *after* the non-bubbling base), but that seems
575 // less bad than duplication.
576 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
577 event.stopPropagation();
580 // If this is a native event triggered above, everything is now in order
581 // Fire an inner synthetic event with the original arguments
582 } else if ( saved.length ) {
584 // ...and capture the result
585 dataPriv.set( this, type, {
586 value: jQuery.event.trigger(
588 // Support: IE <=9 - 11+
589 // Extend with the prototype to reset the above stopImmediatePropagation()
590 jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
596 // Abort handling of the native event
597 event.stopImmediatePropagation();
603 jQuery.removeEvent = function( elem, type, handle ) {
605 // This "if" is needed for plain objects
606 if ( elem.removeEventListener ) {
607 elem.removeEventListener( type, handle );
611 jQuery.Event = function( src, props ) {
613 // Allow instantiation without the 'new' keyword
614 if ( !( this instanceof jQuery.Event ) ) {
615 return new jQuery.Event( src, props );
619 if ( src && src.type ) {
620 this.originalEvent = src;
621 this.type = src.type;
623 // Events bubbling up the document may have been marked as prevented
624 // by a handler lower down the tree; reflect the correct value.
625 this.isDefaultPrevented = src.defaultPrevented ?
629 // Create target properties
630 this.target = src.target;
631 this.currentTarget = src.currentTarget;
632 this.relatedTarget = src.relatedTarget;
639 // Put explicitly provided properties onto the event object
641 jQuery.extend( this, props );
644 // Create a timestamp if incoming event doesn't have one
645 this.timeStamp = src && src.timeStamp || Date.now();
648 this[ jQuery.expando ] = true;
651 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
652 // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
653 jQuery.Event.prototype = {
654 constructor: jQuery.Event,
655 isDefaultPrevented: returnFalse,
656 isPropagationStopped: returnFalse,
657 isImmediatePropagationStopped: returnFalse,
660 preventDefault: function() {
661 var e = this.originalEvent;
663 this.isDefaultPrevented = returnTrue;
665 if ( e && !this.isSimulated ) {
669 stopPropagation: function() {
670 var e = this.originalEvent;
672 this.isPropagationStopped = returnTrue;
674 if ( e && !this.isSimulated ) {
678 stopImmediatePropagation: function() {
679 var e = this.originalEvent;
681 this.isImmediatePropagationStopped = returnTrue;
683 if ( e && !this.isSimulated ) {
684 e.stopImmediatePropagation();
687 this.stopPropagation();
691 // Includes all common event props including KeyEvent and MouseEvent specific props
696 changedTouches: true,
724 }, jQuery.event.addProp );
726 jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
727 jQuery.event.special[ type ] = {
729 // Utilize native event if possible so blur/focus sequence is correct
732 // Claim the first handler
733 // dataPriv.set( this, "focus", ... )
734 // dataPriv.set( this, "blur", ... )
735 leverageNative( this, type, expectSync );
737 // Return false to allow normal processing in the caller
740 trigger: function() {
742 // Force setup before trigger
743 leverageNative( this, type );
745 // Return non-false to allow normal event-path propagation
749 // Suppress native focus or blur if we're currently inside
750 // a leveraged native-event stack
751 _default: function( event ) {
752 return dataPriv.get( event.target, type );
755 delegateType: delegateType
759 // Create mouseenter/leave events using mouseover/out and event-time checks
760 // so that event delegation works in jQuery.
761 // Do the same for pointerenter/pointerleave and pointerover/pointerout
763 mouseenter: "mouseover",
764 mouseleave: "mouseout",
765 pointerenter: "pointerover",
766 pointerleave: "pointerout"
767 }, function( orig, fix ) {
768 jQuery.event.special[ orig ] = {
772 handle: function( event ) {
775 related = event.relatedTarget,
776 handleObj = event.handleObj;
778 // For mouseenter/leave call the handler if related is outside the target.
779 // NB: No relatedTarget if the mouse left/entered the browser window
780 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
781 event.type = handleObj.origType;
782 ret = handleObj.handler.apply( this, arguments );
792 on: function( types, selector, data, fn ) {
793 return on( this, types, selector, data, fn );
795 one: function( types, selector, data, fn ) {
796 return on( this, types, selector, data, fn, 1 );
798 off: function( types, selector, fn ) {
800 if ( types && types.preventDefault && types.handleObj ) {
802 // ( event ) dispatched jQuery.Event
803 handleObj = types.handleObj;
804 jQuery( types.delegateTarget ).off(
805 handleObj.namespace ?
806 handleObj.origType + "." + handleObj.namespace :
813 if ( typeof types === "object" ) {
815 // ( types-object [, selector] )
816 for ( type in types ) {
817 this.off( type, selector, types[ type ] );
821 if ( selector === false || typeof selector === "function" ) {
825 selector = undefined;
827 if ( fn === false ) {
830 return this.each( function() {
831 jQuery.event.remove( this, types, fn, selector );
836 export default jQuery;