1 var rnamespaces = /\.(.*)$/,
2 fcleanup = function( nm ) {
3 return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
9 * A number of helper functions used for managing events.
10 * Many of the ideas behind this code originated from
11 * Dean Edwards' addEvent library.
15 // Bind an event to an element
16 // Original by Dean Edwards
17 add: function( elem, types, handler, data ) {
18 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
22 // For whatever reason, IE has trouble passing the window object
23 // around, causing it to be cloned in the process
24 if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
28 var handleObjIn, handleObj;
30 if ( handler.handler ) {
31 handleObjIn = handler;
32 handler = handleObjIn.handler;
35 // Make sure that the function being executed has a unique ID
36 if ( !handler.guid ) {
37 handler.guid = jQuery.guid++;
40 // Init the element's event structure
41 var elemData = jQuery.data( elem );
43 // If no elemData is found then we must be trying to bind to one of the
44 // banned noData elements
49 var events = elemData.events = elemData.events || {},
50 eventHandle = elemData.handle, eventHandle;
53 elemData.handle = eventHandle = function() {
54 // Handle the second event of a trigger and when
55 // an event is called after a page has unloaded
56 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
57 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
62 // Add elem as a property of the handle function
63 // This is to prevent a memory leak with non-native events in IE.
64 eventHandle.elem = elem;
66 // Handle multiple events separated by a space
67 // jQuery(...).bind("mouseover mouseout", fn);
68 types = types.split(" ");
70 var type, i = 0, namespaces;
72 while ( (type = types[ i++ ]) ) {
73 handleObj = handleObjIn ?
74 jQuery.extend({}, handleObjIn) :
75 { handler: handler, data: data };
77 // Namespaced event handlers
78 if ( type.indexOf(".") > -1 ) {
79 namespaces = type.split(".");
80 type = namespaces.shift();
81 handleObj.namespace = namespaces.slice(0).sort().join(".");
85 handleObj.namespace = "";
88 handleObj.type = type;
89 handleObj.guid = handler.guid;
91 // Get the current list of functions bound to this event
92 var handlers = events[ type ],
93 special = jQuery.event.special[ type ] || {};
95 // Init the event handler queue
97 handlers = events[ type ] = [];
99 // Check for a special event handler
100 // Only use addEventListener/attachEvent if the special
101 // events handler returns false
102 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
103 // Bind the global event handler to the element
104 if ( elem.addEventListener ) {
105 elem.addEventListener( type, eventHandle, false );
107 } else if ( elem.attachEvent ) {
108 elem.attachEvent( "on" + type, eventHandle );
114 special.add.call( elem, handleObj );
116 if ( !handleObj.handler.guid ) {
117 handleObj.handler.guid = handler.guid;
121 // Add the function to the element's handler list
122 handlers.push( handleObj );
124 // Keep track of which events have been used, for global triggering
125 jQuery.event.global[ type ] = true;
128 // Nullify elem to prevent memory leaks in IE
134 // Detach an event or set of events from an element
135 remove: function( elem, types, handler, pos ) {
136 // don't do events on text and comment nodes
137 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
141 var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
142 elemData = jQuery.data( elem ),
143 events = elemData && elemData.events;
145 if ( !elemData || !events ) {
149 // types is actually an event object here
150 if ( types && types.type ) {
151 handler = types.handler;
155 // Unbind all events for the element
156 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
159 for ( type in events ) {
160 jQuery.event.remove( elem, type + types );
166 // Handle multiple events separated by a space
167 // jQuery(...).unbind("mouseover mouseout", fn);
168 types = types.split(" ");
170 while ( (type = types[ i++ ]) ) {
173 all = type.indexOf(".") < 0;
177 // Namespaced event handlers
178 namespaces = type.split(".");
179 type = namespaces.shift();
181 namespace = new RegExp("(^|\\.)" +
182 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
185 eventType = events[ type ];
192 for ( var j = 0; j < eventType.length; j++ ) {
193 handleObj = eventType[ j ];
195 if ( all || namespace.test( handleObj.namespace ) ) {
196 jQuery.event.remove( elem, origType, handleObj.handler, j );
197 eventType.splice( j--, 1 );
204 special = jQuery.event.special[ type ] || {};
206 for ( var j = pos || 0; j < eventType.length; j++ ) {
207 handleObj = eventType[ j ];
209 if ( handler.guid === handleObj.guid ) {
210 // remove the given handler for the given type
211 if ( all || namespace.test( handleObj.namespace ) ) {
213 eventType.splice( j--, 1 );
216 if ( special.remove ) {
217 special.remove.call( elem, handleObj );
227 // remove generic event handler if no more handlers exist
228 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
229 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
230 removeEvent( elem, type, elemData.handle );
234 delete events[ type ];
238 // Remove the expando if it's no longer used
239 if ( jQuery.isEmptyObject( events ) ) {
240 var handle = elemData.handle;
245 delete elemData.events;
246 delete elemData.handle;
248 if ( jQuery.isEmptyObject( elemData ) ) {
249 jQuery.removeData( elem );
254 // bubbling is internal
255 trigger: function( event, data, elem /*, bubbling */ ) {
256 // Event object or event type
257 var type = event.type || event,
258 bubbling = arguments[3];
261 event = typeof event === "object" ?
262 // jQuery.Event object
263 event[expando] ? event :
265 jQuery.extend( jQuery.Event(type), event ) :
266 // Just the event type (string)
269 if ( type.indexOf("!") >= 0 ) {
270 event.type = type = type.slice(0, -1);
271 event.exclusive = true;
274 // Handle a global trigger
276 // Don't bubble custom events when global (to avoid too much overhead)
277 event.stopPropagation();
279 // Only trigger if we've ever bound an event for it
280 if ( jQuery.event.global[ type ] ) {
281 jQuery.each( jQuery.cache, function() {
282 if ( this.events && this.events[type] ) {
283 jQuery.event.trigger( event, data, this.handle.elem );
289 // Handle triggering a single element
291 // don't do events on text and comment nodes
292 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
296 // Clean up in case it is reused
297 event.result = undefined;
300 // Clone the incoming data, if any
301 data = jQuery.makeArray( data );
302 data.unshift( event );
305 event.currentTarget = elem;
307 // Trigger the event, it is assumed that "handle" is a function
308 var handle = jQuery.data( elem, "handle" );
310 handle.apply( elem, data );
313 var parent = elem.parentNode || elem.ownerDocument;
315 // Trigger an inline bound script
317 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
318 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
319 event.result = false;
323 // prevent IE from throwing an error for some elements with some event types, see #3533
326 if ( !event.isPropagationStopped() && parent ) {
327 jQuery.event.trigger( event, data, parent, true );
329 } else if ( !event.isDefaultPrevented() ) {
330 var target = event.target, old,
331 isClick = jQuery.nodeName(target, "a") && type === "click",
332 special = jQuery.event.special[ type ] || {};
334 if ( (!special._default || special._default.call( elem, event ) === false) &&
335 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
338 if ( target[ type ] ) {
339 // Make sure that we don't accidentally re-trigger the onFOO events
340 old = target[ "on" + type ];
343 target[ "on" + type ] = null;
346 jQuery.event.triggered = true;
350 // prevent IE from throwing an error for some elements with some event types, see #3533
354 target[ "on" + type ] = old;
357 jQuery.event.triggered = false;
362 handle: function( event ) {
363 var all, handlers, namespaces, namespace, events;
365 event = arguments[0] = jQuery.event.fix( event || window.event );
366 event.currentTarget = this;
368 // Namespaced event handlers
369 all = event.type.indexOf(".") < 0 && !event.exclusive;
372 namespaces = event.type.split(".");
373 event.type = namespaces.shift();
374 namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
377 var events = jQuery.data(this, "events"), handlers = events[ event.type ];
379 if ( events && handlers ) {
380 // Clone the handlers to prevent manipulation
381 handlers = handlers.slice(0);
383 for ( var j = 0, l = handlers.length; j < l; j++ ) {
384 var handleObj = handlers[ j ];
386 // Filter the functions by class
387 if ( all || namespace.test( handleObj.namespace ) ) {
388 // Pass in a reference to the handler function itself
389 // So that we can later remove it
390 event.handler = handleObj.handler;
391 event.data = handleObj.data;
392 event.handleObj = handleObj;
394 var ret = handleObj.handler.apply( this, arguments );
396 if ( ret !== undefined ) {
398 if ( ret === false ) {
399 event.preventDefault();
400 event.stopPropagation();
404 if ( event.isImmediatePropagationStopped() ) {
414 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(" "),
416 fix: function( event ) {
417 if ( event[ expando ] ) {
421 // store a copy of the original event object
422 // and "clone" to set read-only properties
423 var originalEvent = event;
424 event = jQuery.Event( originalEvent );
426 for ( var i = this.props.length, prop; i; ) {
427 prop = this.props[ --i ];
428 event[ prop ] = originalEvent[ prop ];
431 // Fix target property, if necessary
432 if ( !event.target ) {
433 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
436 // check if target is a textnode (safari)
437 if ( event.target.nodeType === 3 ) {
438 event.target = event.target.parentNode;
441 // Add relatedTarget, if necessary
442 if ( !event.relatedTarget && event.fromElement ) {
443 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
446 // Calculate pageX/Y if missing and clientX/Y available
447 if ( event.pageX == null && event.clientX != null ) {
448 var doc = document.documentElement, body = document.body;
449 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
450 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
453 // Add which for key events
454 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
455 event.which = event.charCode || event.keyCode;
458 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
459 if ( !event.metaKey && event.ctrlKey ) {
460 event.metaKey = event.ctrlKey;
463 // Add which for click: 1 === left; 2 === middle; 3 === right
464 // Note: button is not normalized, so don't use it
465 if ( !event.which && event.button !== undefined ) {
466 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
472 // Deprecated, use jQuery.guid instead
475 // Deprecated, use jQuery.proxy instead
480 // Make sure the ready event is setup
481 setup: jQuery.bindReady,
482 teardown: jQuery.noop
486 add: function( handleObj ) {
487 jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
490 remove: function( handleObj ) {
492 type = handleObj.origType.replace(rnamespaces, "");
494 jQuery.each( jQuery.data(this, "events").live || [], function() {
495 if ( type === this.origType.replace(rnamespaces, "") ) {
502 jQuery.event.remove( this, handleObj.origType, liveHandler );
509 setup: function( data, namespaces, eventHandle ) {
510 // We only want to do this special case on windows
511 if ( this.setInterval ) {
512 this.onbeforeunload = eventHandle;
517 teardown: function( namespaces, eventHandle ) {
518 if ( this.onbeforeunload === eventHandle ) {
519 this.onbeforeunload = null;
526 var removeEvent = document.removeEventListener ?
527 function( elem, type, handle ) {
528 if ( elem.removeEventListener ) {
529 elem.removeEventListener( type, handle, false );
532 function( elem, type, handle ) {
533 if ( elem.detachEvent ) {
534 elem.detachEvent( "on" + type, handle );
538 jQuery.Event = function( src ) {
539 // Allow instantiation without the 'new' keyword
540 if ( !this.preventDefault ) {
541 return new jQuery.Event( src );
545 if ( src && src.type ) {
546 this.originalEvent = src;
547 this.type = src.type;
553 // timeStamp is buggy for some events on Firefox(#3843)
554 // So we won't rely on the native value
555 this.timeStamp = now();
558 this[ expando ] = true;
561 function returnFalse() {
564 function returnTrue() {
568 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
569 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
570 jQuery.Event.prototype = {
571 preventDefault: function() {
572 this.isDefaultPrevented = returnTrue;
574 var e = this.originalEvent;
579 // if preventDefault exists run it on the original event
580 if ( e.preventDefault ) {
583 // otherwise set the returnValue property of the original event to false (IE)
584 e.returnValue = false;
586 stopPropagation: function() {
587 this.isPropagationStopped = returnTrue;
589 var e = this.originalEvent;
593 // if stopPropagation exists run it on the original event
594 if ( e.stopPropagation ) {
597 // otherwise set the cancelBubble property of the original event to true (IE)
598 e.cancelBubble = true;
600 stopImmediatePropagation: function() {
601 this.isImmediatePropagationStopped = returnTrue;
602 this.stopPropagation();
604 isDefaultPrevented: returnFalse,
605 isPropagationStopped: returnFalse,
606 isImmediatePropagationStopped: returnFalse
609 // Checks if an event happened on an element within another element
610 // Used in jQuery.event.special.mouseenter and mouseleave handlers
611 var withinElement = function( event ) {
612 // Check if mouse(over|out) are still within the same parent element
613 var parent = event.relatedTarget;
615 // Firefox sometimes assigns relatedTarget a XUL element
616 // which we cannot access the parentNode property of
618 // Traverse up the tree
619 while ( parent && parent !== this ) {
620 parent = parent.parentNode;
623 if ( parent !== this ) {
624 // set the correct event type
625 event.type = event.data;
627 // handle event if we actually just moused on to a non sub-element
628 jQuery.event.handle.apply( this, arguments );
631 // assuming we've left the element since we most likely mousedover a xul element
635 // In case of event delegation, we only need to rename the event.type,
636 // liveHandler will take care of the rest.
637 delegate = function( event ) {
638 event.type = event.data;
639 jQuery.event.handle.apply( this, arguments );
642 // Create mouseenter and mouseleave events
644 mouseenter: "mouseover",
645 mouseleave: "mouseout"
646 }, function( orig, fix ) {
647 jQuery.event.special[ orig ] = {
648 setup: function( data ) {
649 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
651 teardown: function( data ) {
652 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
658 if ( !jQuery.support.submitBubbles ) {
660 jQuery.event.special.submit = {
661 setup: function( data, namespaces ) {
662 if ( this.nodeName.toLowerCase() !== "form" ) {
663 jQuery.event.add(this, "click.specialSubmit", function( e ) {
664 var elem = e.target, type = elem.type;
666 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
667 return trigger( "submit", this, arguments );
671 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
672 var elem = e.target, type = elem.type;
674 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
675 return trigger( "submit", this, arguments );
684 teardown: function( namespaces ) {
685 jQuery.event.remove( this, ".specialSubmit" );
691 // change delegation, happens here so we have bind.
692 if ( !jQuery.support.changeBubbles ) {
694 var formElems = /textarea|input|select/i,
698 getVal = function( elem ) {
699 var type = elem.type, val = elem.value;
701 if ( type === "radio" || type === "checkbox" ) {
704 } else if ( type === "select-multiple" ) {
705 val = elem.selectedIndex > -1 ?
706 jQuery.map( elem.options, function( elem ) {
707 return elem.selected;
711 } else if ( elem.nodeName.toLowerCase() === "select" ) {
712 val = elem.selectedIndex;
718 testChange = function testChange( e ) {
719 var elem = e.target, data, val;
721 if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
725 data = jQuery.data( elem, "_change_data" );
728 // the current data will be also retrieved by beforeactivate
729 if ( e.type !== "focusout" || elem.type !== "radio" ) {
730 jQuery.data( elem, "_change_data", val );
733 if ( data === undefined || val === data ) {
737 if ( data != null || val ) {
739 return jQuery.event.trigger( e, arguments[1], elem );
743 jQuery.event.special.change = {
745 focusout: testChange,
747 click: function( e ) {
748 var elem = e.target, type = elem.type;
750 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
751 return testChange.call( this, e );
755 // Change has to be called before submit
756 // Keydown will be called before keypress, which is used in submit-event delegation
757 keydown: function( e ) {
758 var elem = e.target, type = elem.type;
760 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
761 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
762 type === "select-multiple" ) {
763 return testChange.call( this, e );
767 // Beforeactivate happens also before the previous element is blurred
768 // with this event you can't trigger a change event, but you can store
769 // information/focus[in] is not needed anymore
770 beforeactivate: function( e ) {
772 jQuery.data( elem, "_change_data", getVal(elem) );
776 setup: function( data, namespaces ) {
777 if ( this.type === "file" ) {
781 for ( var type in changeFilters ) {
782 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
785 return formElems.test( this.nodeName );
788 teardown: function( namespaces ) {
789 jQuery.event.remove( this, ".specialChange" );
791 return formElems.test( this.nodeName );
795 changeFilters = jQuery.event.special.change.filters;
798 function trigger( type, elem, args ) {
800 return jQuery.event.handle.apply( elem, args );
803 // Create "bubbling" focus and blur events
804 if ( document.addEventListener ) {
805 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
806 jQuery.event.special[ fix ] = {
808 this.addEventListener( orig, handler, true );
810 teardown: function() {
811 this.removeEventListener( orig, handler, true );
815 function handler( e ) {
816 e = jQuery.event.fix( e );
818 return jQuery.event.handle.call( this, e );
823 jQuery.each(["bind", "one"], function( i, name ) {
824 jQuery.fn[ name ] = function( type, data, fn ) {
825 // Handle object literals
826 if ( typeof type === "object" ) {
827 for ( var key in type ) {
828 this[ name ](key, data, type[key], fn);
833 if ( jQuery.isFunction( data ) ) {
838 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
839 jQuery( this ).unbind( event, handler );
840 return fn.apply( this, arguments );
843 if ( type === "unload" && name !== "one" ) {
844 this.one( type, data, fn );
847 for ( var i = 0, l = this.length; i < l; i++ ) {
848 jQuery.event.add( this[i], type, handler, data );
857 unbind: function( type, fn ) {
858 // Handle object literals
859 if ( typeof type === "object" && !type.preventDefault ) {
860 for ( var key in type ) {
861 this.unbind(key, type[key]);
865 for ( var i = 0, l = this.length; i < l; i++ ) {
866 jQuery.event.remove( this[i], type, fn );
873 delegate: function( selector, types, data, fn ) {
874 return this.live( types, data, fn, selector );
877 undelegate: function( selector, types, fn ) {
878 if ( arguments.length === 0 ) {
879 return this.unbind( "live" );
882 return this.die( types, null, fn, selector );
886 trigger: function( type, data ) {
887 return this.each(function() {
888 jQuery.event.trigger( type, data, this );
892 triggerHandler: function( type, data ) {
894 var event = jQuery.Event( type );
895 event.preventDefault();
896 event.stopPropagation();
897 jQuery.event.trigger( event, data, this[0] );
902 toggle: function( fn ) {
903 // Save reference to arguments for access in closure
904 var args = arguments, i = 1;
906 // link all the functions, so any of them can unbind this click handler
907 while ( i < args.length ) {
908 jQuery.proxy( fn, args[ i++ ] );
911 return this.click( jQuery.proxy( fn, function( event ) {
912 // Figure out which function to execute
913 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
914 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
916 // Make sure that clicks stop
917 event.preventDefault();
919 // and execute the function
920 return args[ lastToggle ].apply( this, arguments ) || false;
924 hover: function( fnOver, fnOut ) {
925 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
932 mouseenter: "mouseover",
933 mouseleave: "mouseout"
936 jQuery.each(["live", "die"], function( i, name ) {
937 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
938 var type, i = 0, match, namespaces, preType,
939 selector = origSelector || this.selector,
940 context = origSelector ? this : jQuery( this.context );
942 if ( jQuery.isFunction( data ) ) {
947 types = (types || "").split(" ");
949 while ( (type = types[ i++ ]) != null ) {
950 match = rnamespaces.exec( type );
954 namespaces = match[0];
955 type = type.replace( rnamespaces, "" );
958 if ( type === "hover" ) {
959 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
965 if ( type === "focus" || type === "blur" ) {
966 types.push( liveMap[ type ] + namespaces );
967 type = type + namespaces;
970 type = (liveMap[ type ] || type) + namespaces;
973 if ( name === "live" ) {
975 context.each(function(){
976 jQuery.event.add( this, liveConvert( type, selector ),
977 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
981 // unbind live handler
982 context.unbind( liveConvert( type, selector ), fn );
990 function liveHandler( event ) {
991 var stop, maxLevel, elems = [], selectors = [],
992 related, match, handleObj, elem, j, i, l, data, close,
993 events = jQuery.data( this, "events" );
995 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
996 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
1000 event.liveFired = this;
1002 var live = events.live.slice(0);
1004 for ( j = 0; j < live.length; j++ ) {
1005 handleObj = live[j];
1007 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1008 selectors.push( handleObj.selector );
1011 live.splice( j--, 1 );
1015 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1017 for ( i = 0, l = match.length; i < l; i++ ) {
1020 for ( j = 0; j < live.length; j++ ) {
1021 handleObj = live[j];
1023 if ( close.selector === handleObj.selector ) {
1027 // Those two events require additional checking
1028 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1029 event.type = handleObj.preType;
1030 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1033 if ( !related || related !== elem ) {
1034 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1040 for ( i = 0, l = elems.length; i < l; i++ ) {
1043 if ( maxLevel && match.level > maxLevel ) {
1047 event.currentTarget = match.elem;
1048 event.data = match.handleObj.data;
1049 event.handleObj = match.handleObj;
1051 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1053 if ( ret === false || event.isPropagationStopped() ) {
1054 maxLevel = match.level;
1056 if ( ret === false ) {
1065 function liveConvert( type, selector ) {
1066 return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
1069 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1070 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1071 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1073 // Handle event binding
1074 jQuery.fn[ name ] = function( data, fn ) {
1076 this.bind( name, fn ? data : null, fn || data ) :
1077 this.trigger( name );
1080 if ( jQuery.attrFn ) {
1081 jQuery.attrFn[ name ] = true;
1085 // Prevent memory leaks in IE
1086 // Window isn't included so as not to unbind existing unload events
1088 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
1089 if ( window.attachEvent && !window.addEventListener ) {
1090 window.attachEvent("onunload", function() {
1091 for ( var id in jQuery.cache ) {
1092 if ( jQuery.cache[ id ].handle ) {
1093 // Try/Catch is to handle iframes being unloaded, see #4280
1095 jQuery.event.remove( jQuery.cache[ id ].handle.elem );