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 };
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 // For whatever reason, IE has trouble passing the window object
28 // around, causing it to be cloned in the process
29 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
33 if ( handler === false ) {
34 handler = returnFalse;
35 } else if ( !handler ) {
36 // Fixes bug #7229. Fix recommended by jdalton
40 var handleObjIn, handleObj;
42 if ( handler.handler ) {
43 handleObjIn = handler;
44 handler = handleObjIn.handler;
47 // Make sure that the function being executed has a unique ID
48 if ( !handler.guid ) {
49 handler.guid = jQuery.guid++;
52 // Init the element's event structure
53 var elemData = jQuery.data( elem );
55 // If no elemData is found then we must be trying to bind to one of the
56 // banned noData elements
61 // Use a key less likely to result in collisions for plain JS objects.
63 var eventKey = elem.nodeType ? "events" : "__events__",
64 events = elemData[ eventKey ],
65 eventHandle = elemData.handle;
67 if ( typeof events === "function" ) {
68 // On plain objects events is a fn that holds the the data
69 // which prevents this data from being JSON serialized
70 // the function does not need to be called, it just contains the data
71 eventHandle = events.handle;
72 events = events.events;
74 } else if ( !events ) {
75 if ( !elem.nodeType ) {
76 // On plain objects, create a fn that acts as the holder
77 // of the values to avoid JSON serialization of event data
78 elemData[ eventKey ] = elemData = function(){};
81 elemData.events = events = {};
85 elemData.handle = eventHandle = function() {
86 // Handle the second event of a trigger and when
87 // an event is called after a page has unloaded
88 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
89 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
94 // Add elem as a property of the handle function
95 // This is to prevent a memory leak with non-native events in IE.
96 eventHandle.elem = elem;
98 // Handle multiple events separated by a space
99 // jQuery(...).bind("mouseover mouseout", fn);
100 types = types.split(" ");
102 var type, i = 0, namespaces;
104 while ( (type = types[ i++ ]) ) {
105 handleObj = handleObjIn ?
106 jQuery.extend({}, handleObjIn) :
107 { handler: handler, data: data };
109 // Namespaced event handlers
110 if ( type.indexOf(".") > -1 ) {
111 namespaces = type.split(".");
112 type = namespaces.shift();
113 handleObj.namespace = namespaces.slice(0).sort().join(".");
117 handleObj.namespace = "";
120 handleObj.type = type;
121 if ( !handleObj.guid ) {
122 handleObj.guid = handler.guid;
125 // Get the current list of functions bound to this event
126 var handlers = events[ type ],
127 special = jQuery.event.special[ type ] || {};
129 // Init the event handler queue
131 handlers = events[ type ] = [];
133 // Check for a special event handler
134 // Only use addEventListener/attachEvent if the special
135 // events handler returns false
136 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
137 // Bind the global event handler to the element
138 if ( elem.addEventListener ) {
139 elem.addEventListener( type, eventHandle, false );
141 } else if ( elem.attachEvent ) {
142 elem.attachEvent( "on" + type, eventHandle );
148 special.add.call( elem, handleObj );
150 if ( !handleObj.handler.guid ) {
151 handleObj.handler.guid = handler.guid;
155 // Add the function to the element's handler list
156 handlers.push( handleObj );
158 // Keep track of which events have been used, for global triggering
159 jQuery.event.global[ type ] = true;
162 // Nullify elem to prevent memory leaks in IE
168 // Detach an event or set of events from an element
169 remove: function( elem, types, handler, pos ) {
170 // don't do events on text and comment nodes
171 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
175 if ( handler === false ) {
176 handler = returnFalse;
179 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
180 eventKey = elem.nodeType ? "events" : "__events__",
181 elemData = jQuery.data( elem ),
182 events = elemData && elemData[ eventKey ];
184 if ( !elemData || !events ) {
188 if ( typeof events === "function" ) {
190 events = events.events;
193 // types is actually an event object here
194 if ( types && types.type ) {
195 handler = types.handler;
199 // Unbind all events for the element
200 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
203 for ( type in events ) {
204 jQuery.event.remove( elem, type + types );
210 // Handle multiple events separated by a space
211 // jQuery(...).unbind("mouseover mouseout", fn);
212 types = types.split(" ");
214 while ( (type = types[ i++ ]) ) {
217 all = type.indexOf(".") < 0;
221 // Namespaced event handlers
222 namespaces = type.split(".");
223 type = namespaces.shift();
225 namespace = new RegExp("(^|\\.)" +
226 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
229 eventType = events[ type ];
236 for ( j = 0; j < eventType.length; j++ ) {
237 handleObj = eventType[ j ];
239 if ( all || namespace.test( handleObj.namespace ) ) {
240 jQuery.event.remove( elem, origType, handleObj.handler, j );
241 eventType.splice( j--, 1 );
248 special = jQuery.event.special[ type ] || {};
250 for ( j = pos || 0; j < eventType.length; j++ ) {
251 handleObj = eventType[ j ];
253 if ( handler.guid === handleObj.guid ) {
254 // remove the given handler for the given type
255 if ( all || namespace.test( handleObj.namespace ) ) {
257 eventType.splice( j--, 1 );
260 if ( special.remove ) {
261 special.remove.call( elem, handleObj );
271 // remove generic event handler if no more handlers exist
272 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
273 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
274 jQuery.removeEvent( elem, type, elemData.handle );
278 delete events[ type ];
282 // Remove the expando if it's no longer used
283 if ( jQuery.isEmptyObject( events ) ) {
284 var handle = elemData.handle;
289 delete elemData.events;
290 delete elemData.handle;
292 if ( typeof elemData === "function" ) {
293 jQuery.removeData( elem, eventKey );
295 } else if ( jQuery.isEmptyObject( elemData ) ) {
296 jQuery.removeData( elem );
301 // bubbling is internal
302 trigger: function( event, data, elem /*, bubbling */ ) {
303 // Event object or event type
304 var type = event.type || event,
305 bubbling = arguments[3];
308 event = typeof event === "object" ?
309 // jQuery.Event object
310 event[ jQuery.expando ] ? event :
312 jQuery.extend( jQuery.Event(type), event ) :
313 // Just the event type (string)
316 if ( type.indexOf("!") >= 0 ) {
317 event.type = type = type.slice(0, -1);
318 event.exclusive = true;
321 // Handle a global trigger
323 // Don't bubble custom events when global (to avoid too much overhead)
324 event.stopPropagation();
326 // Only trigger if we've ever bound an event for it
327 if ( jQuery.event.global[ type ] ) {
328 jQuery.each( jQuery.cache, function() {
329 if ( this.events && this.events[type] ) {
330 jQuery.event.trigger( event, data, this.handle.elem );
336 // Handle triggering a single element
338 // don't do events on text and comment nodes
339 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
343 // Clean up in case it is reused
344 event.result = undefined;
347 // Clone the incoming data, if any
348 data = jQuery.makeArray( data );
349 data.unshift( event );
352 event.currentTarget = elem;
354 // Trigger the event, it is assumed that "handle" is a function
355 var handle = elem.nodeType ?
356 jQuery.data( elem, "handle" ) :
357 (jQuery.data( elem, "__events__" ) || {}).handle;
360 handle.apply( elem, data );
363 var parent = elem.parentNode || elem.ownerDocument;
365 // Trigger an inline bound script
367 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
368 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
369 event.result = false;
370 event.preventDefault();
374 // prevent IE from throwing an error for some elements with some event types, see #3533
375 } catch (inlineError) {}
377 if ( !event.isPropagationStopped() && parent ) {
378 jQuery.event.trigger( event, data, parent, true );
380 } else if ( !event.isDefaultPrevented() ) {
382 target = event.target,
383 targetType = type.replace( rnamespaces, "" ),
384 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
385 special = jQuery.event.special[ targetType ] || {};
387 if ( (!special._default || special._default.call( elem, event ) === false) &&
388 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
391 if ( target[ targetType ] ) {
392 // Make sure that we don't accidentally re-trigger the onFOO events
393 old = target[ "on" + targetType ];
396 target[ "on" + targetType ] = null;
399 jQuery.event.triggered = true;
400 target[ targetType ]();
403 // prevent IE from throwing an error for some elements with some event types, see #3533
404 } catch (triggerError) {}
407 target[ "on" + targetType ] = old;
410 jQuery.event.triggered = false;
415 handle: function( event ) {
416 var all, handlers, namespaces, namespace_re, events,
418 args = jQuery.makeArray( arguments );
420 event = args[0] = jQuery.event.fix( event || window.event );
421 event.currentTarget = this;
423 // Namespaced event handlers
424 all = event.type.indexOf(".") < 0 && !event.exclusive;
427 namespaces = event.type.split(".");
428 event.type = namespaces.shift();
429 namespace_sort = namespaces.slice(0).sort();
430 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
433 event.namespace = event.namespace || namespace_sort.join(".");
435 events = jQuery.data(this, this.nodeType ? "events" : "__events__");
437 if ( typeof events === "function" ) {
438 events = events.events;
441 handlers = (events || {})[ event.type ];
443 if ( events && handlers ) {
444 // Clone the handlers to prevent manipulation
445 handlers = handlers.slice(0);
447 for ( var j = 0, l = handlers.length; j < l; j++ ) {
448 var handleObj = handlers[ j ];
450 // Filter the functions by class
451 if ( all || namespace_re.test( handleObj.namespace ) ) {
452 // Pass in a reference to the handler function itself
453 // So that we can later remove it
454 event.handler = handleObj.handler;
455 event.data = handleObj.data;
456 event.handleObj = handleObj;
458 var ret = handleObj.handler.apply( this, args );
460 if ( ret !== undefined ) {
462 if ( ret === false ) {
463 event.preventDefault();
464 event.stopPropagation();
468 if ( event.isImmediatePropagationStopped() ) {
478 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(" "),
480 fix: function( event ) {
481 if ( event[ jQuery.expando ] ) {
485 // store a copy of the original event object
486 // and "clone" to set read-only properties
487 var originalEvent = event;
488 event = jQuery.Event( originalEvent );
490 for ( var i = this.props.length, prop; i; ) {
491 prop = this.props[ --i ];
492 event[ prop ] = originalEvent[ prop ];
495 // Fix target property, if necessary
496 if ( !event.target ) {
497 // Fixes #1925 where srcElement might not be defined either
498 event.target = event.srcElement || document;
501 // check if target is a textnode (safari)
502 if ( event.target.nodeType === 3 ) {
503 event.target = event.target.parentNode;
506 // Add relatedTarget, if necessary
507 if ( !event.relatedTarget && event.fromElement ) {
508 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
511 // Calculate pageX/Y if missing and clientX/Y available
512 if ( event.pageX == null && event.clientX != null ) {
513 var doc = document.documentElement,
514 body = document.body;
516 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
517 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
520 // Add which for key events
521 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
522 event.which = event.charCode != null ? event.charCode : event.keyCode;
525 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
526 if ( !event.metaKey && event.ctrlKey ) {
527 event.metaKey = event.ctrlKey;
530 // Add which for click: 1 === left; 2 === middle; 3 === right
531 // Note: button is not normalized, so don't use it
532 if ( !event.which && event.button !== undefined ) {
533 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
539 // Deprecated, use jQuery.guid instead
542 // Deprecated, use jQuery.proxy instead
547 // Make sure the ready event is setup
548 setup: jQuery.bindReady,
549 teardown: jQuery.noop
553 add: function( handleObj ) {
554 jQuery.event.add( this,
555 liveConvert( handleObj.origType, handleObj.selector ),
556 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
559 remove: function( handleObj ) {
560 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
565 setup: function( data, namespaces, eventHandle ) {
566 // We only want to do this special case on windows
567 if ( jQuery.isWindow( this ) ) {
568 this.onbeforeunload = eventHandle;
572 teardown: function( namespaces, eventHandle ) {
573 if ( this.onbeforeunload === eventHandle ) {
574 this.onbeforeunload = null;
581 jQuery.removeEvent = document.removeEventListener ?
582 function( elem, type, handle ) {
583 if ( elem.removeEventListener ) {
584 elem.removeEventListener( type, handle, false );
587 function( elem, type, handle ) {
588 if ( elem.detachEvent ) {
589 elem.detachEvent( "on" + type, handle );
593 jQuery.Event = function( src ) {
594 // Allow instantiation without the 'new' keyword
595 if ( !this.preventDefault ) {
596 return new jQuery.Event( src );
600 if ( src && src.type ) {
601 this.originalEvent = src;
602 this.type = src.type;
604 // Events bubbling up the document may have been marked as prevented
605 // by a handler lower down the tree; reflect the correct value.
606 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
607 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
614 // timeStamp is buggy for some events on Firefox(#3843)
615 // So we won't rely on the native value
616 this.timeStamp = jQuery.now();
619 this[ jQuery.expando ] = true;
622 function returnFalse() {
625 function returnTrue() {
629 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
630 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
631 jQuery.Event.prototype = {
632 preventDefault: function() {
633 this.isDefaultPrevented = returnTrue;
635 var e = this.originalEvent;
640 // if preventDefault exists run it on the original event
641 if ( e.preventDefault ) {
644 // otherwise set the returnValue property of the original event to false (IE)
646 e.returnValue = false;
649 stopPropagation: function() {
650 this.isPropagationStopped = returnTrue;
652 var e = this.originalEvent;
656 // if stopPropagation exists run it on the original event
657 if ( e.stopPropagation ) {
660 // otherwise set the cancelBubble property of the original event to true (IE)
661 e.cancelBubble = true;
663 stopImmediatePropagation: function() {
664 this.isImmediatePropagationStopped = returnTrue;
665 this.stopPropagation();
667 isDefaultPrevented: returnFalse,
668 isPropagationStopped: returnFalse,
669 isImmediatePropagationStopped: returnFalse
672 // Checks if an event happened on an element within another element
673 // Used in jQuery.event.special.mouseenter and mouseleave handlers
674 var withinElement = function( event ) {
675 // Check if mouse(over|out) are still within the same parent element
676 var parent = event.relatedTarget;
678 // Firefox sometimes assigns relatedTarget a XUL element
679 // which we cannot access the parentNode property of
681 // Traverse up the tree
682 while ( parent && parent !== this ) {
683 parent = parent.parentNode;
686 if ( parent !== this ) {
687 // set the correct event type
688 event.type = event.data;
690 // handle event if we actually just moused on to a non sub-element
691 jQuery.event.handle.apply( this, arguments );
694 // assuming we've left the element since we most likely mousedover a xul element
698 // In case of event delegation, we only need to rename the event.type,
699 // liveHandler will take care of the rest.
700 delegate = function( event ) {
701 event.type = event.data;
702 jQuery.event.handle.apply( this, arguments );
705 // Create mouseenter and mouseleave events
707 mouseenter: "mouseover",
708 mouseleave: "mouseout"
709 }, function( orig, fix ) {
710 jQuery.event.special[ orig ] = {
711 setup: function( data ) {
712 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
714 teardown: function( data ) {
715 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
721 if ( !jQuery.support.submitBubbles ) {
723 jQuery.event.special.submit = {
724 setup: function( data, namespaces ) {
725 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
726 jQuery.event.add(this, "click.specialSubmit", function( e ) {
730 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
731 e.liveFired = undefined;
732 return trigger( "submit", this, arguments );
736 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
740 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
741 e.liveFired = undefined;
742 return trigger( "submit", this, arguments );
751 teardown: function( namespaces ) {
752 jQuery.event.remove( this, ".specialSubmit" );
758 // change delegation, happens here so we have bind.
759 if ( !jQuery.support.changeBubbles ) {
763 getVal = function( elem ) {
764 var type = elem.type, val = elem.value;
766 if ( type === "radio" || type === "checkbox" ) {
769 } else if ( type === "select-multiple" ) {
770 val = elem.selectedIndex > -1 ?
771 jQuery.map( elem.options, function( elem ) {
772 return elem.selected;
776 } else if ( elem.nodeName.toLowerCase() === "select" ) {
777 val = elem.selectedIndex;
783 testChange = function testChange( e ) {
784 var elem = e.target, data, val;
786 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
790 data = jQuery.data( elem, "_change_data" );
793 // the current data will be also retrieved by beforeactivate
794 if ( e.type !== "focusout" || elem.type !== "radio" ) {
795 jQuery.data( elem, "_change_data", val );
798 if ( data === undefined || val === data ) {
802 if ( data != null || val ) {
804 e.liveFired = undefined;
805 return jQuery.event.trigger( e, arguments[1], elem );
809 jQuery.event.special.change = {
811 focusout: testChange,
813 beforedeactivate: testChange,
815 click: function( e ) {
816 var elem = e.target, type = elem.type;
818 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
819 return testChange.call( this, e );
823 // Change has to be called before submit
824 // Keydown will be called before keypress, which is used in submit-event delegation
825 keydown: function( e ) {
826 var elem = e.target, type = elem.type;
828 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
829 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
830 type === "select-multiple" ) {
831 return testChange.call( this, e );
835 // Beforeactivate happens also before the previous element is blurred
836 // with this event you can't trigger a change event, but you can store
838 beforeactivate: function( e ) {
840 jQuery.data( elem, "_change_data", getVal(elem) );
844 setup: function( data, namespaces ) {
845 if ( this.type === "file" ) {
849 for ( var type in changeFilters ) {
850 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
853 return rformElems.test( this.nodeName );
856 teardown: function( namespaces ) {
857 jQuery.event.remove( this, ".specialChange" );
859 return rformElems.test( this.nodeName );
863 changeFilters = jQuery.event.special.change.filters;
865 // Handle when the input is .focus()'d
866 changeFilters.focus = changeFilters.beforeactivate;
869 function trigger( type, elem, args ) {
871 return jQuery.event.handle.apply( elem, args );
874 // Create "bubbling" focus and blur events
875 if ( document.addEventListener ) {
876 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
877 jQuery.event.special[ fix ] = {
879 if ( focusCounts[fix]++ === 0 ) {
880 document.addEventListener( orig, handler, true );
883 teardown: function() {
884 if ( --focusCounts[fix] === 0 ) {
885 document.removeEventListener( orig, handler, true );
890 function handler( e ) {
891 e = jQuery.event.fix( e );
893 return jQuery.event.trigger( e, null, e.target );
898 jQuery.each(["bind", "one"], function( i, name ) {
899 jQuery.fn[ name ] = function( type, data, fn ) {
900 // Handle object literals
901 if ( typeof type === "object" ) {
902 for ( var key in type ) {
903 this[ name ](key, data, type[key], fn);
908 if ( jQuery.isFunction( data ) || data === false ) {
913 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
914 jQuery( this ).unbind( event, handler );
915 return fn.apply( this, arguments );
918 if ( type === "unload" && name !== "one" ) {
919 this.one( type, data, fn );
922 for ( var i = 0, l = this.length; i < l; i++ ) {
923 jQuery.event.add( this[i], type, handler, data );
932 unbind: function( type, fn ) {
933 // Handle object literals
934 if ( typeof type === "object" && !type.preventDefault ) {
935 for ( var key in type ) {
936 this.unbind(key, type[key]);
940 for ( var i = 0, l = this.length; i < l; i++ ) {
941 jQuery.event.remove( this[i], type, fn );
948 delegate: function( selector, types, data, fn ) {
949 return this.live( types, data, fn, selector );
952 undelegate: function( selector, types, fn ) {
953 if ( arguments.length === 0 ) {
954 return this.unbind( "live" );
957 return this.die( types, null, fn, selector );
961 trigger: function( type, data ) {
962 return this.each(function() {
963 jQuery.event.trigger( type, data, this );
967 triggerHandler: function( type, data ) {
969 var event = jQuery.Event( type );
970 event.preventDefault();
971 event.stopPropagation();
972 jQuery.event.trigger( event, data, this[0] );
977 toggle: function( fn ) {
978 // Save reference to arguments for access in closure
979 var args = arguments,
982 // link all the functions, so any of them can unbind this click handler
983 while ( i < args.length ) {
984 jQuery.proxy( fn, args[ i++ ] );
987 return this.click( jQuery.proxy( fn, function( event ) {
988 // Figure out which function to execute
989 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
990 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
992 // Make sure that clicks stop
993 event.preventDefault();
995 // and execute the function
996 return args[ lastToggle ].apply( this, arguments ) || false;
1000 hover: function( fnOver, fnOut ) {
1001 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
1008 mouseenter: "mouseover",
1009 mouseleave: "mouseout"
1012 jQuery.each(["live", "die"], function( i, name ) {
1013 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
1014 var type, i = 0, match, namespaces, preType,
1015 selector = origSelector || this.selector,
1016 context = origSelector ? this : jQuery( this.context );
1018 if ( typeof types === "object" && !types.preventDefault ) {
1019 for ( var key in types ) {
1020 context[ name ]( key, data, types[key], selector );
1026 if ( jQuery.isFunction( data ) ) {
1031 types = (types || "").split(" ");
1033 while ( (type = types[ i++ ]) != null ) {
1034 match = rnamespaces.exec( type );
1038 namespaces = match[0];
1039 type = type.replace( rnamespaces, "" );
1042 if ( type === "hover" ) {
1043 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1049 if ( type === "focus" || type === "blur" ) {
1050 types.push( liveMap[ type ] + namespaces );
1051 type = type + namespaces;
1054 type = (liveMap[ type ] || type) + namespaces;
1057 if ( name === "live" ) {
1058 // bind live handler
1059 for ( var j = 0, l = context.length; j < l; j++ ) {
1060 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1061 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1065 // unbind live handler
1066 context.unbind( "live." + liveConvert( type, selector ), fn );
1074 function liveHandler( event ) {
1075 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1078 events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
1080 if ( typeof events === "function" ) {
1081 events = events.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 )) ) {
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;