3 var hasOwn = Object.prototype.hasOwnProperty,
4 rnamespaces = /\.(.*)$/,
5 rformElems = /^(?:textarea|input|select)$/i,
8 rescape = /[^\w\s.|`]/g,
9 fcleanup = function( nm ) {
10 return nm.replace(rescape, "\\$&");
14 * A number of helper functions used for managing events.
15 * Many of the ideas behind this code originated from
16 * Dean Edwards' addEvent library.
20 // Bind an event to an element
21 // Original by Dean Edwards
22 add: function( elem, types, handler, data ) {
23 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
27 if ( handler === false ) {
28 handler = returnFalse;
29 } else if ( !handler ) {
30 // Fixes bug #7229. Fix recommended by jdalton
34 var handleObjIn, handleObj;
36 if ( handler.handler ) {
37 handleObjIn = handler;
38 handler = handleObjIn.handler;
41 // Make sure that the function being executed has a unique ID
42 if ( !handler.guid ) {
43 handler.guid = jQuery.guid++;
46 // Init the element's event structure
47 var elemData = jQuery._data( elem );
49 // If no elemData is found then we must be trying to bind to one of the
50 // banned noData elements
55 var events = elemData.events,
56 eventHandle = elemData.handle;
59 elemData.events = events = {};
63 elemData.handle = eventHandle = function( e ) {
64 // Discard the second event of a jQuery.event.trigger() and
65 // when an event is called after a page has unloaded
66 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
67 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
72 // Add elem as a property of the handle function
73 // This is to prevent a memory leak with non-native events in IE.
74 eventHandle.elem = elem;
76 // Handle multiple events separated by a space
77 // jQuery(...).bind("mouseover mouseout", fn);
78 types = types.split(" ");
80 var type, i = 0, namespaces;
82 while ( (type = types[ i++ ]) ) {
83 handleObj = handleObjIn ?
84 jQuery.extend({}, handleObjIn) :
85 { handler: handler, data: data };
87 // Namespaced event handlers
88 if ( type.indexOf(".") > -1 ) {
89 namespaces = type.split(".");
90 type = namespaces.shift();
91 handleObj.namespace = namespaces.slice(0).sort().join(".");
95 handleObj.namespace = "";
98 handleObj.type = type;
99 if ( !handleObj.guid ) {
100 handleObj.guid = handler.guid;
103 // Get the current list of functions bound to this event
104 var handlers = events[ type ],
105 special = jQuery.event.special[ type ] || {};
107 // Init the event handler queue
109 handlers = events[ type ] = [];
111 // Check for a special event handler
112 // Only use addEventListener/attachEvent if the special
113 // events handler returns false
114 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
115 // Bind the global event handler to the element
116 if ( elem.addEventListener ) {
117 elem.addEventListener( type, eventHandle, false );
119 } else if ( elem.attachEvent ) {
120 elem.attachEvent( "on" + type, eventHandle );
126 special.add.call( elem, handleObj );
128 if ( !handleObj.handler.guid ) {
129 handleObj.handler.guid = handler.guid;
133 // Add the function to the element's handler list
134 handlers.push( handleObj );
136 // Keep track of which events have been used, for event optimization
137 jQuery.event.global[ type ] = true;
140 // Nullify elem to prevent memory leaks in IE
146 // Detach an event or set of events from an element
147 remove: function( elem, types, handler, pos ) {
148 // don't do events on text and comment nodes
149 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
153 if ( handler === false ) {
154 handler = returnFalse;
157 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
158 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
159 events = elemData && elemData.events;
161 if ( !elemData || !events ) {
165 // types is actually an event object here
166 if ( types && types.type ) {
167 handler = types.handler;
171 // Unbind all events for the element
172 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
175 for ( type in events ) {
176 jQuery.event.remove( elem, type + types );
182 // Handle multiple events separated by a space
183 // jQuery(...).unbind("mouseover mouseout", fn);
184 types = types.split(" ");
186 while ( (type = types[ i++ ]) ) {
189 all = type.indexOf(".") < 0;
193 // Namespaced event handlers
194 namespaces = type.split(".");
195 type = namespaces.shift();
197 namespace = new RegExp("(^|\\.)" +
198 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
201 eventType = events[ type ];
208 for ( j = 0; j < eventType.length; j++ ) {
209 handleObj = eventType[ j ];
211 if ( all || namespace.test( handleObj.namespace ) ) {
212 jQuery.event.remove( elem, origType, handleObj.handler, j );
213 eventType.splice( j--, 1 );
220 special = jQuery.event.special[ type ] || {};
222 for ( j = pos || 0; j < eventType.length; j++ ) {
223 handleObj = eventType[ j ];
225 if ( handler.guid === handleObj.guid ) {
226 // remove the given handler for the given type
227 if ( all || namespace.test( handleObj.namespace ) ) {
229 eventType.splice( j--, 1 );
232 if ( special.remove ) {
233 special.remove.call( elem, handleObj );
243 // remove generic event handler if no more handlers exist
244 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
245 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
246 jQuery.removeEvent( elem, type, elemData.handle );
250 delete events[ type ];
254 // Remove the expando if it's no longer used
255 if ( jQuery.isEmptyObject( events ) ) {
256 var handle = elemData.handle;
261 delete elemData.events;
262 delete elemData.handle;
264 if ( jQuery.isEmptyObject( elemData ) ) {
265 jQuery.removeData( elem, undefined, true );
270 // Events that are safe to short-circuit if no handlers are attached.
271 // Native DOM events should not be added, they may have inline handlers.
278 trigger: function( event, data, elem, onlyHandlers ) {
279 // Event object or event type
280 var type = event.type || event,
284 if ( type.indexOf("!") >= 0 ) {
285 // Exclusive events trigger only for the exact event (no namespaces)
286 type = type.slice(0, -1);
290 if ( type.indexOf(".") >= 0 ) {
291 // Namespaced trigger; create a regexp to match event type in handle()
292 namespaces = type.split(".");
293 type = namespaces.shift();
297 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
298 // No jQuery handlers for this event type, and it can't have inline handlers
302 // Caller can pass in an Event, Object, or just an event type string
303 event = typeof event === "object" ?
304 // jQuery.Event object
305 event[ jQuery.expando ] ? event :
307 new jQuery.Event( type, event ) :
308 // Just the event type (string)
309 new jQuery.Event( type );
312 event.exclusive = exclusive;
313 event.namespace = namespaces.join(".");
314 event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
316 // triggerHandler() and global events don't bubble or run the default action
317 if ( onlyHandlers || !elem ) {
318 event.preventDefault();
319 event.stopPropagation();
322 // Handle a global trigger
324 // TODO: Stop taunting the data cache; remove global events and always attach to document
325 jQuery.each( jQuery.cache, function() {
326 // internalKey variable is just used to make it easier to find
327 // and potentially change this stuff later; currently it just
328 // points to jQuery.expando
329 var internalKey = jQuery.expando,
330 internalCache = this[ internalKey ];
331 if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
332 jQuery.event.trigger( event, data, internalCache.handle.elem );
338 // Don't do events on text and comment nodes
339 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
343 // Clean up the event in case it is being reused
344 event.result = undefined;
347 // Clone any incoming data and prepend the event, creating the handler arg list
348 data = data ? jQuery.makeArray( data ) : [];
349 data.unshift( event );
352 // IE doesn't like method names with a colon (#3533, #8272)
353 ontype = type.indexOf(":") < 0 ? "on" + type : "";
355 // Fire event on the current element, then bubble up the DOM tree
357 var handle = jQuery._data( cur, "handle" );
359 event.currentTarget = cur;
361 handle.apply( cur, data );
364 // Trigger an inline bound script
365 if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
366 event.result = false;
367 event.preventDefault();
370 // Bubble up to document, then to window
371 cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
372 } while ( cur && !event.isPropagationStopped() );
374 // If nobody prevented the default action, do it now
375 if ( !event.isDefaultPrevented() ) {
377 special = jQuery.event.special[ type ] || {};
379 if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
380 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
382 // Call a native DOM method on the target with the same name name as the event.
383 // Can't use an .isFunction)() check here because IE6/7 fails that test.
384 // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
386 if ( ontype && elem[ type ] ) {
387 // Don't re-trigger an onFOO event when we call its FOO() method
388 old = elem[ ontype ];
391 elem[ ontype ] = null;
394 jQuery.event.triggered = type;
397 } catch ( ieError ) {}
400 elem[ ontype ] = old;
403 jQuery.event.triggered = undefined;
410 handle: function( event ) {
411 event = jQuery.event.fix( event || window.event );
412 // Snapshot the handlers list since a called handler may add/remove events.
413 var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
414 run_all = !event.exclusive && !event.namespace,
415 args = Array.prototype.slice.call( arguments, 0 );
417 // Use the fix-ed Event rather than the (read-only) native event
419 event.currentTarget = this;
421 for ( var j = 0, l = handlers.length; j < l; j++ ) {
422 var handleObj = handlers[ j ];
424 // Triggered event must 1) be non-exclusive and have no namespace, or
425 // 2) have namespace(s) a subset or equal to those in the bound event.
426 if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
427 // Pass in a reference to the handler function itself
428 // So that we can later remove it
429 event.handler = handleObj.handler;
430 event.data = handleObj.data;
431 event.handleObj = handleObj;
433 var ret = handleObj.handler.apply( this, args );
435 if ( ret !== undefined ) {
437 if ( ret === false ) {
438 event.preventDefault();
439 event.stopPropagation();
443 if ( event.isImmediatePropagationStopped() ) {
451 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
453 fix: function( event ) {
454 if ( event[ jQuery.expando ] ) {
458 // store a copy of the original event object
459 // and "clone" to set read-only properties
460 var originalEvent = event;
461 event = jQuery.Event( originalEvent );
463 for ( var i = this.props.length, prop; i; ) {
464 prop = this.props[ --i ];
465 event[ prop ] = originalEvent[ prop ];
468 // Fix target property, if necessary
469 if ( !event.target ) {
470 // Fixes #1925 where srcElement might not be defined either
471 event.target = event.srcElement || document;
474 // check if target is a textnode (safari)
475 if ( event.target.nodeType === 3 ) {
476 event.target = event.target.parentNode;
479 // Add relatedTarget, if necessary
480 if ( !event.relatedTarget && event.fromElement ) {
481 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
484 // Calculate pageX/Y if missing and clientX/Y available
485 if ( event.pageX == null && event.clientX != null ) {
486 var eventDocument = event.target.ownerDocument || document,
487 doc = eventDocument.documentElement,
488 body = eventDocument.body;
490 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
491 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
494 // Add which for key events
495 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
496 event.which = event.charCode != null ? event.charCode : event.keyCode;
499 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
500 if ( !event.metaKey && event.ctrlKey ) {
501 event.metaKey = event.ctrlKey;
504 // Add which for click: 1 === left; 2 === middle; 3 === right
505 // Note: button is not normalized, so don't use it
506 if ( !event.which && event.button !== undefined ) {
507 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
513 // Deprecated, use jQuery.guid instead
516 // Deprecated, use jQuery.proxy instead
521 // Make sure the ready event is setup
522 setup: jQuery.bindReady,
523 teardown: jQuery.noop
527 add: function( handleObj ) {
528 jQuery.event.add( this,
529 liveConvert( handleObj.origType, handleObj.selector ),
530 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
533 remove: function( handleObj ) {
534 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
539 setup: function( data, namespaces, eventHandle ) {
540 // We only want to do this special case on windows
541 if ( jQuery.isWindow( this ) ) {
542 this.onbeforeunload = eventHandle;
546 teardown: function( namespaces, eventHandle ) {
547 if ( this.onbeforeunload === eventHandle ) {
548 this.onbeforeunload = null;
555 jQuery.removeEvent = document.removeEventListener ?
556 function( elem, type, handle ) {
557 if ( elem.removeEventListener ) {
558 elem.removeEventListener( type, handle, false );
561 function( elem, type, handle ) {
562 if ( elem.detachEvent ) {
563 elem.detachEvent( "on" + type, handle );
567 jQuery.Event = function( src, props ) {
568 // Allow instantiation without the 'new' keyword
569 if ( !this.preventDefault ) {
570 return new jQuery.Event( src, props );
574 if ( src && src.type ) {
575 this.originalEvent = src;
576 this.type = src.type;
578 // Events bubbling up the document may have been marked as prevented
579 // by a handler lower down the tree; reflect the correct value.
580 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
581 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
588 // Put explicitly provided properties onto the event object
590 jQuery.extend( this, props );
593 // timeStamp is buggy for some events on Firefox(#3843)
594 // So we won't rely on the native value
595 this.timeStamp = jQuery.now();
598 this[ jQuery.expando ] = true;
601 function returnFalse() {
604 function returnTrue() {
608 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
609 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
610 jQuery.Event.prototype = {
611 preventDefault: function() {
612 this.isDefaultPrevented = returnTrue;
614 var e = this.originalEvent;
619 // if preventDefault exists run it on the original event
620 if ( e.preventDefault ) {
623 // otherwise set the returnValue property of the original event to false (IE)
625 e.returnValue = false;
628 stopPropagation: function() {
629 this.isPropagationStopped = returnTrue;
631 var e = this.originalEvent;
635 // if stopPropagation exists run it on the original event
636 if ( e.stopPropagation ) {
639 // otherwise set the cancelBubble property of the original event to true (IE)
640 e.cancelBubble = true;
642 stopImmediatePropagation: function() {
643 this.isImmediatePropagationStopped = returnTrue;
644 this.stopPropagation();
646 isDefaultPrevented: returnFalse,
647 isPropagationStopped: returnFalse,
648 isImmediatePropagationStopped: returnFalse
651 // Checks if an event happened on an element within another element
652 // Used in jQuery.event.special.mouseenter and mouseleave handlers
653 var withinElement = function( event ) {
654 // Check if mouse(over|out) are still within the same parent element
655 var parent = event.relatedTarget;
657 // Firefox sometimes assigns relatedTarget a XUL element
658 // which we cannot access the parentNode property of
661 // Chrome does something similar, the parentNode property
662 // can be accessed but is null.
663 if ( parent && parent !== document && !parent.parentNode ) {
666 // Traverse up the tree
667 while ( parent && parent !== this ) {
668 parent = parent.parentNode;
671 if ( parent !== this ) {
672 // set the correct event type
673 event.type = event.data;
675 // handle event if we actually just moused on to a non sub-element
676 jQuery.event.handle.apply( this, arguments );
679 // assuming we've left the element since we most likely mousedover a xul element
683 // In case of event delegation, we only need to rename the event.type,
684 // liveHandler will take care of the rest.
685 delegate = function( event ) {
686 event.type = event.data;
687 jQuery.event.handle.apply( this, arguments );
690 // Create mouseenter and mouseleave events
692 mouseenter: "mouseover",
693 mouseleave: "mouseout"
694 }, function( orig, fix ) {
695 jQuery.event.special[ orig ] = {
696 setup: function( data ) {
697 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
699 teardown: function( data ) {
700 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
706 if ( !jQuery.support.submitBubbles ) {
708 jQuery.event.special.submit = {
709 setup: function( data, namespaces ) {
710 if ( !jQuery.nodeName( this, "form" ) ) {
711 jQuery.event.add(this, "click.specialSubmit", function( e ) {
715 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
716 trigger( "submit", this, arguments );
720 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
724 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
725 trigger( "submit", this, arguments );
734 teardown: function( namespaces ) {
735 jQuery.event.remove( this, ".specialSubmit" );
741 // change delegation, happens here so we have bind.
742 if ( !jQuery.support.changeBubbles ) {
746 getVal = function( elem ) {
747 var type = elem.type, val = elem.value;
749 if ( type === "radio" || type === "checkbox" ) {
752 } else if ( type === "select-multiple" ) {
753 val = elem.selectedIndex > -1 ?
754 jQuery.map( elem.options, function( elem ) {
755 return elem.selected;
759 } else if ( jQuery.nodeName( elem, "select" ) ) {
760 val = elem.selectedIndex;
766 testChange = function testChange( e ) {
767 var elem = e.target, data, val;
769 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
773 data = jQuery._data( elem, "_change_data" );
776 // the current data will be also retrieved by beforeactivate
777 if ( e.type !== "focusout" || elem.type !== "radio" ) {
778 jQuery._data( elem, "_change_data", val );
781 if ( data === undefined || val === data ) {
785 if ( data != null || val ) {
787 e.liveFired = undefined;
788 jQuery.event.trigger( e, arguments[1], elem );
792 jQuery.event.special.change = {
794 focusout: testChange,
796 beforedeactivate: testChange,
798 click: function( e ) {
799 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
801 if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
802 testChange.call( this, e );
806 // Change has to be called before submit
807 // Keydown will be called before keypress, which is used in submit-event delegation
808 keydown: function( e ) {
809 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
811 if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
812 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
813 type === "select-multiple" ) {
814 testChange.call( this, e );
818 // Beforeactivate happens also before the previous element is blurred
819 // with this event you can't trigger a change event, but you can store
821 beforeactivate: function( e ) {
823 jQuery._data( elem, "_change_data", getVal(elem) );
827 setup: function( data, namespaces ) {
828 if ( this.type === "file" ) {
832 for ( var type in changeFilters ) {
833 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
836 return rformElems.test( this.nodeName );
839 teardown: function( namespaces ) {
840 jQuery.event.remove( this, ".specialChange" );
842 return rformElems.test( this.nodeName );
846 changeFilters = jQuery.event.special.change.filters;
848 // Handle when the input is .focus()'d
849 changeFilters.focus = changeFilters.beforeactivate;
852 function trigger( type, elem, args ) {
853 // Piggyback on a donor event to simulate a different one.
854 // Fake originalEvent to avoid donor's stopPropagation, but if the
855 // simulated event prevents default then we do the same on the donor.
856 // Don't pass args or remember liveFired; they apply to the donor event.
857 var event = jQuery.extend( {}, args[ 0 ] );
859 event.originalEvent = {};
860 event.liveFired = undefined;
861 jQuery.event.handle.call( elem, event );
862 if ( event.isDefaultPrevented() ) {
863 args[ 0 ].preventDefault();
867 // Create "bubbling" focus and blur events
868 if ( !jQuery.support.focusinBubbles ) {
869 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
871 // Attach a single capturing handler while someone wants focusin/focusout
874 jQuery.event.special[ fix ] = {
876 if ( attaches++ === 0 ) {
877 document.addEventListener( orig, handler, true );
880 teardown: function() {
881 if ( --attaches === 0 ) {
882 document.removeEventListener( orig, handler, true );
887 function handler( donor ) {
888 // Donor event is always a native one; fix it and switch its type.
889 // Let focusin/out handler cancel the donor focus/blur event.
890 var e = jQuery.event.fix( donor );
892 e.originalEvent = {};
893 jQuery.event.trigger( e, null, e.target );
894 if ( e.isDefaultPrevented() ) {
895 donor.preventDefault();
901 jQuery.each(["bind", "one"], function( i, name ) {
902 jQuery.fn[ name ] = function( type, data, fn ) {
905 // Handle object literals
906 if ( typeof type === "object" ) {
907 for ( var key in type ) {
908 this[ name ](key, data, type[key], fn);
913 if ( arguments.length === 2 || data === false ) {
918 if ( name === "one" ) {
919 handler = function( event ) {
920 jQuery( this ).unbind( event, handler );
921 return fn.apply( this, arguments );
923 handler.guid = fn.guid || jQuery.guid++;
928 if ( type === "unload" && name !== "one" ) {
929 this.one( type, data, fn );
932 for ( var i = 0, l = this.length; i < l; i++ ) {
933 jQuery.event.add( this[i], type, handler, data );
942 unbind: function( type, fn ) {
943 // Handle object literals
944 if ( typeof type === "object" && !type.preventDefault ) {
945 for ( var key in type ) {
946 this.unbind(key, type[key]);
950 for ( var i = 0, l = this.length; i < l; i++ ) {
951 jQuery.event.remove( this[i], type, fn );
958 delegate: function( selector, types, data, fn ) {
959 return this.live( types, data, fn, selector );
962 undelegate: function( selector, types, fn ) {
963 if ( arguments.length === 0 ) {
964 return this.unbind( "live" );
967 return this.die( types, null, fn, selector );
971 trigger: function( type, data ) {
972 return this.each(function() {
973 jQuery.event.trigger( type, data, this );
977 triggerHandler: function( type, data ) {
979 return jQuery.event.trigger( type, data, this[0], true );
983 toggle: function( fn ) {
984 // Save reference to arguments for access in closure
985 var args = arguments,
986 guid = fn.guid || jQuery.guid++,
988 toggler = function( event ) {
989 // Figure out which function to execute
990 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
991 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
993 // Make sure that clicks stop
994 event.preventDefault();
996 // and execute the function
997 return args[ lastToggle ].apply( this, arguments ) || false;
1000 // link all the functions, so any of them can unbind this click handler
1001 toggler.guid = guid;
1002 while ( i < args.length ) {
1003 args[ i++ ].guid = guid;
1006 return this.click( toggler );
1009 hover: function( fnOver, fnOut ) {
1010 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
1017 mouseenter: "mouseover",
1018 mouseleave: "mouseout"
1021 jQuery.each(["live", "die"], function( i, name ) {
1022 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
1023 var type, i = 0, match, namespaces, preType,
1024 selector = origSelector || this.selector,
1025 context = origSelector ? this : jQuery( this.context );
1027 if ( typeof types === "object" && !types.preventDefault ) {
1028 for ( var key in types ) {
1029 context[ name ]( key, data, types[key], selector );
1035 if ( name === "die" && !types &&
1036 origSelector && origSelector.charAt(0) === "." ) {
1038 context.unbind( origSelector );
1043 if ( data === false || jQuery.isFunction( data ) ) {
1044 fn = data || returnFalse;
1048 types = (types || "").split(" ");
1050 while ( (type = types[ i++ ]) != null ) {
1051 match = rnamespaces.exec( type );
1055 namespaces = match[0];
1056 type = type.replace( rnamespaces, "" );
1059 if ( type === "hover" ) {
1060 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1066 if ( liveMap[ type ] ) {
1067 types.push( liveMap[ type ] + namespaces );
1068 type = type + namespaces;
1071 type = (liveMap[ type ] || type) + namespaces;
1074 if ( name === "live" ) {
1075 // bind live handler
1076 for ( var j = 0, l = context.length; j < l; j++ ) {
1077 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1078 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1082 // unbind live handler
1083 context.unbind( "live." + liveConvert( type, selector ), fn );
1091 function liveHandler( event ) {
1092 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1095 events = jQuery._data( this, "events" );
1097 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1098 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1102 if ( event.namespace ) {
1103 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1106 event.liveFired = this;
1108 var live = events.live.slice(0);
1110 for ( j = 0; j < live.length; j++ ) {
1111 handleObj = live[j];
1113 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1114 selectors.push( handleObj.selector );
1117 live.splice( j--, 1 );
1121 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1123 for ( i = 0, l = match.length; i < l; i++ ) {
1126 for ( j = 0; j < live.length; j++ ) {
1127 handleObj = live[j];
1129 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
1133 // Those two events require additional checking
1134 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1135 event.type = handleObj.preType;
1136 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1138 // Make sure not to accidentally match a child element with the same selector
1139 if ( related && jQuery.contains( elem, related ) ) {
1144 if ( !related || related !== elem ) {
1145 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1151 for ( i = 0, l = elems.length; i < l; i++ ) {
1154 if ( maxLevel && match.level > maxLevel ) {
1158 event.currentTarget = match.elem;
1159 event.data = match.handleObj.data;
1160 event.handleObj = match.handleObj;
1162 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1164 if ( ret === false || event.isPropagationStopped() ) {
1165 maxLevel = match.level;
1167 if ( ret === false ) {
1170 if ( event.isImmediatePropagationStopped() ) {
1179 function liveConvert( type, selector ) {
1180 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
1183 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1184 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1185 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1187 // Handle event binding
1188 jQuery.fn[ name ] = function( data, fn ) {
1194 return arguments.length > 0 ?
1195 this.bind( name, data, fn ) :
1196 this.trigger( name );
1199 if ( jQuery.attrFn ) {
1200 jQuery.attrFn[ name ] = true;