10 ], function( jQuery, document, rnotwhite, slice, dataPriv ) {
14 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
15 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
17 function returnTrue() {
21 function returnFalse() {
26 // See #13393 for more info
27 function safeActiveElement() {
29 return document.activeElement;
33 function on( elem, types, selector, data, fn, one ) {
36 // Types can be a map of types/handlers
37 if ( typeof types === "object" ) {
39 // ( types-Object, selector, data )
40 if ( typeof selector !== "string" ) {
42 // ( types-Object, data )
43 data = data || selector;
46 for ( type in types ) {
47 on( elem, type, selector, data, types[ type ], one );
52 if ( data == null && fn == null ) {
56 data = selector = undefined;
57 } else if ( fn == null ) {
58 if ( typeof selector === "string" ) {
60 // ( types, selector, fn )
65 // ( types, data, fn )
79 fn = function( event ) {
81 // Can use an empty set, since event contains the info
82 jQuery().off( event );
83 return origFn.apply( this, arguments );
86 // Use same guid so caller can remove using origFn
87 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
89 return elem.each( function() {
90 jQuery.event.add( this, types, fn, data, selector );
95 * Helper functions for managing events -- not part of the public interface.
96 * Props to Dean Edwards' addEvent library for many of the ideas.
102 add: function( elem, types, handler, data, selector ) {
104 var handleObjIn, eventHandle, tmp,
105 events, t, handleObj,
106 special, handlers, type, namespaces, origType,
107 elemData = dataPriv.get( elem );
109 // Don't attach events to noData or text/comment nodes (but allow plain objects)
114 // Caller can pass in an object of custom data in lieu of the handler
115 if ( handler.handler ) {
116 handleObjIn = handler;
117 handler = handleObjIn.handler;
118 selector = handleObjIn.selector;
121 // Make sure that the handler has a unique ID, used to find/remove it later
122 if ( !handler.guid ) {
123 handler.guid = jQuery.guid++;
126 // Init the element's event structure and main handler, if this is the first
127 if ( !( events = elemData.events ) ) {
128 events = elemData.events = {};
130 if ( !( eventHandle = elemData.handle ) ) {
131 eventHandle = elemData.handle = function( e ) {
133 // Discard the second event of a jQuery.event.trigger() and
134 // when an event is called after a page has unloaded
135 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
136 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
140 // Handle multiple events separated by a space
141 types = ( types || "" ).match( rnotwhite ) || [ "" ];
144 tmp = rtypenamespace.exec( types[ t ] ) || [];
145 type = origType = tmp[ 1 ];
146 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
148 // There *must* be a type, no attaching namespace-only handlers
153 // If event changes its type, use the special event handlers for the changed type
154 special = jQuery.event.special[ type ] || {};
156 // If selector defined, determine special event api type, otherwise given type
157 type = ( selector ? special.delegateType : special.bindType ) || type;
159 // Update special based on newly reset type
160 special = jQuery.event.special[ type ] || {};
162 // handleObj is passed to all event handlers
163 handleObj = jQuery.extend( {
170 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
171 namespace: namespaces.join( "." )
174 // Init the event handler queue if we're the first
175 if ( !( handlers = events[ type ] ) ) {
176 handlers = events[ type ] = [];
177 handlers.delegateCount = 0;
179 // Only use addEventListener if the special events handler returns false
180 if ( !special.setup ||
181 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
183 if ( elem.addEventListener ) {
184 elem.addEventListener( type, eventHandle );
190 special.add.call( elem, handleObj );
192 if ( !handleObj.handler.guid ) {
193 handleObj.handler.guid = handler.guid;
197 // Add to the element's handler list, delegates in front
199 handlers.splice( handlers.delegateCount++, 0, handleObj );
201 handlers.push( handleObj );
204 // Keep track of which events have ever been used, for event optimization
205 jQuery.event.global[ type ] = true;
210 // Detach an event or set of events from an element
211 remove: function( elem, types, handler, selector, mappedTypes ) {
213 var j, origCount, tmp,
214 events, t, handleObj,
215 special, handlers, type, namespaces, origType,
216 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
218 if ( !elemData || !( events = elemData.events ) ) {
222 // Once for each type.namespace in types; type may be omitted
223 types = ( types || "" ).match( rnotwhite ) || [ "" ];
226 tmp = rtypenamespace.exec( types[ t ] ) || [];
227 type = origType = tmp[ 1 ];
228 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
230 // Unbind all events (on this namespace, if provided) for the element
232 for ( type in events ) {
233 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
238 special = jQuery.event.special[ type ] || {};
239 type = ( selector ? special.delegateType : special.bindType ) || type;
240 handlers = events[ type ] || [];
242 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
244 // Remove matching events
245 origCount = j = handlers.length;
247 handleObj = handlers[ j ];
249 if ( ( mappedTypes || origType === handleObj.origType ) &&
250 ( !handler || handler.guid === handleObj.guid ) &&
251 ( !tmp || tmp.test( handleObj.namespace ) ) &&
252 ( !selector || selector === handleObj.selector ||
253 selector === "**" && handleObj.selector ) ) {
254 handlers.splice( j, 1 );
256 if ( handleObj.selector ) {
257 handlers.delegateCount--;
259 if ( special.remove ) {
260 special.remove.call( elem, handleObj );
265 // Remove generic event handler if we removed something and no more handlers exist
266 // (avoids potential for endless recursion during removal of special event handlers)
267 if ( origCount && !handlers.length ) {
268 if ( !special.teardown ||
269 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
271 jQuery.removeEvent( elem, type, elemData.handle );
274 delete events[ type ];
278 // Remove data and the expando if it's no longer used
279 if ( jQuery.isEmptyObject( events ) ) {
280 dataPriv.remove( elem, "handle events" );
284 dispatch: function( event ) {
286 // Make a writable jQuery.Event from the native event object
287 event = jQuery.event.fix( event );
289 var i, j, ret, matched, handleObj,
291 args = slice.call( arguments ),
292 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
293 special = jQuery.event.special[ event.type ] || {};
295 // Use the fix-ed jQuery.Event rather than the (read-only) native event
297 event.delegateTarget = this;
299 // Call the preDispatch hook for the mapped type, and let it bail if desired
300 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
304 // Determine handlers
305 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
307 // Run delegates first; they may want to stop propagation beneath us
309 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
310 event.currentTarget = matched.elem;
313 while ( ( handleObj = matched.handlers[ j++ ] ) &&
314 !event.isImmediatePropagationStopped() ) {
316 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
317 // a subset or equal to those in the bound event (both can have no namespace).
318 if ( !event.rnamespace || 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();
336 // Call the postDispatch hook for the mapped type
337 if ( special.postDispatch ) {
338 special.postDispatch.call( this, event );
344 handlers: function( event, handlers ) {
345 var i, matches, sel, handleObj,
347 delegateCount = handlers.delegateCount,
350 // Support (at least): Chrome, IE9
351 // Find delegate handlers
352 // Black-hole SVG <use> instance trees (#13180)
354 // Support: Firefox<=42+
355 // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
356 if ( delegateCount && cur.nodeType &&
357 ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
359 for ( ; cur !== this; cur = cur.parentNode || this ) {
361 // Don't check non-elements (#13208)
362 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
363 if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
365 for ( i = 0; i < delegateCount; i++ ) {
366 handleObj = handlers[ i ];
368 // Don't conflict with Object.prototype properties (#13203)
369 sel = handleObj.selector + " ";
371 if ( matches[ sel ] === undefined ) {
372 matches[ sel ] = handleObj.needsContext ?
373 jQuery( sel, this ).index( cur ) > -1 :
374 jQuery.find( sel, this, null, [ cur ] ).length;
376 if ( matches[ sel ] ) {
377 matches.push( handleObj );
380 if ( matches.length ) {
381 handlerQueue.push( { elem: cur, handlers: matches } );
387 // Add the remaining (directly-bound) handlers
388 if ( delegateCount < handlers.length ) {
389 handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
395 // Includes some event props shared by KeyEvent and MouseEvent
396 props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
397 "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),
402 props: "char charCode key keyCode".split( " " ),
403 filter: function( event, original ) {
405 // Add which for key events
406 if ( event.which == null ) {
407 event.which = original.charCode != null ? original.charCode : original.keyCode;
415 props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
416 "screenX screenY toElement" ).split( " " ),
417 filter: function( event, original ) {
418 var eventDoc, doc, body,
419 button = original.button;
421 // Calculate pageX/Y if missing and clientX/Y available
422 if ( event.pageX == null && original.clientX != null ) {
423 eventDoc = event.target.ownerDocument || document;
424 doc = eventDoc.documentElement;
425 body = eventDoc.body;
427 event.pageX = original.clientX +
428 ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
429 ( doc && doc.clientLeft || body && body.clientLeft || 0 );
430 event.pageY = original.clientY +
431 ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
432 ( doc && doc.clientTop || body && body.clientTop || 0 );
435 // Add which for click: 1 === left; 2 === middle; 3 === right
436 // Note: button is not normalized, so don't use it
437 if ( !event.which && button !== undefined ) {
438 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
445 fix: function( event ) {
446 if ( event[ jQuery.expando ] ) {
450 // Create a writable copy of the event object and normalize some properties
453 originalEvent = event,
454 fixHook = this.fixHooks[ type ];
457 this.fixHooks[ type ] = fixHook =
458 rmouseEvent.test( type ) ? this.mouseHooks :
459 rkeyEvent.test( type ) ? this.keyHooks :
462 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
464 event = new jQuery.Event( originalEvent );
469 event[ prop ] = originalEvent[ prop ];
472 // Support: Cordova 2.5 (WebKit) (#13255)
473 // All events should have a target; Cordova deviceready doesn't
474 if ( !event.target ) {
475 event.target = document;
478 // Support: Safari 6.0+, Chrome<28
479 // Target should not be a text node (#504, #13143)
480 if ( event.target.nodeType === 3 ) {
481 event.target = event.target.parentNode;
484 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
490 // Prevent triggered image.load events from bubbling to window.load
495 // Fire native event if possible so blur/focus sequence is correct
496 trigger: function() {
497 if ( this !== safeActiveElement() && this.focus ) {
502 delegateType: "focusin"
505 trigger: function() {
506 if ( this === safeActiveElement() && this.blur ) {
511 delegateType: "focusout"
515 // For checkbox, fire native event so checked state will be right
516 trigger: function() {
517 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
523 // For cross-browser consistency, don't fire native .click() on links
524 _default: function( event ) {
525 return jQuery.nodeName( event.target, "a" );
530 postDispatch: function( event ) {
532 // Support: Firefox 20+
533 // Firefox doesn't alert if the returnValue field is not set.
534 if ( event.result !== undefined && event.originalEvent ) {
535 event.originalEvent.returnValue = event.result;
542 jQuery.removeEvent = function( elem, type, handle ) {
544 // This "if" is needed for plain objects
545 if ( elem.removeEventListener ) {
546 elem.removeEventListener( type, handle );
550 jQuery.Event = function( src, props ) {
552 // Allow instantiation without the 'new' keyword
553 if ( !( this instanceof jQuery.Event ) ) {
554 return new jQuery.Event( src, props );
558 if ( src && src.type ) {
559 this.originalEvent = src;
560 this.type = src.type;
562 // Events bubbling up the document may have been marked as prevented
563 // by a handler lower down the tree; reflect the correct value.
564 this.isDefaultPrevented = src.defaultPrevented ||
565 src.defaultPrevented === undefined &&
567 // Support: Android<4.0
568 src.returnValue === false ?
577 // Put explicitly provided properties onto the event object
579 jQuery.extend( this, props );
582 // Create a timestamp if incoming event doesn't have one
583 this.timeStamp = src && src.timeStamp || jQuery.now();
586 this[ jQuery.expando ] = true;
589 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
590 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
591 jQuery.Event.prototype = {
592 constructor: jQuery.Event,
593 isDefaultPrevented: returnFalse,
594 isPropagationStopped: returnFalse,
595 isImmediatePropagationStopped: returnFalse,
598 preventDefault: function() {
599 var e = this.originalEvent;
601 this.isDefaultPrevented = returnTrue;
603 if ( e && !this.isSimulated ) {
607 stopPropagation: function() {
608 var e = this.originalEvent;
610 this.isPropagationStopped = returnTrue;
612 if ( e && !this.isSimulated ) {
616 stopImmediatePropagation: function() {
617 var e = this.originalEvent;
619 this.isImmediatePropagationStopped = returnTrue;
621 if ( e && !this.isSimulated ) {
622 e.stopImmediatePropagation();
625 this.stopPropagation();
629 // Create mouseenter/leave events using mouseover/out and event-time checks
630 // so that event delegation works in jQuery.
631 // Do the same for pointerenter/pointerleave and pointerover/pointerout
633 // Support: Safari 7 only
634 // Safari sends mouseenter too often; see:
635 // https://code.google.com/p/chromium/issues/detail?id=470258
636 // for the description of the bug (it existed in older Chrome versions as well).
638 mouseenter: "mouseover",
639 mouseleave: "mouseout",
640 pointerenter: "pointerover",
641 pointerleave: "pointerout"
642 }, function( orig, fix ) {
643 jQuery.event.special[ orig ] = {
647 handle: function( event ) {
650 related = event.relatedTarget,
651 handleObj = event.handleObj;
653 // For mouseenter/leave call the handler if related is outside the target.
654 // NB: No relatedTarget if the mouse left/entered the browser window
655 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
656 event.type = handleObj.origType;
657 ret = handleObj.handler.apply( this, arguments );
666 on: function( types, selector, data, fn ) {
667 return on( this, types, selector, data, fn );
669 one: function( types, selector, data, fn ) {
670 return on( this, types, selector, data, fn, 1 );
672 off: function( types, selector, fn ) {
674 if ( types && types.preventDefault && types.handleObj ) {
676 // ( event ) dispatched jQuery.Event
677 handleObj = types.handleObj;
678 jQuery( types.delegateTarget ).off(
679 handleObj.namespace ?
680 handleObj.origType + "." + handleObj.namespace :
687 if ( typeof types === "object" ) {
689 // ( types-object [, selector] )
690 for ( type in types ) {
691 this.off( type, selector, types[ type ] );
695 if ( selector === false || typeof selector === "function" ) {
699 selector = undefined;
701 if ( fn === false ) {
704 return this.each( function() {
705 jQuery.event.remove( this, types, fn, selector );