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 // For whatever reason, IE has trouble passing the window object
27 // around, causing it to be cloned in the process
28 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
32 if ( handler === false ) {
33 handler = returnFalse;
36 var handleObjIn, handleObj;
38 if ( handler.handler ) {
39 handleObjIn = handler;
40 handler = handleObjIn.handler;
43 // Make sure that the function being executed has a unique ID
44 if ( !handler.guid ) {
45 handler.guid = jQuery.guid++;
48 // Init the element's event structure
49 var elemData = jQuery.data( elem );
51 // If no elemData is found then we must be trying to bind to one of the
52 // banned noData elements
57 var events = elemData.events = elemData.events || {},
58 eventHandle = elemData.handle;
61 elemData.handle = eventHandle = function() {
62 // Handle the second event of a trigger and when
63 // an event is called after a page has unloaded
64 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
65 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
70 // Add elem as a property of the handle function
71 // This is to prevent a memory leak with non-native events in IE.
72 eventHandle.elem = elem;
74 // Handle multiple events separated by a space
75 // jQuery(...).bind("mouseover mouseout", fn);
76 types = types.split(" ");
78 var type, i = 0, namespaces;
80 while ( (type = types[ i++ ]) ) {
81 handleObj = handleObjIn ?
82 jQuery.extend({}, handleObjIn) :
83 { handler: handler, data: data };
85 // Namespaced event handlers
86 if ( type.indexOf(".") > -1 ) {
87 namespaces = type.split(".");
88 type = namespaces.shift();
89 handleObj.namespace = namespaces.slice(0).sort().join(".");
93 handleObj.namespace = "";
96 handleObj.type = type;
97 if ( !handleObj.guid ) {
98 handleObj.guid = handler.guid;
101 // Get the current list of functions bound to this event
102 var handlers = events[ type ],
103 special = jQuery.event.special[ type ] || {};
105 // Init the event handler queue
107 handlers = events[ type ] = [];
109 // Check for a special event handler
110 // Only use addEventListener/attachEvent if the special
111 // events handler returns false
112 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
113 // Bind the global event handler to the element
114 if ( elem.addEventListener ) {
115 elem.addEventListener( type, eventHandle, false );
117 } else if ( elem.attachEvent ) {
118 elem.attachEvent( "on" + type, eventHandle );
124 special.add.call( elem, handleObj );
126 if ( !handleObj.handler.guid ) {
127 handleObj.handler.guid = handler.guid;
131 // Add the function to the element's handler list
132 handlers.push( handleObj );
134 // Keep track of which events have been used, for global triggering
135 jQuery.event.global[ type ] = true;
138 // Nullify elem to prevent memory leaks in IE
144 // Detach an event or set of events from an element
145 remove: function( elem, types, handler, pos ) {
146 // don't do events on text and comment nodes
147 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
151 if ( handler === false ) {
152 handler = returnFalse;
155 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
156 elemData = jQuery.data( elem ),
157 events = elemData && elemData.events;
159 if ( !elemData || !events ) {
163 // types is actually an event object here
164 if ( types && types.type ) {
165 handler = types.handler;
169 // Unbind all events for the element
170 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
173 for ( type in events ) {
174 jQuery.event.remove( elem, type + types );
180 // Handle multiple events separated by a space
181 // jQuery(...).unbind("mouseover mouseout", fn);
182 types = types.split(" ");
184 while ( (type = types[ i++ ]) ) {
187 all = type.indexOf(".") < 0;
191 // Namespaced event handlers
192 namespaces = type.split(".");
193 type = namespaces.shift();
195 namespace = new RegExp("(^|\\.)" +
196 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
199 eventType = events[ type ];
206 for ( j = 0; j < eventType.length; j++ ) {
207 handleObj = eventType[ j ];
209 if ( all || namespace.test( handleObj.namespace ) ) {
210 jQuery.event.remove( elem, origType, handleObj.handler, j );
211 eventType.splice( j--, 1 );
218 special = jQuery.event.special[ type ] || {};
220 for ( j = pos || 0; j < eventType.length; j++ ) {
221 handleObj = eventType[ j ];
223 if ( handler.guid === handleObj.guid ) {
224 // remove the given handler for the given type
225 if ( all || namespace.test( handleObj.namespace ) ) {
227 eventType.splice( j--, 1 );
230 if ( special.remove ) {
231 special.remove.call( elem, handleObj );
241 // remove generic event handler if no more handlers exist
242 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
243 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
244 jQuery.removeEvent( elem, type, elemData.handle );
248 delete events[ type ];
252 // Remove the expando if it's no longer used
253 if ( jQuery.isEmptyObject( events ) ) {
254 var handle = elemData.handle;
259 delete elemData.events;
260 delete elemData.handle;
262 if ( jQuery.isEmptyObject( elemData ) ) {
263 jQuery.removeData( elem );
268 // bubbling is internal
269 trigger: function( event, data, elem /*, bubbling */ ) {
270 // Event object or event type
271 var type = event.type || event,
272 bubbling = arguments[3];
275 event = typeof event === "object" ?
276 // jQuery.Event object
277 event[ jQuery.expando ] ? event :
279 jQuery.extend( jQuery.Event(type), event ) :
280 // Just the event type (string)
283 if ( type.indexOf("!") >= 0 ) {
284 event.type = type = type.slice(0, -1);
285 event.exclusive = true;
288 // Handle a global trigger
290 // Don't bubble custom events when global (to avoid too much overhead)
291 event.stopPropagation();
293 // Only trigger if we've ever bound an event for it
294 if ( jQuery.event.global[ type ] ) {
295 jQuery.each( jQuery.cache, function() {
296 if ( this.events && this.events[type] ) {
297 jQuery.event.trigger( event, data, this.handle.elem );
303 // Handle triggering a single element
305 // don't do events on text and comment nodes
306 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
310 // Clean up in case it is reused
311 event.result = undefined;
314 // Clone the incoming data, if any
315 data = jQuery.makeArray( data );
316 data.unshift( event );
319 event.currentTarget = elem;
321 // Trigger the event, it is assumed that "handle" is a function
322 var handle = jQuery.data( elem, "handle" );
324 handle.apply( elem, data );
327 var parent = elem.parentNode || elem.ownerDocument;
329 // Trigger an inline bound script
331 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
332 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
333 event.result = false;
337 // prevent IE from throwing an error for some elements with some event types, see #3533
338 } catch (inlineError) {}
340 if ( !event.isPropagationStopped() && parent ) {
341 jQuery.event.trigger( event, data, parent, true );
343 } else if ( !event.isDefaultPrevented() ) {
344 var target = event.target, old, targetType = type.replace(rnamespaces, ""),
345 isClick = jQuery.nodeName(target, "a") && targetType === "click",
346 special = jQuery.event.special[ targetType ] || {};
348 if ( (!special._default || special._default.call( elem, event ) === false) &&
349 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
352 if ( target[ targetType ] ) {
353 // Make sure that we don't accidentally re-trigger the onFOO events
354 old = target[ "on" + targetType ];
357 target[ "on" + targetType ] = null;
360 jQuery.event.triggered = true;
361 target[ targetType ]();
364 // prevent IE from throwing an error for some elements with some event types, see #3533
365 } catch (triggerError) {}
368 target[ "on" + targetType ] = old;
371 jQuery.event.triggered = false;
376 handle: function( event ) {
377 var all, handlers, namespaces, namespace_sort = [], namespace_re, events, args = jQuery.makeArray( arguments );
379 event = args[0] = jQuery.event.fix( event || window.event );
380 event.currentTarget = this;
382 // Namespaced event handlers
383 all = event.type.indexOf(".") < 0 && !event.exclusive;
386 namespaces = event.type.split(".");
387 event.type = namespaces.shift();
388 namespace_sort = namespaces.slice(0).sort();
389 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
392 event.namespace = event.namespace || namespace_sort.join(".");
394 events = jQuery.data(this, "events");
395 handlers = (events || {})[ event.type ];
397 if ( events && handlers ) {
398 // Clone the handlers to prevent manipulation
399 handlers = handlers.slice(0);
401 for ( var j = 0, l = handlers.length; j < l; j++ ) {
402 var handleObj = handlers[ j ];
404 // Filter the functions by class
405 if ( all || namespace_re.test( handleObj.namespace ) ) {
406 // Pass in a reference to the handler function itself
407 // So that we can later remove it
408 event.handler = handleObj.handler;
409 event.data = handleObj.data;
410 event.handleObj = handleObj;
412 var ret = handleObj.handler.apply( this, args );
414 if ( ret !== undefined ) {
416 if ( ret === false ) {
417 event.preventDefault();
418 event.stopPropagation();
422 if ( event.isImmediatePropagationStopped() ) {
432 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
434 fix: function( event ) {
435 if ( event[ jQuery.expando ] ) {
439 // store a copy of the original event object
440 // and "clone" to set read-only properties
441 var originalEvent = event;
442 event = jQuery.Event( originalEvent );
444 for ( var i = this.props.length, prop; i; ) {
445 prop = this.props[ --i ];
446 event[ prop ] = originalEvent[ prop ];
449 // Fix target property, if necessary
450 if ( !event.target ) {
451 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
454 // check if target is a textnode (safari)
455 if ( event.target.nodeType === 3 ) {
456 event.target = event.target.parentNode;
459 // Add relatedTarget, if necessary
460 if ( !event.relatedTarget && event.fromElement ) {
461 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
464 // Calculate pageX/Y if missing and clientX/Y available
465 if ( event.pageX == null && event.clientX != null ) {
466 var doc = document.documentElement, body = document.body;
467 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
468 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
471 // Add which for key events
472 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
473 event.which = event.charCode || event.keyCode;
476 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
477 if ( !event.metaKey && event.ctrlKey ) {
478 event.metaKey = event.ctrlKey;
481 // Add which for click: 1 === left; 2 === middle; 3 === right
482 // Note: button is not normalized, so don't use it
483 if ( !event.which && event.button !== undefined ) {
484 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
490 // Deprecated, use jQuery.guid instead
493 // Deprecated, use jQuery.proxy instead
498 // Make sure the ready event is setup
499 setup: jQuery.bindReady,
500 teardown: jQuery.noop
504 add: function( handleObj ) {
505 jQuery.event.add( this,
506 liveConvert( handleObj.origType, handleObj.selector ),
507 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
510 remove: function( handleObj ) {
511 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
516 setup: function( data, namespaces, eventHandle ) {
517 // We only want to do this special case on windows
518 if ( jQuery.isWindow( this ) ) {
519 this.onbeforeunload = eventHandle;
523 teardown: function( namespaces, eventHandle ) {
524 if ( this.onbeforeunload === eventHandle ) {
525 this.onbeforeunload = null;
532 jQuery.removeEvent = document.removeEventListener ?
533 function( elem, type, handle ) {
534 if ( elem.removeEventListener ) {
535 elem.removeEventListener( type, handle, false );
538 function( elem, type, handle ) {
539 if ( elem.detachEvent ) {
540 elem.detachEvent( "on" + type, handle );
544 jQuery.Event = function( src ) {
545 // Allow instantiation without the 'new' keyword
546 if ( !this.preventDefault ) {
547 return new jQuery.Event( src );
551 if ( src && src.type ) {
552 this.originalEvent = src;
553 this.type = src.type;
559 // timeStamp is buggy for some events on Firefox(#3843)
560 // So we won't rely on the native value
561 this.timeStamp = jQuery.now();
564 this[ jQuery.expando ] = true;
567 function returnFalse() {
570 function returnTrue() {
574 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
575 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
576 jQuery.Event.prototype = {
577 preventDefault: function() {
578 this.isDefaultPrevented = returnTrue;
580 var e = this.originalEvent;
585 // if preventDefault exists run it on the original event
586 if ( e.preventDefault ) {
589 // otherwise set the returnValue property of the original event to false (IE)
591 e.returnValue = false;
594 stopPropagation: function() {
595 this.isPropagationStopped = returnTrue;
597 var e = this.originalEvent;
601 // if stopPropagation exists run it on the original event
602 if ( e.stopPropagation ) {
605 // otherwise set the cancelBubble property of the original event to true (IE)
606 e.cancelBubble = true;
608 stopImmediatePropagation: function() {
609 this.isImmediatePropagationStopped = returnTrue;
610 this.stopPropagation();
612 isDefaultPrevented: returnFalse,
613 isPropagationStopped: returnFalse,
614 isImmediatePropagationStopped: returnFalse
617 // Checks if an event happened on an element within another element
618 // Used in jQuery.event.special.mouseenter and mouseleave handlers
619 var withinElement = function( event ) {
620 // Check if mouse(over|out) are still within the same parent element
621 var parent = event.relatedTarget;
623 // Firefox sometimes assigns relatedTarget a XUL element
624 // which we cannot access the parentNode property of
626 // Traverse up the tree
627 while ( parent && parent !== this ) {
628 parent = parent.parentNode;
631 if ( parent !== this ) {
632 // set the correct event type
633 event.type = event.data;
635 // handle event if we actually just moused on to a non sub-element
636 jQuery.event.handle.apply( this, arguments );
639 // assuming we've left the element since we most likely mousedover a xul element
643 // In case of event delegation, we only need to rename the event.type,
644 // liveHandler will take care of the rest.
645 delegate = function( event ) {
646 event.type = event.data;
647 jQuery.event.handle.apply( this, arguments );
650 // Create mouseenter and mouseleave events
652 mouseenter: "mouseover",
653 mouseleave: "mouseout"
654 }, function( orig, fix ) {
655 jQuery.event.special[ orig ] = {
656 setup: function( data ) {
657 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
659 teardown: function( data ) {
660 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
666 if ( !jQuery.support.submitBubbles ) {
668 jQuery.event.special.submit = {
669 setup: function( data, namespaces ) {
670 if ( this.nodeName.toLowerCase() !== "form" ) {
671 jQuery.event.add(this, "click.specialSubmit", function( e ) {
672 var elem = e.target, type = elem.type;
674 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
675 return trigger( "submit", this, arguments );
679 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
680 var elem = e.target, type = elem.type;
682 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
683 return trigger( "submit", this, arguments );
692 teardown: function( namespaces ) {
693 jQuery.event.remove( this, ".specialSubmit" );
699 // change delegation, happens here so we have bind.
700 if ( !jQuery.support.changeBubbles ) {
704 getVal = function( elem ) {
705 var type = elem.type, val = elem.value;
707 if ( type === "radio" || type === "checkbox" ) {
710 } else if ( type === "select-multiple" ) {
711 val = elem.selectedIndex > -1 ?
712 jQuery.map( elem.options, function( elem ) {
713 return elem.selected;
717 } else if ( elem.nodeName.toLowerCase() === "select" ) {
718 val = elem.selectedIndex;
724 testChange = function testChange( e ) {
725 var elem = e.target, data, val;
727 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
731 data = jQuery.data( elem, "_change_data" );
734 // the current data will be also retrieved by beforeactivate
735 if ( e.type !== "focusout" || elem.type !== "radio" ) {
736 jQuery.data( elem, "_change_data", val );
739 if ( data === undefined || val === data ) {
743 if ( data != null || val ) {
745 return jQuery.event.trigger( e, arguments[1], elem );
749 jQuery.event.special.change = {
751 focusout: testChange,
753 click: function( e ) {
754 var elem = e.target, type = elem.type;
756 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
757 return testChange.call( this, e );
761 // Change has to be called before submit
762 // Keydown will be called before keypress, which is used in submit-event delegation
763 keydown: function( e ) {
764 var elem = e.target, type = elem.type;
766 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
767 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
768 type === "select-multiple" ) {
769 return testChange.call( this, e );
773 // Beforeactivate happens also before the previous element is blurred
774 // with this event you can't trigger a change event, but you can store
775 // information/focus[in] is not needed anymore
776 beforeactivate: function( e ) {
778 jQuery.data( elem, "_change_data", getVal(elem) );
782 setup: function( data, namespaces ) {
783 if ( this.type === "file" ) {
787 for ( var type in changeFilters ) {
788 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
791 return rformElems.test( this.nodeName );
794 teardown: function( namespaces ) {
795 jQuery.event.remove( this, ".specialChange" );
797 return rformElems.test( this.nodeName );
801 changeFilters = jQuery.event.special.change.filters;
804 function trigger( type, elem, args ) {
806 return jQuery.event.handle.apply( elem, args );
809 // Create "bubbling" focus and blur events
810 if ( document.addEventListener ) {
811 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
812 jQuery.event.special[ fix ] = {
814 this.addEventListener( orig, handler, true );
816 teardown: function() {
817 this.removeEventListener( orig, handler, true );
821 function handler( e ) {
822 e = jQuery.event.fix( e );
824 return jQuery.event.handle.call( this, e );
829 jQuery.each(["bind", "one"], function( i, name ) {
830 jQuery.fn[ name ] = function( type, data, fn ) {
831 // Handle object literals
832 if ( typeof type === "object" ) {
833 for ( var key in type ) {
834 this[ name ](key, data, type[key], fn);
839 if ( jQuery.isFunction( data ) || data === false ) {
844 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
845 jQuery( this ).unbind( event, handler );
846 return fn.apply( this, arguments );
849 if ( type === "unload" && name !== "one" ) {
850 this.one( type, data, fn );
853 for ( var i = 0, l = this.length; i < l; i++ ) {
854 jQuery.event.add( this[i], type, handler, data );
863 unbind: function( type, fn ) {
864 // Handle object literals
865 if ( typeof type === "object" && !type.preventDefault ) {
866 for ( var key in type ) {
867 this.unbind(key, type[key]);
871 for ( var i = 0, l = this.length; i < l; i++ ) {
872 jQuery.event.remove( this[i], type, fn );
879 delegate: function( selector, types, data, fn ) {
880 return this.live( types, data, fn, selector );
883 undelegate: function( selector, types, fn ) {
884 if ( arguments.length === 0 ) {
885 return this.unbind( "live" );
888 return this.die( types, null, fn, selector );
892 trigger: function( type, data ) {
893 return this.each(function() {
894 jQuery.event.trigger( type, data, this );
898 triggerHandler: function( type, data ) {
900 var event = jQuery.Event( type );
901 event.preventDefault();
902 event.stopPropagation();
903 jQuery.event.trigger( event, data, this[0] );
908 toggle: function( fn ) {
909 // Save reference to arguments for access in closure
910 var args = arguments, i = 1;
912 // link all the functions, so any of them can unbind this click handler
913 while ( i < args.length ) {
914 jQuery.proxy( fn, args[ i++ ] );
917 return this.click( jQuery.proxy( fn, function( event ) {
918 // Figure out which function to execute
919 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
920 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
922 // Make sure that clicks stop
923 event.preventDefault();
925 // and execute the function
926 return args[ lastToggle ].apply( this, arguments ) || false;
930 hover: function( fnOver, fnOut ) {
931 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
938 mouseenter: "mouseover",
939 mouseleave: "mouseout"
942 jQuery.each(["live", "die"], function( i, name ) {
943 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
944 var type, i = 0, match, namespaces, preType,
945 selector = origSelector || this.selector,
946 context = origSelector ? this : jQuery( this.context );
948 if ( typeof types === "object" && !types.preventDefault ) {
949 for ( var key in types ) {
950 context[ name ]( key, data, types[key], selector );
956 if ( jQuery.isFunction( data ) ) {
961 types = (types || "").split(" ");
963 while ( (type = types[ i++ ]) != null ) {
964 match = rnamespaces.exec( type );
968 namespaces = match[0];
969 type = type.replace( rnamespaces, "" );
972 if ( type === "hover" ) {
973 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
979 if ( type === "focus" || type === "blur" ) {
980 types.push( liveMap[ type ] + namespaces );
981 type = type + namespaces;
984 type = (liveMap[ type ] || type) + namespaces;
987 if ( name === "live" ) {
989 for ( var j = 0, l = context.length; j < l; j++ ) {
990 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
991 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
995 // unbind live handler
996 context.unbind( "live." + liveConvert( type, selector ), fn );
1004 function liveHandler( event ) {
1005 var stop, maxLevel, elems = [], selectors = [],
1006 related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1007 events = jQuery.data( this, "events" );
1009 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
1010 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
1014 if ( event.namespace ) {
1015 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1018 event.liveFired = this;
1020 var live = events.live.slice(0);
1022 for ( j = 0; j < live.length; j++ ) {
1023 handleObj = live[j];
1025 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1026 selectors.push( handleObj.selector );
1029 live.splice( j--, 1 );
1033 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1035 for ( i = 0, l = match.length; i < l; i++ ) {
1038 for ( j = 0; j < live.length; j++ ) {
1039 handleObj = live[j];
1041 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1045 // Those two events require additional checking
1046 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1047 event.type = handleObj.preType;
1048 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1051 if ( !related || related !== elem ) {
1052 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1058 for ( i = 0, l = elems.length; i < l; i++ ) {
1061 if ( maxLevel && match.level > maxLevel ) {
1065 event.currentTarget = match.elem;
1066 event.data = match.handleObj.data;
1067 event.handleObj = match.handleObj;
1069 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1071 if ( ret === false || event.isPropagationStopped() ) {
1072 maxLevel = match.level;
1074 if ( ret === false ) {
1083 function liveConvert( type, selector ) {
1084 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1087 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1088 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1089 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1091 // Handle event binding
1092 jQuery.fn[ name ] = function( data, fn ) {
1098 return arguments.length > 0 ?
1099 this.bind( name, data, fn ) :
1100 this.trigger( name );
1103 if ( jQuery.attrFn ) {
1104 jQuery.attrFn[ name ] = true;
1108 // Prevent memory leaks in IE
1109 // Window isn't included so as not to unbind existing unload events
1111 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
1112 if ( window.attachEvent && !window.addEventListener ) {
1113 window.attachEvent("onunload", function() {
1114 for ( var id in jQuery.cache ) {
1115 if ( jQuery.cache[ id ].handle ) {
1116 // Try/Catch is to handle iframes being unloaded, see #4280
1118 jQuery.event.remove( jQuery.cache[ id ].handle.elem );