3 var rnamespaces = /\.(.*)$/,
4 rformElems = /^(?:textarea|input|select)$/i,
7 rescape = /[^\w\s.|`]/g,
8 fcleanup = function( nm ) {
9 return nm.replace(rescape, "\\$&");
13 * A number of helper functions used for managing events.
14 * Many of the ideas behind this code originated from
15 * Dean Edwards' addEvent library.
19 // Bind an event to an element
20 // Original by Dean Edwards
21 add: function( elem, types, handler, data ) {
22 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
26 // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6)
27 // Minor release fix for bug #8018
29 // For whatever reason, IE has trouble passing the window object
30 // around, causing it to be cloned in the process
31 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
37 if ( handler === false ) {
38 handler = returnFalse;
39 } else if ( !handler ) {
40 // Fixes bug #7229. Fix recommended by jdalton
44 var handleObjIn, handleObj;
46 if ( handler.handler ) {
47 handleObjIn = handler;
48 handler = handleObjIn.handler;
51 // Make sure that the function being executed has a unique ID
52 if ( !handler.guid ) {
53 handler.guid = jQuery.guid++;
56 // Init the element's event structure
57 var elemData = jQuery._data( elem );
59 // If no elemData is found then we must be trying to bind to one of the
60 // banned noData elements
65 var events = elemData.events,
66 eventHandle = elemData.handle;
69 elemData.events = events = {};
73 elemData.handle = eventHandle = function( e ) {
74 // Handle the second event of a trigger and when
75 // an event is called after a page has unloaded
76 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
77 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
82 // Add elem as a property of the handle function
83 // This is to prevent a memory leak with non-native events in IE.
84 eventHandle.elem = elem;
86 // Handle multiple events separated by a space
87 // jQuery(...).bind("mouseover mouseout", fn);
88 types = types.split(" ");
90 var type, i = 0, namespaces;
92 while ( (type = types[ i++ ]) ) {
93 handleObj = handleObjIn ?
94 jQuery.extend({}, handleObjIn) :
95 { handler: handler, data: data };
97 // Namespaced event handlers
98 if ( type.indexOf(".") > -1 ) {
99 namespaces = type.split(".");
100 type = namespaces.shift();
101 handleObj.namespace = namespaces.slice(0).sort().join(".");
105 handleObj.namespace = "";
108 handleObj.type = type;
109 if ( !handleObj.guid ) {
110 handleObj.guid = handler.guid;
113 // Get the current list of functions bound to this event
114 var handlers = events[ type ],
115 special = jQuery.event.special[ type ] || {};
117 // Init the event handler queue
119 handlers = events[ type ] = [];
121 // Check for a special event handler
122 // Only use addEventListener/attachEvent if the special
123 // events handler returns false
124 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
125 // Bind the global event handler to the element
126 if ( elem.addEventListener ) {
127 elem.addEventListener( type, eventHandle, false );
129 } else if ( elem.attachEvent ) {
130 elem.attachEvent( "on" + type, eventHandle );
136 special.add.call( elem, handleObj );
138 if ( !handleObj.handler.guid ) {
139 handleObj.handler.guid = handler.guid;
143 // Add the function to the element's handler list
144 handlers.push( handleObj );
146 // Keep track of which events have been used, for global triggering
147 jQuery.event.global[ type ] = true;
150 // Nullify elem to prevent memory leaks in IE
156 // Detach an event or set of events from an element
157 remove: function( elem, types, handler, pos ) {
158 // don't do events on text and comment nodes
159 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
163 if ( handler === false ) {
164 handler = returnFalse;
167 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
168 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
169 events = elemData && elemData.events;
171 if ( !elemData || !events ) {
175 // types is actually an event object here
176 if ( types && types.type ) {
177 handler = types.handler;
181 // Unbind all events for the element
182 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
185 for ( type in events ) {
186 jQuery.event.remove( elem, type + types );
192 // Handle multiple events separated by a space
193 // jQuery(...).unbind("mouseover mouseout", fn);
194 types = types.split(" ");
196 while ( (type = types[ i++ ]) ) {
199 all = type.indexOf(".") < 0;
203 // Namespaced event handlers
204 namespaces = type.split(".");
205 type = namespaces.shift();
207 namespace = new RegExp("(^|\\.)" +
208 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
211 eventType = events[ type ];
218 for ( j = 0; j < eventType.length; j++ ) {
219 handleObj = eventType[ j ];
221 if ( all || namespace.test( handleObj.namespace ) ) {
222 jQuery.event.remove( elem, origType, handleObj.handler, j );
223 eventType.splice( j--, 1 );
230 special = jQuery.event.special[ type ] || {};
232 for ( j = pos || 0; j < eventType.length; j++ ) {
233 handleObj = eventType[ j ];
235 if ( handler.guid === handleObj.guid ) {
236 // remove the given handler for the given type
237 if ( all || namespace.test( handleObj.namespace ) ) {
239 eventType.splice( j--, 1 );
242 if ( special.remove ) {
243 special.remove.call( elem, handleObj );
253 // remove generic event handler if no more handlers exist
254 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
255 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
256 jQuery.removeEvent( elem, type, elemData.handle );
260 delete events[ type ];
264 // Remove the expando if it's no longer used
265 if ( jQuery.isEmptyObject( events ) ) {
266 var handle = elemData.handle;
271 delete elemData.events;
272 delete elemData.handle;
274 if ( jQuery.isEmptyObject( elemData ) ) {
275 jQuery.removeData( elem, undefined, true );
280 // bubbling is internal
281 trigger: function( event, data, elem /*, bubbling */ ) {
282 // Event object or event type
283 var type = event.type || event,
284 bubbling = arguments[3];
287 event = typeof event === "object" ?
288 // jQuery.Event object
289 event[ jQuery.expando ] ? event :
291 jQuery.extend( jQuery.Event(type), event ) :
292 // Just the event type (string)
295 if ( type.indexOf("!") >= 0 ) {
296 event.type = type = type.slice(0, -1);
297 event.exclusive = true;
300 // Handle a global trigger
302 // Don't bubble custom events when global (to avoid too much overhead)
303 event.stopPropagation();
305 // Only trigger if we've ever bound an event for it
306 if ( jQuery.event.global[ type ] ) {
307 // XXX This code smells terrible. event.js should not be directly
308 // inspecting the data cache
309 jQuery.each( jQuery.cache, function() {
310 // internalKey variable is just used to make it easier to find
311 // and potentially change this stuff later; currently it just
312 // points to jQuery.expando
313 var internalKey = jQuery.expando,
314 internalCache = this[ internalKey ];
315 if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
316 jQuery.event.trigger( event, data, internalCache.handle.elem );
322 // Handle triggering a single element
324 // don't do events on text and comment nodes
325 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
329 // Clean up in case it is reused
330 event.result = undefined;
333 // Clone the incoming data, if any
334 data = jQuery.makeArray( data );
335 data.unshift( event );
338 event.currentTarget = elem;
340 // Trigger the event, it is assumed that "handle" is a function
341 var handle = jQuery._data( elem, "handle" );
344 handle.apply( elem, data );
347 var parent = elem.parentNode || elem.ownerDocument;
349 // Trigger an inline bound script
351 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
352 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
353 event.result = false;
354 event.preventDefault();
358 // prevent IE from throwing an error for some elements with some event types, see #3533
359 } catch (inlineError) {}
361 if ( !event.isPropagationStopped() && parent ) {
362 jQuery.event.trigger( event, data, parent, true );
364 } else if ( !event.isDefaultPrevented() ) {
366 target = event.target,
367 targetType = type.replace( rnamespaces, "" ),
368 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
369 special = jQuery.event.special[ targetType ] || {};
371 if ( (!special._default || special._default.call( elem, event ) === false) &&
372 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
375 if ( target[ targetType ] ) {
376 // Make sure that we don't accidentally re-trigger the onFOO events
377 old = target[ "on" + targetType ];
380 target[ "on" + targetType ] = null;
383 jQuery.event.triggered = event.type;
384 target[ targetType ]();
387 // prevent IE from throwing an error for some elements with some event types, see #3533
388 } catch (triggerError) {}
391 target[ "on" + targetType ] = old;
394 jQuery.event.triggered = undefined;
399 handle: function( event ) {
400 var all, handlers, namespaces, namespace_re, events,
402 args = jQuery.makeArray( arguments );
404 event = args[0] = jQuery.event.fix( event || window.event );
405 event.currentTarget = this;
407 // Namespaced event handlers
408 all = event.type.indexOf(".") < 0 && !event.exclusive;
411 namespaces = event.type.split(".");
412 event.type = namespaces.shift();
413 namespace_sort = namespaces.slice(0).sort();
414 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
417 event.namespace = event.namespace || namespace_sort.join(".");
419 events = jQuery._data(this, "events");
421 handlers = (events || {})[ event.type ];
423 if ( events && handlers ) {
424 // Clone the handlers to prevent manipulation
425 handlers = handlers.slice(0);
427 for ( var j = 0, l = handlers.length; j < l; j++ ) {
428 var handleObj = handlers[ j ];
430 // Filter the functions by class
431 if ( all || namespace_re.test( handleObj.namespace ) ) {
432 // Pass in a reference to the handler function itself
433 // So that we can later remove it
434 event.handler = handleObj.handler;
435 event.data = handleObj.data;
436 event.handleObj = handleObj;
438 var ret = handleObj.handler.apply( this, args );
440 if ( ret !== undefined ) {
442 if ( ret === false ) {
443 event.preventDefault();
444 event.stopPropagation();
448 if ( event.isImmediatePropagationStopped() ) {
458 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(" "),
460 fix: function( event ) {
461 if ( event[ jQuery.expando ] ) {
465 // store a copy of the original event object
466 // and "clone" to set read-only properties
467 var originalEvent = event;
468 event = jQuery.Event( originalEvent );
470 for ( var i = this.props.length, prop; i; ) {
471 prop = this.props[ --i ];
472 event[ prop ] = originalEvent[ prop ];
475 // Fix target property, if necessary
476 if ( !event.target ) {
477 // Fixes #1925 where srcElement might not be defined either
478 event.target = event.srcElement || document;
481 // check if target is a textnode (safari)
482 if ( event.target.nodeType === 3 ) {
483 event.target = event.target.parentNode;
486 // Add relatedTarget, if necessary
487 if ( !event.relatedTarget && event.fromElement ) {
488 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
491 // Calculate pageX/Y if missing and clientX/Y available
492 if ( event.pageX == null && event.clientX != null ) {
493 var doc = document.documentElement,
494 body = document.body;
496 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
497 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
500 // Add which for key events
501 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
502 event.which = event.charCode != null ? event.charCode : event.keyCode;
505 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
506 if ( !event.metaKey && event.ctrlKey ) {
507 event.metaKey = event.ctrlKey;
510 // Add which for click: 1 === left; 2 === middle; 3 === right
511 // Note: button is not normalized, so don't use it
512 if ( !event.which && event.button !== undefined ) {
513 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
519 // Deprecated, use jQuery.guid instead
522 // Deprecated, use jQuery.proxy instead
527 // Make sure the ready event is setup
528 setup: jQuery.bindReady,
529 teardown: jQuery.noop
533 add: function( handleObj ) {
534 jQuery.event.add( this,
535 liveConvert( handleObj.origType, handleObj.selector ),
536 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
539 remove: function( handleObj ) {
540 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
545 setup: function( data, namespaces, eventHandle ) {
546 // We only want to do this special case on windows
547 if ( jQuery.isWindow( this ) ) {
548 this.onbeforeunload = eventHandle;
552 teardown: function( namespaces, eventHandle ) {
553 if ( this.onbeforeunload === eventHandle ) {
554 this.onbeforeunload = null;
561 jQuery.removeEvent = document.removeEventListener ?
562 function( elem, type, handle ) {
563 if ( elem.removeEventListener ) {
564 elem.removeEventListener( type, handle, false );
567 function( elem, type, handle ) {
568 if ( elem.detachEvent ) {
569 elem.detachEvent( "on" + type, handle );
573 jQuery.Event = function( src ) {
574 // Allow instantiation without the 'new' keyword
575 if ( !this.preventDefault ) {
576 return new jQuery.Event( src );
580 if ( src && src.type ) {
581 this.originalEvent = src;
582 this.type = src.type;
584 // Events bubbling up the document may have been marked as prevented
585 // by a handler lower down the tree; reflect the correct value.
586 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
587 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
594 // timeStamp is buggy for some events on Firefox(#3843)
595 // So we won't rely on the native value
596 this.timeStamp = jQuery.now();
599 this[ jQuery.expando ] = true;
602 function returnFalse() {
605 function returnTrue() {
609 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
610 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
611 jQuery.Event.prototype = {
612 preventDefault: function() {
613 this.isDefaultPrevented = returnTrue;
615 var e = this.originalEvent;
620 // if preventDefault exists run it on the original event
621 if ( e.preventDefault ) {
624 // otherwise set the returnValue property of the original event to false (IE)
626 e.returnValue = false;
629 stopPropagation: function() {
630 this.isPropagationStopped = returnTrue;
632 var e = this.originalEvent;
636 // if stopPropagation exists run it on the original event
637 if ( e.stopPropagation ) {
640 // otherwise set the cancelBubble property of the original event to true (IE)
641 e.cancelBubble = true;
643 stopImmediatePropagation: function() {
644 this.isImmediatePropagationStopped = returnTrue;
645 this.stopPropagation();
647 isDefaultPrevented: returnFalse,
648 isPropagationStopped: returnFalse,
649 isImmediatePropagationStopped: returnFalse
652 // Checks if an event happened on an element within another element
653 // Used in jQuery.event.special.mouseenter and mouseleave handlers
654 var withinElement = function( event ) {
655 // Check if mouse(over|out) are still within the same parent element
656 var parent = event.relatedTarget;
658 // Firefox sometimes assigns relatedTarget a XUL element
659 // which we cannot access the parentNode property of
662 // Chrome does something similar, the parentNode property
663 // can be accessed but is null.
664 if ( parent !== document && !parent.parentNode ) {
667 // Traverse up the tree
668 while ( parent && parent !== this ) {
669 parent = parent.parentNode;
672 if ( parent !== this ) {
673 // set the correct event type
674 event.type = event.data;
676 // handle event if we actually just moused on to a non sub-element
677 jQuery.event.handle.apply( this, arguments );
680 // assuming we've left the element since we most likely mousedover a xul element
684 // In case of event delegation, we only need to rename the event.type,
685 // liveHandler will take care of the rest.
686 delegate = function( event ) {
687 event.type = event.data;
688 jQuery.event.handle.apply( this, arguments );
691 // Create mouseenter and mouseleave events
693 mouseenter: "mouseover",
694 mouseleave: "mouseout"
695 }, function( orig, fix ) {
696 jQuery.event.special[ orig ] = {
697 setup: function( data ) {
698 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
700 teardown: function( data ) {
701 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
707 if ( !jQuery.support.submitBubbles ) {
709 jQuery.event.special.submit = {
710 setup: function( data, namespaces ) {
711 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
712 jQuery.event.add(this, "click.specialSubmit", function( e ) {
716 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
717 trigger( "submit", this, arguments );
721 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
725 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
726 trigger( "submit", this, arguments );
735 teardown: function( namespaces ) {
736 jQuery.event.remove( this, ".specialSubmit" );
742 // change delegation, happens here so we have bind.
743 if ( !jQuery.support.changeBubbles ) {
747 getVal = function( elem ) {
748 var type = elem.type, val = elem.value;
750 if ( type === "radio" || type === "checkbox" ) {
753 } else if ( type === "select-multiple" ) {
754 val = elem.selectedIndex > -1 ?
755 jQuery.map( elem.options, function( elem ) {
756 return elem.selected;
760 } else if ( elem.nodeName.toLowerCase() === "select" ) {
761 val = elem.selectedIndex;
767 testChange = function testChange( e ) {
768 var elem = e.target, data, val;
770 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
774 data = jQuery._data( elem, "_change_data" );
777 // the current data will be also retrieved by beforeactivate
778 if ( e.type !== "focusout" || elem.type !== "radio" ) {
779 jQuery._data( elem, "_change_data", val );
782 if ( data === undefined || val === data ) {
786 if ( data != null || val ) {
788 e.liveFired = undefined;
789 jQuery.event.trigger( e, arguments[1], elem );
793 jQuery.event.special.change = {
795 focusout: testChange,
797 beforedeactivate: testChange,
799 click: function( e ) {
800 var elem = e.target, type = elem.type;
802 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
803 testChange.call( this, e );
807 // Change has to be called before submit
808 // Keydown will be called before keypress, which is used in submit-event delegation
809 keydown: function( e ) {
810 var elem = e.target, type = elem.type;
812 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
813 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
814 type === "select-multiple" ) {
815 testChange.call( this, e );
819 // Beforeactivate happens also before the previous element is blurred
820 // with this event you can't trigger a change event, but you can store
822 beforeactivate: function( e ) {
824 jQuery._data( elem, "_change_data", getVal(elem) );
828 setup: function( data, namespaces ) {
829 if ( this.type === "file" ) {
833 for ( var type in changeFilters ) {
834 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
837 return rformElems.test( this.nodeName );
840 teardown: function( namespaces ) {
841 jQuery.event.remove( this, ".specialChange" );
843 return rformElems.test( this.nodeName );
847 changeFilters = jQuery.event.special.change.filters;
849 // Handle when the input is .focus()'d
850 changeFilters.focus = changeFilters.beforeactivate;
853 function trigger( type, elem, args ) {
854 // Piggyback on a donor event to simulate a different one.
855 // Fake originalEvent to avoid donor's stopPropagation, but if the
856 // simulated event prevents default then we do the same on the donor.
857 // Don't pass args or remember liveFired; they apply to the donor event.
858 var event = jQuery.extend( {}, args[ 0 ] );
860 event.originalEvent = {};
861 event.liveFired = undefined;
862 jQuery.event.handle.call( elem, event );
863 if ( event.isDefaultPrevented() ) {
864 args[ 0 ].preventDefault();
868 // Create "bubbling" focus and blur events
869 if ( document.addEventListener ) {
870 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
872 // Attach a single capturing handler while someone wants focusin/focusout
875 jQuery.event.special[ fix ] = {
877 if ( attaches++ === 0 ) {
878 document.addEventListener( orig, handler, true );
881 teardown: function() {
882 if ( --attaches === 0 ) {
883 document.removeEventListener( orig, handler, true );
888 function handler( donor ) {
889 // Donor event is always a native one; fix it and switch its type.
890 // Let focusin/out handler cancel the donor focus/blur event.
891 var e = jQuery.event.fix( donor );
893 e.originalEvent = {};
894 jQuery.event.trigger( e, null, e.target );
895 if ( e.isDefaultPrevented() ) {
896 donor.preventDefault();
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, "events" );
1084 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1085 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1089 if ( event.namespace ) {
1090 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1093 event.liveFired = this;
1095 var live = events.live.slice(0);
1097 for ( j = 0; j < live.length; j++ ) {
1098 handleObj = live[j];
1100 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1101 selectors.push( handleObj.selector );
1104 live.splice( j--, 1 );
1108 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1110 for ( i = 0, l = match.length; i < l; i++ ) {
1113 for ( j = 0; j < live.length; j++ ) {
1114 handleObj = live[j];
1116 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
1120 // Those two events require additional checking
1121 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1122 event.type = handleObj.preType;
1123 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1126 if ( !related || related !== elem ) {
1127 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1133 for ( i = 0, l = elems.length; i < l; i++ ) {
1136 if ( maxLevel && match.level > maxLevel ) {
1140 event.currentTarget = match.elem;
1141 event.data = match.handleObj.data;
1142 event.handleObj = match.handleObj;
1144 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1146 if ( ret === false || event.isPropagationStopped() ) {
1147 maxLevel = match.level;
1149 if ( ret === false ) {
1152 if ( event.isImmediatePropagationStopped() ) {
1161 function liveConvert( type, selector ) {
1162 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1165 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1166 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1167 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1169 // Handle event binding
1170 jQuery.fn[ name ] = function( data, fn ) {
1176 return arguments.length > 0 ?
1177 this.bind( name, data, fn ) :
1178 this.trigger( name );
1181 if ( jQuery.attrFn ) {
1182 jQuery.attrFn[ name ] = true;