Deprecated: Define `.hover()` using non-deprecated methods
[jquery.git] / src / event.js
blob5d2c8c1c3c12c171c571f84a80c6b7d410b73ed3
1 import jQuery from "./core.js";
2 import documentElement from "./var/documentElement.js";
3 import rnothtmlwhite from "./var/rnothtmlwhite.js";
4 import rcheckableType from "./var/rcheckableType.js";
5 import slice from "./var/slice.js";
6 import isIE from "./var/isIE.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() {
17         return true;
20 function returnFalse() {
21         return false;
24 function on( elem, types, selector, data, fn, one ) {
25         var origFn, type;
27         // Types can be a map of types/handlers
28         if ( typeof types === "object" ) {
30                 // ( types-Object, selector, data )
31                 if ( typeof selector !== "string" ) {
33                         // ( types-Object, data )
34                         data = data || selector;
35                         selector = undefined;
36                 }
37                 for ( type in types ) {
38                         on( elem, type, selector, data, types[ type ], one );
39                 }
40                 return elem;
41         }
43         if ( data == null && fn == null ) {
45                 // ( types, fn )
46                 fn = selector;
47                 data = selector = undefined;
48         } else if ( fn == null ) {
49                 if ( typeof selector === "string" ) {
51                         // ( types, selector, fn )
52                         fn = data;
53                         data = undefined;
54                 } else {
56                         // ( types, data, fn )
57                         fn = data;
58                         data = selector;
59                         selector = undefined;
60                 }
61         }
62         if ( fn === false ) {
63                 fn = returnFalse;
64         } else if ( !fn ) {
65                 return elem;
66         }
68         if ( one === 1 ) {
69                 origFn = fn;
70                 fn = function( event ) {
72                         // Can use an empty set, since event contains the info
73                         jQuery().off( event );
74                         return origFn.apply( this, arguments );
75                 };
77                 // Use same guid so caller can remove using origFn
78                 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
79         }
80         return elem.each( function() {
81                 jQuery.event.add( this, types, fn, data, selector );
82         } );
86  * Helper functions for managing events -- not part of the public interface.
87  * Props to Dean Edwards' addEvent library for many of the ideas.
88  */
89 jQuery.event = {
91         add: function( elem, types, handler, data, selector ) {
93                 var handleObjIn, eventHandle, tmp,
94                         events, t, handleObj,
95                         special, handlers, type, namespaces, origType,
96                         elemData = dataPriv.get( elem );
98                 // Only attach events to objects that accept data
99                 if ( !acceptData( elem ) ) {
100                         return;
101                 }
103                 // Caller can pass in an object of custom data in lieu of the handler
104                 if ( handler.handler ) {
105                         handleObjIn = handler;
106                         handler = handleObjIn.handler;
107                         selector = handleObjIn.selector;
108                 }
110                 // Ensure that invalid selectors throw exceptions at attach time
111                 // Evaluate against documentElement in case elem is a non-element node (e.g., document)
112                 if ( selector ) {
113                         jQuery.find.matchesSelector( documentElement, selector );
114                 }
116                 // Make sure that the handler has a unique ID, used to find/remove it later
117                 if ( !handler.guid ) {
118                         handler.guid = jQuery.guid++;
119                 }
121                 // Init the element's event structure and main handler, if this is the first
122                 if ( !( events = elemData.events ) ) {
123                         events = elemData.events = Object.create( null );
124                 }
125                 if ( !( eventHandle = elemData.handle ) ) {
126                         eventHandle = elemData.handle = function( e ) {
128                                 // Discard the second event of a jQuery.event.trigger() and
129                                 // when an event is called after a page has unloaded
130                                 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
131                                         jQuery.event.dispatch.apply( elem, arguments ) : undefined;
132                         };
133                 }
135                 // Handle multiple events separated by a space
136                 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
137                 t = types.length;
138                 while ( t-- ) {
139                         tmp = rtypenamespace.exec( types[ t ] ) || [];
140                         type = origType = tmp[ 1 ];
141                         namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
143                         // There *must* be a type, no attaching namespace-only handlers
144                         if ( !type ) {
145                                 continue;
146                         }
148                         // If event changes its type, use the special event handlers for the changed type
149                         special = jQuery.event.special[ type ] || {};
151                         // If selector defined, determine special event api type, otherwise given type
152                         type = ( selector ? special.delegateType : special.bindType ) || type;
154                         // Update special based on newly reset type
155                         special = jQuery.event.special[ type ] || {};
157                         // handleObj is passed to all event handlers
158                         handleObj = jQuery.extend( {
159                                 type: type,
160                                 origType: origType,
161                                 data: data,
162                                 handler: handler,
163                                 guid: handler.guid,
164                                 selector: selector,
165                                 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
166                                 namespace: namespaces.join( "." )
167                         }, handleObjIn );
169                         // Init the event handler queue if we're the first
170                         if ( !( handlers = events[ type ] ) ) {
171                                 handlers = events[ type ] = [];
172                                 handlers.delegateCount = 0;
174                                 // Only use addEventListener if the special events handler returns false
175                                 if ( !special.setup ||
176                                         special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
178                                         if ( elem.addEventListener ) {
179                                                 elem.addEventListener( type, eventHandle );
180                                         }
181                                 }
182                         }
184                         if ( special.add ) {
185                                 special.add.call( elem, handleObj );
187                                 if ( !handleObj.handler.guid ) {
188                                         handleObj.handler.guid = handler.guid;
189                                 }
190                         }
192                         // Add to the element's handler list, delegates in front
193                         if ( selector ) {
194                                 handlers.splice( handlers.delegateCount++, 0, handleObj );
195                         } else {
196                                 handlers.push( handleObj );
197                         }
198                 }
200         },
202         // Detach an event or set of events from an element
203         remove: function( elem, types, handler, selector, mappedTypes ) {
205                 var j, origCount, tmp,
206                         events, t, handleObj,
207                         special, handlers, type, namespaces, origType,
208                         elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
210                 if ( !elemData || !( events = elemData.events ) ) {
211                         return;
212                 }
214                 // Once for each type.namespace in types; type may be omitted
215                 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
216                 t = types.length;
217                 while ( t-- ) {
218                         tmp = rtypenamespace.exec( types[ t ] ) || [];
219                         type = origType = tmp[ 1 ];
220                         namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
222                         // Unbind all events (on this namespace, if provided) for the element
223                         if ( !type ) {
224                                 for ( type in events ) {
225                                         jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
226                                 }
227                                 continue;
228                         }
230                         special = jQuery.event.special[ type ] || {};
231                         type = ( selector ? special.delegateType : special.bindType ) || type;
232                         handlers = events[ type ] || [];
233                         tmp = tmp[ 2 ] &&
234                                 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
236                         // Remove matching events
237                         origCount = j = handlers.length;
238                         while ( j-- ) {
239                                 handleObj = handlers[ j ];
241                                 if ( ( mappedTypes || origType === handleObj.origType ) &&
242                                         ( !handler || handler.guid === handleObj.guid ) &&
243                                         ( !tmp || tmp.test( handleObj.namespace ) ) &&
244                                         ( !selector || selector === handleObj.selector ||
245                                                 selector === "**" && handleObj.selector ) ) {
246                                         handlers.splice( j, 1 );
248                                         if ( handleObj.selector ) {
249                                                 handlers.delegateCount--;
250                                         }
251                                         if ( special.remove ) {
252                                                 special.remove.call( elem, handleObj );
253                                         }
254                                 }
255                         }
257                         // Remove generic event handler if we removed something and no more handlers exist
258                         // (avoids potential for endless recursion during removal of special event handlers)
259                         if ( origCount && !handlers.length ) {
260                                 if ( !special.teardown ||
261                                         special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
263                                         jQuery.removeEvent( elem, type, elemData.handle );
264                                 }
266                                 delete events[ type ];
267                         }
268                 }
270                 // Remove data and the expando if it's no longer used
271                 if ( jQuery.isEmptyObject( events ) ) {
272                         dataPriv.remove( elem, "handle events" );
273                 }
274         },
276         dispatch: function( nativeEvent ) {
278                 var i, j, ret, matched, handleObj, handlerQueue,
279                         args = new Array( arguments.length ),
281                         // Make a writable jQuery.Event from the native event object
282                         event = jQuery.event.fix( nativeEvent ),
284                         handlers = (
285                                 dataPriv.get( this, "events" ) || Object.create( null )
286                         )[ event.type ] || [],
287                         special = jQuery.event.special[ event.type ] || {};
289                 // Use the fix-ed jQuery.Event rather than the (read-only) native event
290                 args[ 0 ] = event;
292                 for ( i = 1; i < arguments.length; i++ ) {
293                         args[ i ] = arguments[ i ];
294                 }
296                 event.delegateTarget = this;
298                 // Call the preDispatch hook for the mapped type, and let it bail if desired
299                 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
300                         return;
301                 }
303                 // Determine handlers
304                 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
306                 // Run delegates first; they may want to stop propagation beneath us
307                 i = 0;
308                 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
309                         event.currentTarget = matched.elem;
311                         j = 0;
312                         while ( ( handleObj = matched.handlers[ j++ ] ) &&
313                                 !event.isImmediatePropagationStopped() ) {
315                                 // If the event is namespaced, then each handler is only invoked if it is
316                                 // specially universal or its namespaces are a superset of the event's.
317                                 if ( !event.rnamespace || handleObj.namespace === false ||
318                                         event.rnamespace.test( handleObj.namespace ) ) {
320                                         event.handleObj = handleObj;
321                                         event.data = handleObj.data;
323                                         ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
324                                                 handleObj.handler ).apply( matched.elem, args );
326                                         if ( ret !== undefined ) {
327                                                 if ( ( event.result = ret ) === false ) {
328                                                         event.preventDefault();
329                                                         event.stopPropagation();
330                                                 }
331                                         }
332                                 }
333                         }
334                 }
336                 // Call the postDispatch hook for the mapped type
337                 if ( special.postDispatch ) {
338                         special.postDispatch.call( this, event );
339                 }
341                 return event.result;
342         },
344         handlers: function( event, handlers ) {
345                 var i, handleObj, sel, matchedHandlers, matchedSelectors,
346                         handlerQueue = [],
347                         delegateCount = handlers.delegateCount,
348                         cur = event.target;
350                 // Find delegate handlers
351                 if ( delegateCount &&
353                         // Support: Firefox <=42 - 66+
354                         // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
355                         // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
356                         // Support: IE 11+
357                         // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
358                         !( event.type === "click" && event.button >= 1 ) ) {
360                         for ( ; cur !== this; cur = cur.parentNode || this ) {
362                                 // Don't check non-elements (trac-13208)
363                                 // Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764)
364                                 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
365                                         matchedHandlers = [];
366                                         matchedSelectors = {};
367                                         for ( i = 0; i < delegateCount; i++ ) {
368                                                 handleObj = handlers[ i ];
370                                                 // Don't conflict with Object.prototype properties (trac-13203)
371                                                 sel = handleObj.selector + " ";
373                                                 if ( matchedSelectors[ sel ] === undefined ) {
374                                                         matchedSelectors[ sel ] = handleObj.needsContext ?
375                                                                 jQuery( sel, this ).index( cur ) > -1 :
376                                                                 jQuery.find( sel, this, null, [ cur ] ).length;
377                                                 }
378                                                 if ( matchedSelectors[ sel ] ) {
379                                                         matchedHandlers.push( handleObj );
380                                                 }
381                                         }
382                                         if ( matchedHandlers.length ) {
383                                                 handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
384                                         }
385                                 }
386                         }
387                 }
389                 // Add the remaining (directly-bound) handlers
390                 cur = this;
391                 if ( delegateCount < handlers.length ) {
392                         handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
393                 }
395                 return handlerQueue;
396         },
398         addProp: function( name, hook ) {
399                 Object.defineProperty( jQuery.Event.prototype, name, {
400                         enumerable: true,
401                         configurable: true,
403                         get: typeof hook === "function" ?
404                                 function() {
405                                         if ( this.originalEvent ) {
406                                                 return hook( this.originalEvent );
407                                         }
408                                 } :
409                                 function() {
410                                         if ( this.originalEvent ) {
411                                                 return this.originalEvent[ name ];
412                                         }
413                                 },
415                         set: function( value ) {
416                                 Object.defineProperty( this, name, {
417                                         enumerable: true,
418                                         configurable: true,
419                                         writable: true,
420                                         value: value
421                                 } );
422                         }
423                 } );
424         },
426         fix: function( originalEvent ) {
427                 return originalEvent[ jQuery.expando ] ?
428                         originalEvent :
429                         new jQuery.Event( originalEvent );
430         },
432         special: jQuery.extend( Object.create( null ), {
433                 load: {
435                         // Prevent triggered image.load events from bubbling to window.load
436                         noBubble: true
437                 },
438                 click: {
440                         // Utilize native event to ensure correct state for checkable inputs
441                         setup: function( data ) {
443                                 // For mutual compressibility with _default, replace `this` access with a local var.
444                                 // `|| data` is dead code meant only to preserve the variable through minification.
445                                 var el = this || data;
447                                 // Claim the first handler
448                                 if ( rcheckableType.test( el.type ) &&
449                                         el.click && nodeName( el, "input" ) ) {
451                                         // dataPriv.set( el, "click", ... )
452                                         leverageNative( el, "click", true );
453                                 }
455                                 // Return false to allow normal processing in the caller
456                                 return false;
457                         },
458                         trigger: function( data ) {
460                                 // For mutual compressibility with _default, replace `this` access with a local var.
461                                 // `|| data` is dead code meant only to preserve the variable through minification.
462                                 var el = this || data;
464                                 // Force setup before triggering a click
465                                 if ( rcheckableType.test( el.type ) &&
466                                         el.click && nodeName( el, "input" ) ) {
468                                         leverageNative( el, "click" );
469                                 }
471                                 // Return non-false to allow normal event-path propagation
472                                 return true;
473                         },
475                         // For cross-browser consistency, suppress native .click() on links
476                         // Also prevent it if we're currently inside a leveraged native-event stack
477                         _default: function( event ) {
478                                 var target = event.target;
479                                 return rcheckableType.test( target.type ) &&
480                                         target.click && nodeName( target, "input" ) &&
481                                         dataPriv.get( target, "click" ) ||
482                                         nodeName( target, "a" );
483                         }
484                 },
486                 beforeunload: {
487                         postDispatch: function( event ) {
489                                 // Support: Chrome <=73+
490                                 // Chrome doesn't alert on `event.preventDefault()`
491                                 // as the standard mandates.
492                                 if ( event.result !== undefined && event.originalEvent ) {
493                                         event.originalEvent.returnValue = event.result;
494                                 }
495                         }
496                 }
497         } )
500 // Ensure the presence of an event listener that handles manually-triggered
501 // synthetic events by interrupting progress until reinvoked in response to
502 // *native* events that it fires directly, ensuring that state changes have
503 // already occurred before other listeners are invoked.
504 function leverageNative( el, type, isSetup ) {
506         // Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add
507         if ( !isSetup ) {
508                 if ( dataPriv.get( el, type ) === undefined ) {
509                         jQuery.event.add( el, type, returnTrue );
510                 }
511                 return;
512         }
514         // Register the controller as a special universal handler for all event namespaces
515         dataPriv.set( el, type, false );
516         jQuery.event.add( el, type, {
517                 namespace: false,
518                 handler: function( event ) {
519                         var result,
520                                 saved = dataPriv.get( this, type );
522                         if ( ( event.isTrigger & 1 ) && this[ type ] ) {
524                                 // Interrupt processing of the outer synthetic .trigger()ed event
525                                 if ( !saved ) {
527                                         // Store arguments for use when handling the inner native event
528                                         // There will always be at least one argument (an event object), so this array
529                                         // will not be confused with a leftover capture object.
530                                         saved = slice.call( arguments );
531                                         dataPriv.set( this, type, saved );
533                                         // Trigger the native event and capture its result
534                                         this[ type ]();
535                                         result = dataPriv.get( this, type );
536                                         dataPriv.set( this, type, false );
538                                         if ( saved !== result ) {
540                                                 // Cancel the outer synthetic event
541                                                 event.stopImmediatePropagation();
542                                                 event.preventDefault();
544                                                 return result;
545                                         }
547                                 // If this is an inner synthetic event for an event with a bubbling surrogate
548                                 // (focus or blur), assume that the surrogate already propagated from triggering
549                                 // the native event and prevent that from happening again here.
550                                 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
551                                 // bubbling surrogate propagates *after* the non-bubbling base), but that seems
552                                 // less bad than duplication.
553                                 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
554                                         event.stopPropagation();
555                                 }
557                         // If this is a native event triggered above, everything is now in order
558                         // Fire an inner synthetic event with the original arguments
559                         } else if ( saved ) {
561                                 // ...and capture the result
562                                 dataPriv.set( this, type, jQuery.event.trigger(
563                                         saved[ 0 ],
564                                         saved.slice( 1 ),
565                                         this
566                                 ) );
568                                 // Abort handling of the native event by all jQuery handlers while allowing
569                                 // native handlers on the same element to run. On target, this is achieved
570                                 // by stopping immediate propagation just on the jQuery event. However,
571                                 // the native event is re-wrapped by a jQuery one on each level of the
572                                 // propagation so the only way to stop it for jQuery is to stop it for
573                                 // everyone via native `stopPropagation()`. This is not a problem for
574                                 // focus/blur which don't bubble, but it does also stop click on checkboxes
575                                 // and radios. We accept this limitation.
576                                 event.stopPropagation();
577                                 event.isImmediatePropagationStopped = returnTrue;
578                         }
579                 }
580         } );
583 jQuery.removeEvent = function( elem, type, handle ) {
585         // This "if" is needed for plain objects
586         if ( elem.removeEventListener ) {
587                 elem.removeEventListener( type, handle );
588         }
591 jQuery.Event = function( src, props ) {
593         // Allow instantiation without the 'new' keyword
594         if ( !( this instanceof jQuery.Event ) ) {
595                 return new jQuery.Event( src, props );
596         }
598         // Event object
599         if ( src && src.type ) {
600                 this.originalEvent = src;
601                 this.type = src.type;
603                 // Events bubbling up the document may have been marked as prevented
604                 // by a handler lower down the tree; reflect the correct value.
605                 this.isDefaultPrevented = src.defaultPrevented ?
606                         returnTrue :
607                         returnFalse;
609                 // Create target properties
610                 this.target = src.target;
611                 this.currentTarget = src.currentTarget;
612                 this.relatedTarget = src.relatedTarget;
614         // Event type
615         } else {
616                 this.type = src;
617         }
619         // Put explicitly provided properties onto the event object
620         if ( props ) {
621                 jQuery.extend( this, props );
622         }
624         // Create a timestamp if incoming event doesn't have one
625         this.timeStamp = src && src.timeStamp || Date.now();
627         // Mark it as fixed
628         this[ jQuery.expando ] = true;
631 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
632 // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
633 jQuery.Event.prototype = {
634         constructor: jQuery.Event,
635         isDefaultPrevented: returnFalse,
636         isPropagationStopped: returnFalse,
637         isImmediatePropagationStopped: returnFalse,
638         isSimulated: false,
640         preventDefault: function() {
641                 var e = this.originalEvent;
643                 this.isDefaultPrevented = returnTrue;
645                 if ( e && !this.isSimulated ) {
646                         e.preventDefault();
647                 }
648         },
649         stopPropagation: function() {
650                 var e = this.originalEvent;
652                 this.isPropagationStopped = returnTrue;
654                 if ( e && !this.isSimulated ) {
655                         e.stopPropagation();
656                 }
657         },
658         stopImmediatePropagation: function() {
659                 var e = this.originalEvent;
661                 this.isImmediatePropagationStopped = returnTrue;
663                 if ( e && !this.isSimulated ) {
664                         e.stopImmediatePropagation();
665                 }
667                 this.stopPropagation();
668         }
671 // Includes all common event props including KeyEvent and MouseEvent specific props
672 jQuery.each( {
673         altKey: true,
674         bubbles: true,
675         cancelable: true,
676         changedTouches: true,
677         ctrlKey: true,
678         detail: true,
679         eventPhase: true,
680         metaKey: true,
681         pageX: true,
682         pageY: true,
683         shiftKey: true,
684         view: true,
685         "char": true,
686         code: true,
687         charCode: true,
688         key: true,
689         keyCode: true,
690         button: true,
691         buttons: true,
692         clientX: true,
693         clientY: true,
694         offsetX: true,
695         offsetY: true,
696         pointerId: true,
697         pointerType: true,
698         screenX: true,
699         screenY: true,
700         targetTouches: true,
701         toElement: true,
702         touches: true,
703         which: true
704 }, jQuery.event.addProp );
706 jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
708         // Support: IE 11+
709         // Attach a single focusin/focusout handler on the document while someone wants focus/blur.
710         // This is because the former are synchronous in IE while the latter are async. In other
711         // browsers, all those handlers are invoked synchronously.
712         function focusMappedHandler( nativeEvent ) {
714                 // `eventHandle` would already wrap the event, but we need to change the `type` here.
715                 var event = jQuery.event.fix( nativeEvent );
716                 event.type = nativeEvent.type === "focusin" ? "focus" : "blur";
717                 event.isSimulated = true;
719                 // focus/blur don't bubble while focusin/focusout do; simulate the former by only
720                 // invoking the handler at the lower level.
721                 if ( event.target === event.currentTarget ) {
723                         // The setup part calls `leverageNative`, which, in turn, calls
724                         // `jQuery.event.add`, so event handle will already have been set
725                         // by this point.
726                         dataPriv.get( this, "handle" )( event );
727                 }
728         }
730         jQuery.event.special[ type ] = {
732                 // Utilize native event if possible so blur/focus sequence is correct
733                 setup: function() {
735                         // Claim the first handler
736                         // dataPriv.set( this, "focus", ... )
737                         // dataPriv.set( this, "blur", ... )
738                         leverageNative( this, type, true );
740                         if ( isIE ) {
741                                 this.addEventListener( delegateType, focusMappedHandler );
742                         } else {
744                                 // Return false to allow normal processing in the caller
745                                 return false;
746                         }
747                 },
748                 trigger: function() {
750                         // Force setup before trigger
751                         leverageNative( this, type );
753                         // Return non-false to allow normal event-path propagation
754                         return true;
755                 },
757                 teardown: function() {
758                         if ( isIE ) {
759                                 this.removeEventListener( delegateType, focusMappedHandler );
760                         } else {
762                                 // Return false to indicate standard teardown should be applied
763                                 return false;
764                         }
765                 },
767                 // Suppress native focus or blur if we're currently inside
768                 // a leveraged native-event stack
769                 _default: function( event ) {
770                         return dataPriv.get( event.target, type );
771                 },
773                 delegateType: delegateType
774         };
775 } );
777 // Create mouseenter/leave events using mouseover/out and event-time checks
778 // so that event delegation works in jQuery.
779 // Do the same for pointerenter/pointerleave and pointerover/pointerout
780 jQuery.each( {
781         mouseenter: "mouseover",
782         mouseleave: "mouseout",
783         pointerenter: "pointerover",
784         pointerleave: "pointerout"
785 }, function( orig, fix ) {
786         jQuery.event.special[ orig ] = {
787                 delegateType: fix,
788                 bindType: fix,
790                 handle: function( event ) {
791                         var ret,
792                                 target = this,
793                                 related = event.relatedTarget,
794                                 handleObj = event.handleObj;
796                         // For mouseenter/leave call the handler if related is outside the target.
797                         // NB: No relatedTarget if the mouse left/entered the browser window
798                         if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
799                                 event.type = handleObj.origType;
800                                 ret = handleObj.handler.apply( this, arguments );
801                                 event.type = fix;
802                         }
803                         return ret;
804                 }
805         };
806 } );
808 jQuery.fn.extend( {
810         on: function( types, selector, data, fn ) {
811                 return on( this, types, selector, data, fn );
812         },
813         one: function( types, selector, data, fn ) {
814                 return on( this, types, selector, data, fn, 1 );
815         },
816         off: function( types, selector, fn ) {
817                 var handleObj, type;
818                 if ( types && types.preventDefault && types.handleObj ) {
820                         // ( event )  dispatched jQuery.Event
821                         handleObj = types.handleObj;
822                         jQuery( types.delegateTarget ).off(
823                                 handleObj.namespace ?
824                                         handleObj.origType + "." + handleObj.namespace :
825                                         handleObj.origType,
826                                 handleObj.selector,
827                                 handleObj.handler
828                         );
829                         return this;
830                 }
831                 if ( typeof types === "object" ) {
833                         // ( types-object [, selector] )
834                         for ( type in types ) {
835                                 this.off( type, selector, types[ type ] );
836                         }
837                         return this;
838                 }
839                 if ( selector === false || typeof selector === "function" ) {
841                         // ( types [, fn] )
842                         fn = selector;
843                         selector = undefined;
844                 }
845                 if ( fn === false ) {
846                         fn = returnFalse;
847                 }
848                 return this.each( function() {
849                         jQuery.event.remove( this, types, fn, selector );
850                 } );
851         }
852 } );
854 export default jQuery;