3 var rnamespaces = /\.(.*)$/,
4 rformElems = /^(?:textarea|input|select)$/i,
7 rescape = /[^\w\s.|`]/g,
8 fcleanup = function( nm ) {
9 return nm.replace(rescape, "\\$&");
11 focusCounts = { focusin: 0, focusout: 0 },
15 * A number of helper functions used for managing events.
16 * Many of the ideas behind this code originated from
17 * Dean Edwards' addEvent library.
21 // Bind an event to an element
22 // Original by Dean Edwards
23 add: function( elem, types, handler, data ) {
24 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
28 // For whatever reason, IE has trouble passing the window object
29 // around, causing it to be cloned in the process
30 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
34 if ( handler === false ) {
35 handler = returnFalse;
36 } else if ( !handler ) {
37 // Fixes bug #7229. Fix recommended by jdalton
41 var handleObjIn, handleObj;
43 if ( handler.handler ) {
44 handleObjIn = handler;
45 handler = handleObjIn.handler;
48 // Make sure that the function being executed has a unique ID
49 if ( !handler.guid ) {
50 handler.guid = jQuery.guid++;
53 // Init the element's event structure
54 var elemData = jQuery._data( elem );
56 // If no elemData is found then we must be trying to bind to one of the
57 // banned noData elements
62 var events = elemData[ eventKey ],
63 eventHandle = elemData.handle;
65 if ( typeof events === "function" ) {
66 // On plain objects events is a fn that holds the the data
67 // which prevents this data from being JSON serialized
68 // the function does not need to be called, it just contains the data
69 eventHandle = events.handle;
70 events = events.events;
72 } else if ( !events ) {
73 if ( !elem.nodeType ) {
74 // On plain objects, create a fn that acts as the holder
75 // of the values to avoid JSON serialization of event data
76 elemData[ eventKey ] = elemData = function(){};
79 elemData.events = events = {};
83 elemData.handle = eventHandle = function() {
84 // Handle the second event of a trigger and when
85 // an event is called after a page has unloaded
86 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
87 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
92 // Add elem as a property of the handle function
93 // This is to prevent a memory leak with non-native events in IE.
94 eventHandle.elem = elem;
96 // Handle multiple events separated by a space
97 // jQuery(...).bind("mouseover mouseout", fn);
98 types = types.split(" ");
100 var type, i = 0, namespaces;
102 while ( (type = types[ i++ ]) ) {
103 handleObj = handleObjIn ?
104 jQuery.extend({}, handleObjIn) :
105 { handler: handler, data: data };
107 // Namespaced event handlers
108 if ( type.indexOf(".") > -1 ) {
109 namespaces = type.split(".");
110 type = namespaces.shift();
111 handleObj.namespace = namespaces.slice(0).sort().join(".");
115 handleObj.namespace = "";
118 handleObj.type = type;
119 if ( !handleObj.guid ) {
120 handleObj.guid = handler.guid;
123 // Get the current list of functions bound to this event
124 var handlers = events[ type ],
125 special = jQuery.event.special[ type ] || {};
127 // Init the event handler queue
129 handlers = events[ type ] = [];
131 // Check for a special event handler
132 // Only use addEventListener/attachEvent if the special
133 // events handler returns false
134 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
135 // Bind the global event handler to the element
136 if ( elem.addEventListener ) {
137 elem.addEventListener( type, eventHandle, false );
139 } else if ( elem.attachEvent ) {
140 elem.attachEvent( "on" + type, eventHandle );
146 special.add.call( elem, handleObj );
148 if ( !handleObj.handler.guid ) {
149 handleObj.handler.guid = handler.guid;
153 // Add the function to the element's handler list
154 handlers.push( handleObj );
156 // Keep track of which events have been used, for global triggering
157 jQuery.event.global[ type ] = true;
160 // Nullify elem to prevent memory leaks in IE
166 // Detach an event or set of events from an element
167 remove: function( elem, types, handler, pos ) {
168 // don't do events on text and comment nodes
169 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
173 if ( handler === false ) {
174 handler = returnFalse;
177 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
178 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
179 events = elemData && elemData[ eventKey ];
181 if ( !elemData || !events ) {
185 if ( typeof events === "function" ) {
187 events = events.events;
190 // types is actually an event object here
191 if ( types && types.type ) {
192 handler = types.handler;
196 // Unbind all events for the element
197 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
200 for ( type in events ) {
201 jQuery.event.remove( elem, type + types );
207 // Handle multiple events separated by a space
208 // jQuery(...).unbind("mouseover mouseout", fn);
209 types = types.split(" ");
211 while ( (type = types[ i++ ]) ) {
214 all = type.indexOf(".") < 0;
218 // Namespaced event handlers
219 namespaces = type.split(".");
220 type = namespaces.shift();
222 namespace = new RegExp("(^|\\.)" +
223 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
226 eventType = events[ type ];
233 for ( j = 0; j < eventType.length; j++ ) {
234 handleObj = eventType[ j ];
236 if ( all || namespace.test( handleObj.namespace ) ) {
237 jQuery.event.remove( elem, origType, handleObj.handler, j );
238 eventType.splice( j--, 1 );
245 special = jQuery.event.special[ type ] || {};
247 for ( j = pos || 0; j < eventType.length; j++ ) {
248 handleObj = eventType[ j ];
250 if ( handler.guid === handleObj.guid ) {
251 // remove the given handler for the given type
252 if ( all || namespace.test( handleObj.namespace ) ) {
254 eventType.splice( j--, 1 );
257 if ( special.remove ) {
258 special.remove.call( elem, handleObj );
268 // remove generic event handler if no more handlers exist
269 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
270 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
271 jQuery.removeEvent( elem, type, elemData.handle );
275 delete events[ type ];
279 // Remove the expando if it's no longer used
280 if ( jQuery.isEmptyObject( events ) ) {
281 var handle = elemData.handle;
286 delete elemData.events;
287 delete elemData.handle;
289 if ( typeof elemData === "function" ) {
290 jQuery.removeData( elem, eventKey, true );
292 } else if ( jQuery.isEmptyObject( elemData ) ) {
293 jQuery.removeData( elem, undefined, true );
298 // bubbling is internal
299 trigger: function( event, data, elem /*, bubbling */ ) {
300 // Event object or event type
301 var type = event.type || event,
302 bubbling = arguments[3];
305 event = typeof event === "object" ?
306 // jQuery.Event object
307 event[ jQuery.expando ] ? event :
309 jQuery.extend( jQuery.Event(type), event ) :
310 // Just the event type (string)
313 if ( type.indexOf("!") >= 0 ) {
314 event.type = type = type.slice(0, -1);
315 event.exclusive = true;
318 // Handle a global trigger
320 // Don't bubble custom events when global (to avoid too much overhead)
321 event.stopPropagation();
323 // Only trigger if we've ever bound an event for it
324 if ( jQuery.event.global[ type ] ) {
325 // XXX This code smells terrible. event.js should not be directly
326 // inspecting the data cache
327 jQuery.each( jQuery.cache, function() {
328 // internalKey variable is just used to make it easier to find
329 // and potentially change this stuff later; currently it just
330 // points to jQuery.expando
331 var internalKey = jQuery.expando,
332 internalCache = this[ internalKey ];
333 if ( internalCache && internalCache.events && internalCache.events[type] ) {
334 jQuery.event.trigger( event, data, internalCache.handle.elem );
340 // Handle triggering a single element
342 // don't do events on text and comment nodes
343 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
347 // Clean up in case it is reused
348 event.result = undefined;
351 // Clone the incoming data, if any
352 data = jQuery.makeArray( data );
353 data.unshift( event );
356 event.currentTarget = elem;
358 // Trigger the event, it is assumed that "handle" is a function
359 var handle = elem.nodeType ?
360 jQuery._data( elem, "handle" ) :
361 (jQuery._data( elem, eventKey ) || {}).handle;
364 handle.apply( elem, data );
367 var parent = elem.parentNode || elem.ownerDocument;
369 // Trigger an inline bound script
371 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
372 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
373 event.result = false;
374 event.preventDefault();
378 // prevent IE from throwing an error for some elements with some event types, see #3533
379 } catch (inlineError) {}
381 if ( !event.isPropagationStopped() && parent ) {
382 jQuery.event.trigger( event, data, parent, true );
384 } else if ( !event.isDefaultPrevented() ) {
386 target = event.target,
387 targetType = type.replace( rnamespaces, "" ),
388 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
389 special = jQuery.event.special[ targetType ] || {};
391 if ( (!special._default || special._default.call( elem, event ) === false) &&
392 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
395 if ( target[ targetType ] ) {
396 // Make sure that we don't accidentally re-trigger the onFOO events
397 old = target[ "on" + targetType ];
400 target[ "on" + targetType ] = null;
403 jQuery.event.triggered = true;
404 target[ targetType ]();
407 // prevent IE from throwing an error for some elements with some event types, see #3533
408 } catch (triggerError) {}
411 target[ "on" + targetType ] = old;
414 jQuery.event.triggered = false;
419 handle: function( event ) {
420 var all, handlers, namespaces, namespace_re, events,
422 args = jQuery.makeArray( arguments );
424 event = args[0] = jQuery.event.fix( event || window.event );
425 event.currentTarget = this;
427 // Namespaced event handlers
428 all = event.type.indexOf(".") < 0 && !event.exclusive;
431 namespaces = event.type.split(".");
432 event.type = namespaces.shift();
433 namespace_sort = namespaces.slice(0).sort();
434 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
437 event.namespace = event.namespace || namespace_sort.join(".");
439 events = jQuery._data(this, eventKey);
441 if ( typeof events === "function" ) {
442 events = events.events;
445 handlers = (events || {})[ event.type ];
447 if ( events && handlers ) {
448 // Clone the handlers to prevent manipulation
449 handlers = handlers.slice(0);
451 for ( var j = 0, l = handlers.length; j < l; j++ ) {
452 var handleObj = handlers[ j ];
454 // Filter the functions by class
455 if ( all || namespace_re.test( handleObj.namespace ) ) {
456 // Pass in a reference to the handler function itself
457 // So that we can later remove it
458 event.handler = handleObj.handler;
459 event.data = handleObj.data;
460 event.handleObj = handleObj;
462 var ret = handleObj.handler.apply( this, args );
464 if ( ret !== undefined ) {
466 if ( ret === false ) {
467 event.preventDefault();
468 event.stopPropagation();
472 if ( event.isImmediatePropagationStopped() ) {
482 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(" "),
484 fix: function( event ) {
485 if ( event[ jQuery.expando ] ) {
489 // store a copy of the original event object
490 // and "clone" to set read-only properties
491 var originalEvent = event;
492 event = jQuery.Event( originalEvent );
494 for ( var i = this.props.length, prop; i; ) {
495 prop = this.props[ --i ];
496 event[ prop ] = originalEvent[ prop ];
499 // Fix target property, if necessary
500 if ( !event.target ) {
501 // Fixes #1925 where srcElement might not be defined either
502 event.target = event.srcElement || document;
505 // check if target is a textnode (safari)
506 if ( event.target.nodeType === 3 ) {
507 event.target = event.target.parentNode;
510 // Add relatedTarget, if necessary
511 if ( !event.relatedTarget && event.fromElement ) {
512 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
515 // Calculate pageX/Y if missing and clientX/Y available
516 if ( event.pageX == null && event.clientX != null ) {
517 var doc = document.documentElement,
518 body = document.body;
520 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
521 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
524 // Add which for key events
525 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
526 event.which = event.charCode != null ? event.charCode : event.keyCode;
529 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
530 if ( !event.metaKey && event.ctrlKey ) {
531 event.metaKey = event.ctrlKey;
534 // Add which for click: 1 === left; 2 === middle; 3 === right
535 // Note: button is not normalized, so don't use it
536 if ( !event.which && event.button !== undefined ) {
537 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
543 // Deprecated, use jQuery.guid instead
546 // Deprecated, use jQuery.proxy instead
551 // Make sure the ready event is setup
552 setup: jQuery.bindReady,
553 teardown: jQuery.noop
557 add: function( handleObj ) {
558 jQuery.event.add( this,
559 liveConvert( handleObj.origType, handleObj.selector ),
560 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
563 remove: function( handleObj ) {
564 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
569 setup: function( data, namespaces, eventHandle ) {
570 // We only want to do this special case on windows
571 if ( jQuery.isWindow( this ) ) {
572 this.onbeforeunload = eventHandle;
576 teardown: function( namespaces, eventHandle ) {
577 if ( this.onbeforeunload === eventHandle ) {
578 this.onbeforeunload = null;
585 jQuery.removeEvent = document.removeEventListener ?
586 function( elem, type, handle ) {
587 if ( elem.removeEventListener ) {
588 elem.removeEventListener( type, handle, false );
591 function( elem, type, handle ) {
592 if ( elem.detachEvent ) {
593 elem.detachEvent( "on" + type, handle );
597 jQuery.Event = function( src ) {
598 // Allow instantiation without the 'new' keyword
599 if ( !this.preventDefault ) {
600 return new jQuery.Event( src );
604 if ( src && src.type ) {
605 this.originalEvent = src;
606 this.type = src.type;
608 // Events bubbling up the document may have been marked as prevented
609 // by a handler lower down the tree; reflect the correct value.
610 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
611 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
618 // timeStamp is buggy for some events on Firefox(#3843)
619 // So we won't rely on the native value
620 this.timeStamp = jQuery.now();
623 this[ jQuery.expando ] = true;
626 function returnFalse() {
629 function returnTrue() {
633 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
634 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
635 jQuery.Event.prototype = {
636 preventDefault: function() {
637 this.isDefaultPrevented = returnTrue;
639 var e = this.originalEvent;
644 // if preventDefault exists run it on the original event
645 if ( e.preventDefault ) {
648 // otherwise set the returnValue property of the original event to false (IE)
650 e.returnValue = false;
653 stopPropagation: function() {
654 this.isPropagationStopped = returnTrue;
656 var e = this.originalEvent;
660 // if stopPropagation exists run it on the original event
661 if ( e.stopPropagation ) {
664 // otherwise set the cancelBubble property of the original event to true (IE)
665 e.cancelBubble = true;
667 stopImmediatePropagation: function() {
668 this.isImmediatePropagationStopped = returnTrue;
669 this.stopPropagation();
671 isDefaultPrevented: returnFalse,
672 isPropagationStopped: returnFalse,
673 isImmediatePropagationStopped: returnFalse
676 // Checks if an event happened on an element within another element
677 // Used in jQuery.event.special.mouseenter and mouseleave handlers
678 var withinElement = function( event ) {
679 // Check if mouse(over|out) are still within the same parent element
680 var parent = event.relatedTarget;
682 // Firefox sometimes assigns relatedTarget a XUL element
683 // which we cannot access the parentNode property of
685 // Traverse up the tree
686 while ( parent && parent !== this ) {
687 parent = parent.parentNode;
690 if ( parent !== this ) {
691 // set the correct event type
692 event.type = event.data;
694 // handle event if we actually just moused on to a non sub-element
695 jQuery.event.handle.apply( this, arguments );
698 // assuming we've left the element since we most likely mousedover a xul element
702 // In case of event delegation, we only need to rename the event.type,
703 // liveHandler will take care of the rest.
704 delegate = function( event ) {
705 event.type = event.data;
706 jQuery.event.handle.apply( this, arguments );
709 // Create mouseenter and mouseleave events
711 mouseenter: "mouseover",
712 mouseleave: "mouseout"
713 }, function( orig, fix ) {
714 jQuery.event.special[ orig ] = {
715 setup: function( data ) {
716 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
718 teardown: function( data ) {
719 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
725 if ( !jQuery.support.submitBubbles ) {
727 jQuery.event.special.submit = {
728 setup: function( data, namespaces ) {
729 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
730 jQuery.event.add(this, "click.specialSubmit", function( e ) {
734 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
735 e.liveFired = undefined;
736 return trigger( "submit", this, arguments );
740 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
744 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
745 e.liveFired = undefined;
746 return trigger( "submit", this, arguments );
755 teardown: function( namespaces ) {
756 jQuery.event.remove( this, ".specialSubmit" );
762 // change delegation, happens here so we have bind.
763 if ( !jQuery.support.changeBubbles ) {
767 getVal = function( elem ) {
768 var type = elem.type, val = elem.value;
770 if ( type === "radio" || type === "checkbox" ) {
773 } else if ( type === "select-multiple" ) {
774 val = elem.selectedIndex > -1 ?
775 jQuery.map( elem.options, function( elem ) {
776 return elem.selected;
780 } else if ( elem.nodeName.toLowerCase() === "select" ) {
781 val = elem.selectedIndex;
787 testChange = function testChange( e ) {
788 var elem = e.target, data, val;
790 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
794 data = jQuery._data( elem, "_change_data" );
797 // the current data will be also retrieved by beforeactivate
798 if ( e.type !== "focusout" || elem.type !== "radio" ) {
799 jQuery._data( elem, "_change_data", val );
802 if ( data === undefined || val === data ) {
806 if ( data != null || val ) {
808 e.liveFired = undefined;
809 return jQuery.event.trigger( e, arguments[1], elem );
813 jQuery.event.special.change = {
815 focusout: testChange,
817 beforedeactivate: testChange,
819 click: function( e ) {
820 var elem = e.target, type = elem.type;
822 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
823 return testChange.call( this, e );
827 // Change has to be called before submit
828 // Keydown will be called before keypress, which is used in submit-event delegation
829 keydown: function( e ) {
830 var elem = e.target, type = elem.type;
832 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
833 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
834 type === "select-multiple" ) {
835 return testChange.call( this, e );
839 // Beforeactivate happens also before the previous element is blurred
840 // with this event you can't trigger a change event, but you can store
842 beforeactivate: function( e ) {
844 jQuery._data( elem, "_change_data", getVal(elem) );
848 setup: function( data, namespaces ) {
849 if ( this.type === "file" ) {
853 for ( var type in changeFilters ) {
854 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
857 return rformElems.test( this.nodeName );
860 teardown: function( namespaces ) {
861 jQuery.event.remove( this, ".specialChange" );
863 return rformElems.test( this.nodeName );
867 changeFilters = jQuery.event.special.change.filters;
869 // Handle when the input is .focus()'d
870 changeFilters.focus = changeFilters.beforeactivate;
873 function trigger( type, elem, args ) {
875 return jQuery.event.handle.apply( elem, args );
878 // Create "bubbling" focus and blur events
879 if ( document.addEventListener ) {
880 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
881 jQuery.event.special[ fix ] = {
883 if ( focusCounts[fix]++ === 0 ) {
884 document.addEventListener( orig, handler, true );
887 teardown: function() {
888 if ( --focusCounts[fix] === 0 ) {
889 document.removeEventListener( orig, handler, true );
894 function handler( e ) {
895 e = jQuery.event.fix( e );
897 return jQuery.event.trigger( e, null, e.target );
902 jQuery.each(["bind", "one"], function( i, name ) {
903 jQuery.fn[ name ] = function( type, data, fn ) {
904 // Handle object literals
905 if ( typeof type === "object" ) {
906 for ( var key in type ) {
907 this[ name ](key, data, type[key], fn);
912 if ( jQuery.isFunction( data ) || data === false ) {
917 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
918 jQuery( this ).unbind( event, handler );
919 return fn.apply( this, arguments );
922 if ( type === "unload" && name !== "one" ) {
923 this.one( type, data, fn );
926 for ( var i = 0, l = this.length; i < l; i++ ) {
927 jQuery.event.add( this[i], type, handler, data );
936 unbind: function( type, fn ) {
937 // Handle object literals
938 if ( typeof type === "object" && !type.preventDefault ) {
939 for ( var key in type ) {
940 this.unbind(key, type[key]);
944 for ( var i = 0, l = this.length; i < l; i++ ) {
945 jQuery.event.remove( this[i], type, fn );
952 delegate: function( selector, types, data, fn ) {
953 return this.live( types, data, fn, selector );
956 undelegate: function( selector, types, fn ) {
957 if ( arguments.length === 0 ) {
958 return this.unbind( "live" );
961 return this.die( types, null, fn, selector );
965 trigger: function( type, data ) {
966 return this.each(function() {
967 jQuery.event.trigger( type, data, this );
971 triggerHandler: function( type, data ) {
973 var event = jQuery.Event( type );
974 event.preventDefault();
975 event.stopPropagation();
976 jQuery.event.trigger( event, data, this[0] );
981 toggle: function( fn ) {
982 // Save reference to arguments for access in closure
983 var args = arguments,
986 // link all the functions, so any of them can unbind this click handler
987 while ( i < args.length ) {
988 jQuery.proxy( fn, args[ i++ ] );
991 return this.click( jQuery.proxy( fn, function( event ) {
992 // Figure out which function to execute
993 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
994 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
996 // Make sure that clicks stop
997 event.preventDefault();
999 // and execute the function
1000 return args[ lastToggle ].apply( this, arguments ) || false;
1004 hover: function( fnOver, fnOut ) {
1005 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
1012 mouseenter: "mouseover",
1013 mouseleave: "mouseout"
1016 jQuery.each(["live", "die"], function( i, name ) {
1017 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
1018 var type, i = 0, match, namespaces, preType,
1019 selector = origSelector || this.selector,
1020 context = origSelector ? this : jQuery( this.context );
1022 if ( typeof types === "object" && !types.preventDefault ) {
1023 for ( var key in types ) {
1024 context[ name ]( key, data, types[key], selector );
1030 if ( jQuery.isFunction( data ) ) {
1035 types = (types || "").split(" ");
1037 while ( (type = types[ i++ ]) != null ) {
1038 match = rnamespaces.exec( type );
1042 namespaces = match[0];
1043 type = type.replace( rnamespaces, "" );
1046 if ( type === "hover" ) {
1047 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1053 if ( type === "focus" || type === "blur" ) {
1054 types.push( liveMap[ type ] + namespaces );
1055 type = type + namespaces;
1058 type = (liveMap[ type ] || type) + namespaces;
1061 if ( name === "live" ) {
1062 // bind live handler
1063 for ( var j = 0, l = context.length; j < l; j++ ) {
1064 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1065 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1069 // unbind live handler
1070 context.unbind( "live." + liveConvert( type, selector ), fn );
1078 function liveHandler( event ) {
1079 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1082 events = jQuery._data( this, eventKey );
1084 if ( typeof events === "function" ) {
1085 events = events.events;
1088 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1089 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1093 if ( event.namespace ) {
1094 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1097 event.liveFired = this;
1099 var live = events.live.slice(0);
1101 for ( j = 0; j < live.length; j++ ) {
1102 handleObj = live[j];
1104 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1105 selectors.push( handleObj.selector );
1108 live.splice( j--, 1 );
1112 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1114 for ( i = 0, l = match.length; i < l; i++ ) {
1117 for ( j = 0; j < live.length; j++ ) {
1118 handleObj = live[j];
1120 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1124 // Those two events require additional checking
1125 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1126 event.type = handleObj.preType;
1127 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1130 if ( !related || related !== elem ) {
1131 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1137 for ( i = 0, l = elems.length; i < l; i++ ) {
1140 if ( maxLevel && match.level > maxLevel ) {
1144 event.currentTarget = match.elem;
1145 event.data = match.handleObj.data;
1146 event.handleObj = match.handleObj;
1148 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1150 if ( ret === false || event.isPropagationStopped() ) {
1151 maxLevel = match.level;
1153 if ( ret === false ) {
1156 if ( event.isImmediatePropagationStopped() ) {
1165 function liveConvert( type, selector ) {
1166 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1169 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1170 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1171 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1173 // Handle event binding
1174 jQuery.fn[ name ] = function( data, fn ) {
1180 return arguments.length > 0 ?
1181 this.bind( name, data, fn ) :
1182 this.trigger( name );
1185 if ( jQuery.attrFn ) {
1186 jQuery.attrFn[ name ] = true;