UNPKG

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