8 "./data/var/data_priv",
13 ], function( jQuery, strundefined, rnotwhite, hasOwn, slice, support, data_priv ) {
17 rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
18 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
19 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
21 function returnTrue() {
25 function returnFalse() {
29 function safeActiveElement() {
31 return document.activeElement;
36 * Helper functions for managing events -- not part of the public interface.
37 * Props to Dean Edwards' addEvent library for many of the ideas.
43 add: function( elem, types, handler, data, selector ) {
45 var handleObjIn, eventHandle, tmp,
47 special, handlers, type, namespaces, origType,
48 elemData = data_priv.get( elem );
50 // Don't attach events to noData or text/comment nodes (but allow plain objects)
55 // Caller can pass in an object of custom data in lieu of the handler
56 if ( handler.handler ) {
57 handleObjIn = handler;
58 handler = handleObjIn.handler;
59 selector = handleObjIn.selector;
62 // Make sure that the handler has a unique ID, used to find/remove it later
63 if ( !handler.guid ) {
64 handler.guid = jQuery.guid++;
67 // Init the element's event structure and main handler, if this is the first
68 if ( !(events = elemData.events) ) {
69 events = elemData.events = {};
71 if ( !(eventHandle = elemData.handle) ) {
72 eventHandle = elemData.handle = function( e ) {
73 // Discard the second event of a jQuery.event.trigger() and
74 // when an event is called after a page has unloaded
75 return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
76 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
80 // Handle multiple events separated by a space
81 types = ( types || "" ).match( rnotwhite ) || [ "" ];
84 tmp = rtypenamespace.exec( types[t] ) || [];
85 type = origType = tmp[1];
86 namespaces = ( tmp[2] || "" ).split( "." ).sort();
88 // There *must* be a type, no attaching namespace-only handlers
93 // If event changes its type, use the special event handlers for the changed type
94 special = jQuery.event.special[ type ] || {};
96 // If selector defined, determine special event api type, otherwise given type
97 type = ( selector ? special.delegateType : special.bindType ) || type;
99 // Update special based on newly reset type
100 special = jQuery.event.special[ type ] || {};
102 // handleObj is passed to all event handlers
103 handleObj = jQuery.extend({
110 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
111 namespace: namespaces.join(".")
114 // Init the event handler queue if we're the first
115 if ( !(handlers = events[ type ]) ) {
116 handlers = events[ type ] = [];
117 handlers.delegateCount = 0;
119 // Only use addEventListener if the special events handler returns false
120 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
121 if ( elem.addEventListener ) {
122 elem.addEventListener( type, eventHandle, false );
128 special.add.call( elem, handleObj );
130 if ( !handleObj.handler.guid ) {
131 handleObj.handler.guid = handler.guid;
135 // Add to the element's handler list, delegates in front
137 handlers.splice( handlers.delegateCount++, 0, handleObj );
139 handlers.push( handleObj );
142 // Keep track of which events have ever been used, for event optimization
143 jQuery.event.global[ type ] = true;
148 // Detach an event or set of events from an element
149 remove: function( elem, types, handler, selector, mappedTypes ) {
151 var j, origCount, tmp,
152 events, t, handleObj,
153 special, handlers, type, namespaces, origType,
154 elemData = data_priv.hasData( elem ) && data_priv.get( elem );
156 if ( !elemData || !(events = elemData.events) ) {
160 // Once for each type.namespace in types; type may be omitted
161 types = ( types || "" ).match( rnotwhite ) || [ "" ];
164 tmp = rtypenamespace.exec( types[t] ) || [];
165 type = origType = tmp[1];
166 namespaces = ( tmp[2] || "" ).split( "." ).sort();
168 // Unbind all events (on this namespace, if provided) for the element
170 for ( type in events ) {
171 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
176 special = jQuery.event.special[ type ] || {};
177 type = ( selector ? special.delegateType : special.bindType ) || type;
178 handlers = events[ type ] || [];
179 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
181 // Remove matching events
182 origCount = j = handlers.length;
184 handleObj = handlers[ j ];
186 if ( ( mappedTypes || origType === handleObj.origType ) &&
187 ( !handler || handler.guid === handleObj.guid ) &&
188 ( !tmp || tmp.test( handleObj.namespace ) ) &&
189 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
190 handlers.splice( j, 1 );
192 if ( handleObj.selector ) {
193 handlers.delegateCount--;
195 if ( special.remove ) {
196 special.remove.call( elem, handleObj );
201 // Remove generic event handler if we removed something and no more handlers exist
202 // (avoids potential for endless recursion during removal of special event handlers)
203 if ( origCount && !handlers.length ) {
204 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
205 jQuery.removeEvent( elem, type, elemData.handle );
208 delete events[ type ];
212 // Remove the expando if it's no longer used
213 if ( jQuery.isEmptyObject( events ) ) {
214 delete elemData.handle;
215 data_priv.remove( elem, "events" );
219 trigger: function( event, data, elem, onlyHandlers ) {
221 var i, cur, tmp, bubbleType, ontype, handle, special,
222 eventPath = [ elem || document ],
223 type = hasOwn.call( event, "type" ) ? event.type : event,
224 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
226 cur = tmp = elem = elem || document;
228 // Don't do events on text and comment nodes
229 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
233 // focus/blur morphs to focusin/out; ensure we're not firing them right now
234 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
238 if ( type.indexOf(".") >= 0 ) {
239 // Namespaced trigger; create a regexp to match event type in handle()
240 namespaces = type.split(".");
241 type = namespaces.shift();
244 ontype = type.indexOf(":") < 0 && "on" + type;
246 // Caller can pass in a jQuery.Event object, Object, or just an event type string
247 event = event[ jQuery.expando ] ?
249 new jQuery.Event( type, typeof event === "object" && event );
251 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
252 event.isTrigger = onlyHandlers ? 2 : 3;
253 event.namespace = namespaces.join(".");
254 event.namespace_re = event.namespace ?
255 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
258 // Clean up the event in case it is being reused
259 event.result = undefined;
260 if ( !event.target ) {
264 // Clone any incoming data and prepend the event, creating the handler arg list
265 data = data == null ?
267 jQuery.makeArray( data, [ event ] );
269 // Allow special events to draw outside the lines
270 special = jQuery.event.special[ type ] || {};
271 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
275 // Determine event propagation path in advance, per W3C events spec (#9951)
276 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
277 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
279 bubbleType = special.delegateType || type;
280 if ( !rfocusMorph.test( bubbleType + type ) ) {
281 cur = cur.parentNode;
283 for ( ; cur; cur = cur.parentNode ) {
284 eventPath.push( cur );
288 // Only add window if we got to document (e.g., not plain obj or detached DOM)
289 if ( tmp === (elem.ownerDocument || document) ) {
290 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
294 // Fire handlers on the event path
296 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
300 special.bindType || type;
303 handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
305 handle.apply( cur, data );
309 handle = ontype && cur[ ontype ];
310 if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
311 event.result = handle.apply( cur, data );
312 if ( event.result === false ) {
313 event.preventDefault();
319 // If nobody prevented the default action, do it now
320 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
322 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
323 jQuery.acceptData( elem ) ) {
325 // Call a native DOM method on the target with the same name name as the event.
326 // Don't do default actions on window, that's where global variables be (#6170)
327 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
329 // Don't re-trigger an onFOO event when we call its FOO() method
330 tmp = elem[ ontype ];
333 elem[ ontype ] = null;
336 // Prevent re-triggering of the same event, since we already bubbled it above
337 jQuery.event.triggered = type;
339 jQuery.event.triggered = undefined;
342 elem[ ontype ] = tmp;
351 dispatch: function( event ) {
353 // Make a writable jQuery.Event from the native event object
354 event = jQuery.event.fix( event );
356 var i, j, ret, matched, handleObj,
358 args = slice.call( arguments ),
359 handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
360 special = jQuery.event.special[ event.type ] || {};
362 // Use the fix-ed jQuery.Event rather than the (read-only) native event
364 event.delegateTarget = this;
366 // Call the preDispatch hook for the mapped type, and let it bail if desired
367 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
371 // Determine handlers
372 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
374 // Run delegates first; they may want to stop propagation beneath us
376 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
377 event.currentTarget = matched.elem;
380 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
382 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
383 // a subset or equal to those in the bound event (both can have no namespace).
384 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
386 event.handleObj = handleObj;
387 event.data = handleObj.data;
389 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
390 .apply( matched.elem, args );
392 if ( ret !== undefined ) {
393 if ( (event.result = ret) === false ) {
394 event.preventDefault();
395 event.stopPropagation();
402 // Call the postDispatch hook for the mapped type
403 if ( special.postDispatch ) {
404 special.postDispatch.call( this, event );
410 handlers: function( event, handlers ) {
411 var i, matches, sel, handleObj,
413 delegateCount = handlers.delegateCount,
416 // Find delegate handlers
417 // Black-hole SVG <use> instance trees (#13180)
418 // Avoid non-left-click bubbling in Firefox (#3861)
419 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
421 for ( ; cur !== this; cur = cur.parentNode || this ) {
423 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
424 if ( cur.disabled !== true || event.type !== "click" ) {
426 for ( i = 0; i < delegateCount; i++ ) {
427 handleObj = handlers[ i ];
429 // Don't conflict with Object.prototype properties (#13203)
430 sel = handleObj.selector + " ";
432 if ( matches[ sel ] === undefined ) {
433 matches[ sel ] = handleObj.needsContext ?
434 jQuery( sel, this ).index( cur ) >= 0 :
435 jQuery.find( sel, this, null, [ cur ] ).length;
437 if ( matches[ sel ] ) {
438 matches.push( handleObj );
441 if ( matches.length ) {
442 handlerQueue.push({ elem: cur, handlers: matches });
448 // Add the remaining (directly-bound) handlers
449 if ( delegateCount < handlers.length ) {
450 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
456 // Includes some event props shared by KeyEvent and MouseEvent
457 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
462 props: "char charCode key keyCode".split(" "),
463 filter: function( event, original ) {
465 // Add which for key events
466 if ( event.which == null ) {
467 event.which = original.charCode != null ? original.charCode : original.keyCode;
475 props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
476 filter: function( event, original ) {
477 var eventDoc, doc, body,
478 button = original.button;
480 // Calculate pageX/Y if missing and clientX/Y available
481 if ( event.pageX == null && original.clientX != null ) {
482 eventDoc = event.target.ownerDocument || document;
483 doc = eventDoc.documentElement;
484 body = eventDoc.body;
486 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
487 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
490 // Add which for click: 1 === left; 2 === middle; 3 === right
491 // Note: button is not normalized, so don't use it
492 if ( !event.which && button !== undefined ) {
493 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
500 fix: function( event ) {
501 if ( event[ jQuery.expando ] ) {
505 // Create a writable copy of the event object and normalize some properties
508 originalEvent = event,
509 fixHook = this.fixHooks[ type ];
512 this.fixHooks[ type ] = fixHook =
513 rmouseEvent.test( type ) ? this.mouseHooks :
514 rkeyEvent.test( type ) ? this.keyHooks :
517 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
519 event = new jQuery.Event( originalEvent );
524 event[ prop ] = originalEvent[ prop ];
527 // Support: Cordova 2.5 (WebKit) (#13255)
528 // All events should have a target; Cordova deviceready doesn't
529 if ( !event.target ) {
530 event.target = document;
533 // Support: Safari 6.0+, Chrome<28
534 // Target should not be a text node (#504, #13143)
535 if ( event.target.nodeType === 3 ) {
536 event.target = event.target.parentNode;
539 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
544 // Prevent triggered image.load events from bubbling to window.load
548 // Fire native event if possible so blur/focus sequence is correct
549 trigger: function() {
550 if ( this !== safeActiveElement() && this.focus ) {
555 delegateType: "focusin"
558 trigger: function() {
559 if ( this === safeActiveElement() && this.blur ) {
564 delegateType: "focusout"
567 // For checkbox, fire native event so checked state will be right
568 trigger: function() {
569 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
575 // For cross-browser consistency, don't fire native .click() on links
576 _default: function( event ) {
577 return jQuery.nodeName( event.target, "a" );
582 postDispatch: function( event ) {
584 // Support: Firefox 20+
585 // Firefox doesn't alert if the returnValue field is not set.
586 if ( event.result !== undefined && event.originalEvent ) {
587 event.originalEvent.returnValue = event.result;
593 simulate: function( type, elem, event, bubble ) {
594 // Piggyback on a donor event to simulate a different one.
595 // Fake originalEvent to avoid donor's stopPropagation, but if the
596 // simulated event prevents default then we do the same on the donor.
597 var e = jQuery.extend(
607 jQuery.event.trigger( e, null, elem );
609 jQuery.event.dispatch.call( elem, e );
611 if ( e.isDefaultPrevented() ) {
612 event.preventDefault();
617 jQuery.removeEvent = function( elem, type, handle ) {
618 if ( elem.removeEventListener ) {
619 elem.removeEventListener( type, handle, false );
623 jQuery.Event = function( src, props ) {
624 // Allow instantiation without the 'new' keyword
625 if ( !(this instanceof jQuery.Event) ) {
626 return new jQuery.Event( src, props );
630 if ( src && src.type ) {
631 this.originalEvent = src;
632 this.type = src.type;
634 // Events bubbling up the document may have been marked as prevented
635 // by a handler lower down the tree; reflect the correct value.
636 this.isDefaultPrevented = src.defaultPrevented ||
637 src.defaultPrevented === undefined &&
638 // Support: Android<4.0
639 src.returnValue === false ?
648 // Put explicitly provided properties onto the event object
650 jQuery.extend( this, props );
653 // Create a timestamp if incoming event doesn't have one
654 this.timeStamp = src && src.timeStamp || jQuery.now();
657 this[ jQuery.expando ] = true;
660 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
661 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
662 jQuery.Event.prototype = {
663 isDefaultPrevented: returnFalse,
664 isPropagationStopped: returnFalse,
665 isImmediatePropagationStopped: returnFalse,
667 preventDefault: function() {
668 var e = this.originalEvent;
670 this.isDefaultPrevented = returnTrue;
672 if ( e && e.preventDefault ) {
676 stopPropagation: function() {
677 var e = this.originalEvent;
679 this.isPropagationStopped = returnTrue;
681 if ( e && e.stopPropagation ) {
685 stopImmediatePropagation: function() {
686 var e = this.originalEvent;
688 this.isImmediatePropagationStopped = returnTrue;
690 if ( e && e.stopImmediatePropagation ) {
691 e.stopImmediatePropagation();
694 this.stopPropagation();
698 // Create mouseenter/leave events using mouseover/out and event-time checks
699 // Support: Chrome 15+
701 mouseenter: "mouseover",
702 mouseleave: "mouseout",
703 pointerenter: "pointerover",
704 pointerleave: "pointerout"
705 }, function( orig, fix ) {
706 jQuery.event.special[ orig ] = {
710 handle: function( event ) {
713 related = event.relatedTarget,
714 handleObj = event.handleObj;
716 // For mousenter/leave call the handler if related is outside the target.
717 // NB: No relatedTarget if the mouse left/entered the browser window
718 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
719 event.type = handleObj.origType;
720 ret = handleObj.handler.apply( this, arguments );
728 // Support: Firefox, Chrome, Safari
729 // Create "bubbling" focus and blur events
730 if ( !support.focusinBubbles ) {
731 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
733 // Attach a single capturing handler on the document while someone wants focusin/focusout
734 var handler = function( event ) {
735 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
738 jQuery.event.special[ fix ] = {
740 var doc = this.ownerDocument || this,
741 attaches = data_priv.access( doc, fix );
744 doc.addEventListener( orig, handler, true );
746 data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
748 teardown: function() {
749 var doc = this.ownerDocument || this,
750 attaches = data_priv.access( doc, fix ) - 1;
753 doc.removeEventListener( orig, handler, true );
754 data_priv.remove( doc, fix );
757 data_priv.access( doc, fix, attaches );
766 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
769 // Types can be a map of types/handlers
770 if ( typeof types === "object" ) {
771 // ( types-Object, selector, data )
772 if ( typeof selector !== "string" ) {
773 // ( types-Object, data )
774 data = data || selector;
775 selector = undefined;
777 for ( type in types ) {
778 this.on( type, selector, data, types[ type ], one );
783 if ( data == null && fn == null ) {
786 data = selector = undefined;
787 } else if ( fn == null ) {
788 if ( typeof selector === "string" ) {
789 // ( types, selector, fn )
793 // ( types, data, fn )
796 selector = undefined;
799 if ( fn === false ) {
807 fn = function( event ) {
808 // Can use an empty set, since event contains the info
809 jQuery().off( event );
810 return origFn.apply( this, arguments );
812 // Use same guid so caller can remove using origFn
813 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
815 return this.each( function() {
816 jQuery.event.add( this, types, fn, data, selector );
819 one: function( types, selector, data, fn ) {
820 return this.on( types, selector, data, fn, 1 );
822 off: function( types, selector, fn ) {
824 if ( types && types.preventDefault && types.handleObj ) {
825 // ( event ) dispatched jQuery.Event
826 handleObj = types.handleObj;
827 jQuery( types.delegateTarget ).off(
828 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
834 if ( typeof types === "object" ) {
835 // ( types-object [, selector] )
836 for ( type in types ) {
837 this.off( type, selector, types[ type ] );
841 if ( selector === false || typeof selector === "function" ) {
844 selector = undefined;
846 if ( fn === false ) {
849 return this.each(function() {
850 jQuery.event.remove( this, types, fn, selector );
854 trigger: function( type, data ) {
855 return this.each(function() {
856 jQuery.event.trigger( type, data, this );
859 triggerHandler: function( type, data ) {
862 return jQuery.event.trigger( type, data, elem, true );