13 ], function( jQuery, document, rnotwhite, hasOwn, slice, support, dataPriv ) {
17 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
18 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
19 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
21 function returnTrue() {
25 function returnFalse() {
30 // See #13393 for more info
31 function safeActiveElement() {
33 return document.activeElement;
38 * Helper functions for managing events -- not part of the public interface.
39 * Props to Dean Edwards' addEvent library for many of the ideas.
45 add: function( elem, types, handler, data, selector ) {
47 var handleObjIn, eventHandle, tmp,
49 special, handlers, type, namespaces, origType,
50 elemData = dataPriv.get( elem );
52 // Don't attach events to noData or text/comment nodes (but allow plain objects)
57 // Caller can pass in an object of custom data in lieu of the handler
58 if ( handler.handler ) {
59 handleObjIn = handler;
60 handler = handleObjIn.handler;
61 selector = handleObjIn.selector;
64 // Make sure that the handler has a unique ID, used to find/remove it later
65 if ( !handler.guid ) {
66 handler.guid = jQuery.guid++;
69 // Init the element's event structure and main handler, if this is the first
70 if ( !(events = elemData.events) ) {
71 events = elemData.events = {};
73 if ( !(eventHandle = elemData.handle) ) {
74 eventHandle = elemData.handle = function( e ) {
75 // Discard the second event of a jQuery.event.trigger() and
76 // when an event is called after a page has unloaded
77 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
78 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
82 // Handle multiple events separated by a space
83 types = ( types || "" ).match( rnotwhite ) || [ "" ];
86 tmp = rtypenamespace.exec( types[t] ) || [];
87 type = origType = tmp[1];
88 namespaces = ( tmp[2] || "" ).split( "." ).sort();
90 // There *must* be a type, no attaching namespace-only handlers
95 // If event changes its type, use the special event handlers for the changed type
96 special = jQuery.event.special[ type ] || {};
98 // If selector defined, determine special event api type, otherwise given type
99 type = ( selector ? special.delegateType : special.bindType ) || type;
101 // Update special based on newly reset type
102 special = jQuery.event.special[ type ] || {};
104 // handleObj is passed to all event handlers
105 handleObj = jQuery.extend({
112 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
113 namespace: namespaces.join(".")
116 // Init the event handler queue if we're the first
117 if ( !(handlers = events[ type ]) ) {
118 handlers = events[ type ] = [];
119 handlers.delegateCount = 0;
121 // Only use addEventListener if the special events handler returns false
122 if ( !special.setup ||
123 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
125 if ( elem.addEventListener ) {
126 elem.addEventListener( type, eventHandle );
132 special.add.call( elem, handleObj );
134 if ( !handleObj.handler.guid ) {
135 handleObj.handler.guid = handler.guid;
139 // Add to the element's handler list, delegates in front
141 handlers.splice( handlers.delegateCount++, 0, handleObj );
143 handlers.push( handleObj );
146 // Keep track of which events have ever been used, for event optimization
147 jQuery.event.global[ type ] = true;
152 // Detach an event or set of events from an element
153 remove: function( elem, types, handler, selector, mappedTypes ) {
155 var j, origCount, tmp,
156 events, t, handleObj,
157 special, handlers, type, namespaces, origType,
158 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
160 if ( !elemData || !(events = elemData.events) ) {
164 // Once for each type.namespace in types; type may be omitted
165 types = ( types || "" ).match( rnotwhite ) || [ "" ];
168 tmp = rtypenamespace.exec( types[t] ) || [];
169 type = origType = tmp[1];
170 namespaces = ( tmp[2] || "" ).split( "." ).sort();
172 // Unbind all events (on this namespace, if provided) for the element
174 for ( type in events ) {
175 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
180 special = jQuery.event.special[ type ] || {};
181 type = ( selector ? special.delegateType : special.bindType ) || type;
182 handlers = events[ type ] || [];
183 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
185 // Remove matching events
186 origCount = j = handlers.length;
188 handleObj = handlers[ j ];
190 if ( ( mappedTypes || origType === handleObj.origType ) &&
191 ( !handler || handler.guid === handleObj.guid ) &&
192 ( !tmp || tmp.test( handleObj.namespace ) ) &&
193 ( !selector || selector === handleObj.selector ||
194 selector === "**" && handleObj.selector ) ) {
195 handlers.splice( j, 1 );
197 if ( handleObj.selector ) {
198 handlers.delegateCount--;
200 if ( special.remove ) {
201 special.remove.call( elem, handleObj );
206 // Remove generic event handler if we removed something and no more handlers exist
207 // (avoids potential for endless recursion during removal of special event handlers)
208 if ( origCount && !handlers.length ) {
209 if ( !special.teardown ||
210 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
212 jQuery.removeEvent( elem, type, elemData.handle );
215 delete events[ type ];
219 // Remove the expando if it's no longer used
220 if ( jQuery.isEmptyObject( events ) ) {
221 // Normally this should go through the data api
222 // but since event.js owns these properties,
223 // this exception is made for the sake of optimizing
225 delete elemData.handle;
226 delete elemData.events;
230 trigger: function( event, data, elem, onlyHandlers ) {
232 var i, cur, tmp, bubbleType, ontype, handle, special,
233 eventPath = [ elem || document ],
234 type = hasOwn.call( event, "type" ) ? event.type : event,
235 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
237 cur = tmp = elem = elem || document;
239 // Don't do events on text and comment nodes
240 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
244 // focus/blur morphs to focusin/out; ensure we're not firing them right now
245 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
249 if ( type.indexOf(".") > -1 ) {
250 // Namespaced trigger; create a regexp to match event type in handle()
251 namespaces = type.split(".");
252 type = namespaces.shift();
255 ontype = type.indexOf(":") < 0 && "on" + type;
257 // Caller can pass in a jQuery.Event object, Object, or just an event type string
258 event = event[ jQuery.expando ] ?
260 new jQuery.Event( type, typeof event === "object" && event );
262 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
263 event.isTrigger = onlyHandlers ? 2 : 3;
264 event.namespace = namespaces.join(".");
265 event.rnamespace = event.namespace ?
266 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
269 // Clean up the event in case it is being reused
270 event.result = undefined;
271 if ( !event.target ) {
275 // Clone any incoming data and prepend the event, creating the handler arg list
276 data = data == null ?
278 jQuery.makeArray( data, [ event ] );
280 // Allow special events to draw outside the lines
281 special = jQuery.event.special[ type ] || {};
282 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
286 // Determine event propagation path in advance, per W3C events spec (#9951)
287 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
288 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
290 bubbleType = special.delegateType || type;
291 if ( !rfocusMorph.test( bubbleType + type ) ) {
292 cur = cur.parentNode;
294 for ( ; cur; cur = cur.parentNode ) {
295 eventPath.push( cur );
299 // Only add window if we got to document (e.g., not plain obj or detached DOM)
300 if ( tmp === (elem.ownerDocument || document) ) {
301 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
305 // Fire handlers on the event path
307 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
311 special.bindType || type;
314 handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
315 dataPriv.get( cur, "handle" );
317 handle.apply( cur, data );
321 handle = ontype && cur[ ontype ];
322 if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
323 event.result = handle.apply( cur, data );
324 if ( event.result === false ) {
325 event.preventDefault();
331 // If nobody prevented the default action, do it now
332 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
334 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
335 jQuery.acceptData( elem ) ) {
337 // Call a native DOM method on the target with the same name name as the event.
338 // Don't do default actions on window, that's where global variables be (#6170)
339 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
341 // Don't re-trigger an onFOO event when we call its FOO() method
342 tmp = elem[ ontype ];
345 elem[ ontype ] = null;
348 // Prevent re-triggering of the same event, since we already bubbled it above
349 jQuery.event.triggered = type;
351 jQuery.event.triggered = undefined;
354 elem[ ontype ] = tmp;
363 dispatch: function( event ) {
365 // Make a writable jQuery.Event from the native event object
366 event = jQuery.event.fix( event );
368 var i, j, ret, matched, handleObj,
370 args = slice.call( arguments ),
371 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
372 special = jQuery.event.special[ event.type ] || {};
374 // Use the fix-ed jQuery.Event rather than the (read-only) native event
376 event.delegateTarget = this;
378 // Call the preDispatch hook for the mapped type, and let it bail if desired
379 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
383 // Determine handlers
384 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
386 // Run delegates first; they may want to stop propagation beneath us
388 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
389 event.currentTarget = matched.elem;
392 while ( (handleObj = matched.handlers[ j++ ]) &&
393 !event.isImmediatePropagationStopped() ) {
395 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
396 // a subset or equal to those in the bound event (both can have no namespace).
397 if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
399 event.handleObj = handleObj;
400 event.data = handleObj.data;
402 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle ||
403 handleObj.handler ).apply( matched.elem, args );
405 if ( ret !== undefined ) {
406 if ( (event.result = ret) === false ) {
407 event.preventDefault();
408 event.stopPropagation();
415 // Call the postDispatch hook for the mapped type
416 if ( special.postDispatch ) {
417 special.postDispatch.call( this, event );
423 handlers: function( event, handlers ) {
424 var i, matches, sel, handleObj,
426 delegateCount = handlers.delegateCount,
429 // Support (at least): Chrome, IE9
430 // Find delegate handlers
431 // Black-hole SVG <use> instance trees (#13180)
434 // Avoid non-left-click bubbling in Firefox (#3861)
435 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
437 for ( ; cur !== this; cur = cur.parentNode || this ) {
439 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
440 if ( cur.disabled !== true || event.type !== "click" ) {
442 for ( i = 0; i < delegateCount; i++ ) {
443 handleObj = handlers[ i ];
445 // Don't conflict with Object.prototype properties (#13203)
446 sel = handleObj.selector + " ";
448 if ( matches[ sel ] === undefined ) {
449 matches[ sel ] = handleObj.needsContext ?
450 jQuery( sel, this ).index( cur ) > -1 :
451 jQuery.find( sel, this, null, [ cur ] ).length;
453 if ( matches[ sel ] ) {
454 matches.push( handleObj );
457 if ( matches.length ) {
458 handlerQueue.push({ elem: cur, handlers: matches });
464 // Add the remaining (directly-bound) handlers
465 if ( delegateCount < handlers.length ) {
466 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
472 // Includes some event props shared by KeyEvent and MouseEvent
473 props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
474 "metaKey relatedTarget shiftKey target timeStamp view which" ).split(" "),
479 props: "char charCode key keyCode".split(" "),
480 filter: function( event, original ) {
482 // Add which for key events
483 if ( event.which == null ) {
484 event.which = original.charCode != null ? original.charCode : original.keyCode;
492 props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
493 "screenX screenY toElement" ).split(" "),
494 filter: function( event, original ) {
495 var eventDoc, doc, body,
496 button = original.button;
498 // Calculate pageX/Y if missing and clientX/Y available
499 if ( event.pageX == null && original.clientX != null ) {
500 eventDoc = event.target.ownerDocument || document;
501 doc = eventDoc.documentElement;
502 body = eventDoc.body;
504 event.pageX = original.clientX +
505 ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
506 ( doc && doc.clientLeft || body && body.clientLeft || 0 );
507 event.pageY = original.clientY +
508 ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
509 ( doc && doc.clientTop || body && body.clientTop || 0 );
512 // Add which for click: 1 === left; 2 === middle; 3 === right
513 // Note: button is not normalized, so don't use it
514 if ( !event.which && button !== undefined ) {
515 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
522 fix: function( event ) {
523 if ( event[ jQuery.expando ] ) {
527 // Create a writable copy of the event object and normalize some properties
530 originalEvent = event,
531 fixHook = this.fixHooks[ type ];
534 this.fixHooks[ type ] = fixHook =
535 rmouseEvent.test( type ) ? this.mouseHooks :
536 rkeyEvent.test( type ) ? this.keyHooks :
539 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
541 event = new jQuery.Event( originalEvent );
546 event[ prop ] = originalEvent[ prop ];
549 // Support: Safari 6.0+
550 // Target should not be a text node (#504, #13143)
551 if ( event.target.nodeType === 3 ) {
552 event.target = event.target.parentNode;
555 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
560 // Prevent triggered image.load events from bubbling to window.load
564 // Fire native event if possible so blur/focus sequence is correct
565 trigger: function() {
566 if ( this !== safeActiveElement() && this.focus ) {
571 delegateType: "focusin"
574 trigger: function() {
575 if ( this === safeActiveElement() && this.blur ) {
580 delegateType: "focusout"
583 // For checkbox, fire native event so checked state will be right
584 trigger: function() {
585 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
591 // For cross-browser consistency, don't fire native .click() on links
592 _default: function( event ) {
593 return jQuery.nodeName( event.target, "a" );
598 postDispatch: function( event ) {
600 // Support: Firefox 20+
601 // Firefox doesn't alert if the returnValue field is not set.
602 if ( event.result !== undefined && event.originalEvent ) {
603 event.originalEvent.returnValue = event.result;
609 simulate: function( type, elem, event, bubble ) {
610 // Piggyback on a donor event to simulate a different one.
611 // Fake originalEvent to avoid donor's stopPropagation, but if the
612 // simulated event prevents default then we do the same on the donor.
613 var e = jQuery.extend(
623 jQuery.event.trigger( e, null, elem );
625 jQuery.event.dispatch.call( elem, e );
627 if ( e.isDefaultPrevented() ) {
628 event.preventDefault();
633 jQuery.removeEvent = function( elem, type, handle ) {
635 // This "if" is needed for plain objects
636 if ( elem.removeEventListener ) {
637 elem.removeEventListener( type, handle );
641 jQuery.Event = function( src, props ) {
642 // Allow instantiation without the 'new' keyword
643 if ( !(this instanceof jQuery.Event) ) {
644 return new jQuery.Event( src, props );
648 if ( src && src.type ) {
649 this.originalEvent = src;
650 this.type = src.type;
652 // Events bubbling up the document may have been marked as prevented
653 // by a handler lower down the tree; reflect the correct value.
654 this.isDefaultPrevented = src.defaultPrevented ||
655 src.defaultPrevented === undefined &&
656 // Support: Android<4.0
657 src.returnValue === false ?
666 // Put explicitly provided properties onto the event object
668 jQuery.extend( this, props );
671 // Create a timestamp if incoming event doesn't have one
672 this.timeStamp = src && src.timeStamp || jQuery.now();
675 this[ jQuery.expando ] = true;
678 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
679 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
680 jQuery.Event.prototype = {
681 constructor: jQuery.Event,
682 isDefaultPrevented: returnFalse,
683 isPropagationStopped: returnFalse,
684 isImmediatePropagationStopped: returnFalse,
686 preventDefault: function() {
687 var e = this.originalEvent;
689 this.isDefaultPrevented = returnTrue;
695 stopPropagation: function() {
696 var e = this.originalEvent;
698 this.isPropagationStopped = returnTrue;
704 stopImmediatePropagation: function() {
705 var e = this.originalEvent;
707 this.isImmediatePropagationStopped = returnTrue;
710 e.stopImmediatePropagation();
713 this.stopPropagation();
717 // Create mouseenter/leave events using mouseover/out and event-time checks
718 // so that event delegation works in jQuery.
719 // Do the same for pointerenter/pointerleave and pointerover/pointerout
721 // Support: Safari<7.0
722 // Safari doesn't support mouseenter/mouseleave at all.
724 // Support: Chrome 34+
725 // Mouseenter doesn't perform while left mouse button is pressed
726 // (and initiated outside the observed element)
727 // https://code.google.com/p/chromium/issues/detail?id=333868
729 mouseenter: "mouseover",
730 mouseleave: "mouseout",
731 pointerenter: "pointerover",
732 pointerleave: "pointerout"
733 }, function( orig, fix ) {
734 jQuery.event.special[ orig ] = {
738 handle: function( event ) {
741 related = event.relatedTarget,
742 handleObj = event.handleObj;
744 // For mousenter/leave call the handler if related is outside the target.
745 // NB: No relatedTarget if the mouse left/entered the browser window
746 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
747 event.type = handleObj.origType;
748 ret = handleObj.handler.apply( this, arguments );
756 // Support: Firefox, Chrome, Safari
757 // Create "bubbling" focus and blur events
758 if ( !support.focusinBubbles ) {
759 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
761 // Attach a single capturing handler on the document while someone wants focusin/focusout
762 var handler = function( event ) {
763 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
766 jQuery.event.special[ fix ] = {
768 var doc = this.ownerDocument || this,
769 attaches = dataPriv.access( doc, fix );
772 doc.addEventListener( orig, handler, true );
774 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
776 teardown: function() {
777 var doc = this.ownerDocument || this,
778 attaches = dataPriv.access( doc, fix ) - 1;
781 doc.removeEventListener( orig, handler, true );
782 dataPriv.remove( doc, fix );
785 dataPriv.access( doc, fix, attaches );
794 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
797 // Types can be a map of types/handlers
798 if ( typeof types === "object" ) {
799 // ( types-Object, selector, data )
800 if ( typeof selector !== "string" ) {
801 // ( types-Object, data )
802 data = data || selector;
803 selector = undefined;
805 for ( type in types ) {
806 this.on( type, selector, data, types[ type ], one );
811 if ( data == null && fn == null ) {
814 data = selector = undefined;
815 } else if ( fn == null ) {
816 if ( typeof selector === "string" ) {
817 // ( types, selector, fn )
821 // ( types, data, fn )
824 selector = undefined;
827 if ( fn === false ) {
833 fn = function( event ) {
834 // Can use an empty set, since event contains the info
835 jQuery().off( event );
836 return origFn.apply( this, arguments );
838 // Use same guid so caller can remove using origFn
839 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
841 return this.each( function() {
842 jQuery.event.add( this, types, fn, data, selector );
845 one: function( types, selector, data, fn ) {
846 return this.on( types, selector, data, fn, 1 );
848 off: function( types, selector, fn ) {
850 if ( types && types.preventDefault && types.handleObj ) {
851 // ( event ) dispatched jQuery.Event
852 handleObj = types.handleObj;
853 jQuery( types.delegateTarget ).off(
854 handleObj.namespace ?
855 handleObj.origType + "." + handleObj.namespace :
862 if ( typeof types === "object" ) {
863 // ( types-object [, selector] )
864 for ( type in types ) {
865 this.off( type, selector, types[ type ] );
869 if ( selector === false || typeof selector === "function" ) {
872 selector = undefined;
874 if ( fn === false ) {
877 return this.each(function() {
878 jQuery.event.remove( this, types, fn, selector );
882 trigger: function( type, data ) {
883 return this.each(function() {
884 jQuery.event.trigger( type, data, this );
887 triggerHandler: function( type, data ) {
890 return jQuery.event.trigger( type, data, elem, true );