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() {
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 ?
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 = true;
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 = false;
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 ) {
871 jQuery.event.special[ fix ] = {
873 this.addEventListener( orig, handler, true );
875 teardown: function() {
876 this.removeEventListener( orig, handler, true );
880 function handler( e ) {
881 e = jQuery.event.fix( e );
883 return jQuery.event.handle.call( this, e );
888 jQuery.each(["bind", "one"], function( i, name ) {
889 jQuery.fn[ name ] = function( type, data, fn ) {
890 // Handle object literals
891 if ( typeof type === "object" ) {
892 for ( var key in type ) {
893 this[ name ](key, data, type[key], fn);
898 if ( jQuery.isFunction( data ) || data === false ) {
903 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
904 jQuery( this ).unbind( event, handler );
905 return fn.apply( this, arguments );
908 if ( type === "unload" && name !== "one" ) {
909 this.one( type, data, fn );
912 for ( var i = 0, l = this.length; i < l; i++ ) {
913 jQuery.event.add( this[i], type, handler, data );
922 unbind: function( type, fn ) {
923 // Handle object literals
924 if ( typeof type === "object" && !type.preventDefault ) {
925 for ( var key in type ) {
926 this.unbind(key, type[key]);
930 for ( var i = 0, l = this.length; i < l; i++ ) {
931 jQuery.event.remove( this[i], type, fn );
938 delegate: function( selector, types, data, fn ) {
939 return this.live( types, data, fn, selector );
942 undelegate: function( selector, types, fn ) {
943 if ( arguments.length === 0 ) {
944 return this.unbind( "live" );
947 return this.die( types, null, fn, selector );
951 trigger: function( type, data ) {
952 return this.each(function() {
953 jQuery.event.trigger( type, data, this );
957 triggerHandler: function( type, data ) {
959 var event = jQuery.Event( type );
960 event.preventDefault();
961 event.stopPropagation();
962 jQuery.event.trigger( event, data, this[0] );
967 toggle: function( fn ) {
968 // Save reference to arguments for access in closure
969 var args = arguments,
972 // link all the functions, so any of them can unbind this click handler
973 while ( i < args.length ) {
974 jQuery.proxy( fn, args[ i++ ] );
977 return this.click( jQuery.proxy( fn, function( event ) {
978 // Figure out which function to execute
979 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
980 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
982 // Make sure that clicks stop
983 event.preventDefault();
985 // and execute the function
986 return args[ lastToggle ].apply( this, arguments ) || false;
990 hover: function( fnOver, fnOut ) {
991 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
998 mouseenter: "mouseover",
999 mouseleave: "mouseout"
1002 jQuery.each(["live", "die"], function( i, name ) {
1003 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
1004 var type, i = 0, match, namespaces, preType,
1005 selector = origSelector || this.selector,
1006 context = origSelector ? this : jQuery( this.context );
1008 if ( typeof types === "object" && !types.preventDefault ) {
1009 for ( var key in types ) {
1010 context[ name ]( key, data, types[key], selector );
1016 if ( jQuery.isFunction( data ) ) {
1021 types = (types || "").split(" ");
1023 while ( (type = types[ i++ ]) != null ) {
1024 match = rnamespaces.exec( type );
1028 namespaces = match[0];
1029 type = type.replace( rnamespaces, "" );
1032 if ( type === "hover" ) {
1033 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1039 if ( type === "focus" || type === "blur" ) {
1040 types.push( liveMap[ type ] + namespaces );
1041 type = type + namespaces;
1044 type = (liveMap[ type ] || type) + namespaces;
1047 if ( name === "live" ) {
1048 // bind live handler
1049 for ( var j = 0, l = context.length; j < l; j++ ) {
1050 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1051 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1055 // unbind live handler
1056 context.unbind( "live." + liveConvert( type, selector ), fn );
1064 function liveHandler( event ) {
1065 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1068 events = jQuery._data( this, "events" );
1070 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1071 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1075 if ( event.namespace ) {
1076 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1079 event.liveFired = this;
1081 var live = events.live.slice(0);
1083 for ( j = 0; j < live.length; j++ ) {
1084 handleObj = live[j];
1086 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1087 selectors.push( handleObj.selector );
1090 live.splice( j--, 1 );
1094 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1096 for ( i = 0, l = match.length; i < l; i++ ) {
1099 for ( j = 0; j < live.length; j++ ) {
1100 handleObj = live[j];
1102 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
1106 // Those two events require additional checking
1107 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1108 event.type = handleObj.preType;
1109 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1112 if ( !related || related !== elem ) {
1113 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1119 for ( i = 0, l = elems.length; i < l; i++ ) {
1122 if ( maxLevel && match.level > maxLevel ) {
1126 event.currentTarget = match.elem;
1127 event.data = match.handleObj.data;
1128 event.handleObj = match.handleObj;
1130 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1132 if ( ret === false || event.isPropagationStopped() ) {
1133 maxLevel = match.level;
1135 if ( ret === false ) {
1138 if ( event.isImmediatePropagationStopped() ) {
1147 function liveConvert( type, selector ) {
1148 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1151 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1152 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1153 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1155 // Handle event binding
1156 jQuery.fn[ name ] = function( data, fn ) {
1162 return arguments.length > 0 ?
1163 this.bind( name, data, fn ) :
1164 this.trigger( name );
1167 if ( jQuery.attrFn ) {
1168 jQuery.attrFn[ name ] = true;