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 elem.removeEventListener( type, handle, false );
530 function( elem, type, handle ) {
531 elem.detachEvent( "on" + type, handle );
534 jQuery.Event = function( src ) {
535 // Allow instantiation without the 'new' keyword
536 if ( !this.preventDefault ) {
537 return new jQuery.Event( src );
541 if ( src && src.type ) {
542 this.originalEvent = src;
543 this.type = src.type;
549 // timeStamp is buggy for some events on Firefox(#3843)
550 // So we won't rely on the native value
551 this.timeStamp = now();
554 this[ expando ] = true;
557 function returnFalse() {
560 function returnTrue() {
564 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
565 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
566 jQuery.Event.prototype = {
567 preventDefault: function() {
568 this.isDefaultPrevented = returnTrue;
570 var e = this.originalEvent;
575 // if preventDefault exists run it on the original event
576 if ( e.preventDefault ) {
579 // otherwise set the returnValue property of the original event to false (IE)
580 e.returnValue = false;
582 stopPropagation: function() {
583 this.isPropagationStopped = returnTrue;
585 var e = this.originalEvent;
589 // if stopPropagation exists run it on the original event
590 if ( e.stopPropagation ) {
593 // otherwise set the cancelBubble property of the original event to true (IE)
594 e.cancelBubble = true;
596 stopImmediatePropagation: function() {
597 this.isImmediatePropagationStopped = returnTrue;
598 this.stopPropagation();
600 isDefaultPrevented: returnFalse,
601 isPropagationStopped: returnFalse,
602 isImmediatePropagationStopped: returnFalse
605 // Checks if an event happened on an element within another element
606 // Used in jQuery.event.special.mouseenter and mouseleave handlers
607 var withinElement = function( event ) {
608 // Check if mouse(over|out) are still within the same parent element
609 var parent = event.relatedTarget;
611 // Firefox sometimes assigns relatedTarget a XUL element
612 // which we cannot access the parentNode property of
614 // Traverse up the tree
615 while ( parent && parent !== this ) {
616 parent = parent.parentNode;
619 if ( parent !== this ) {
620 // set the correct event type
621 event.type = event.data;
623 // handle event if we actually just moused on to a non sub-element
624 jQuery.event.handle.apply( this, arguments );
627 // assuming we've left the element since we most likely mousedover a xul element
631 // In case of event delegation, we only need to rename the event.type,
632 // liveHandler will take care of the rest.
633 delegate = function( event ) {
634 event.type = event.data;
635 jQuery.event.handle.apply( this, arguments );
638 // Create mouseenter and mouseleave events
640 mouseenter: "mouseover",
641 mouseleave: "mouseout"
642 }, function( orig, fix ) {
643 jQuery.event.special[ orig ] = {
644 setup: function( data ) {
645 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
647 teardown: function( data ) {
648 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
654 if ( !jQuery.support.submitBubbles ) {
656 jQuery.event.special.submit = {
657 setup: function( data, namespaces ) {
658 if ( this.nodeName.toLowerCase() !== "form" ) {
659 jQuery.event.add(this, "click.specialSubmit", function( e ) {
660 var elem = e.target, type = elem.type;
662 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
663 return trigger( "submit", this, arguments );
667 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
668 var elem = e.target, type = elem.type;
670 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
671 return trigger( "submit", this, arguments );
680 teardown: function( namespaces ) {
681 jQuery.event.remove( this, ".specialSubmit" );
687 // change delegation, happens here so we have bind.
688 if ( !jQuery.support.changeBubbles ) {
690 var formElems = /textarea|input|select/i,
694 getVal = function( elem ) {
695 var type = elem.type, val = elem.value;
697 if ( type === "radio" || type === "checkbox" ) {
700 } else if ( type === "select-multiple" ) {
701 val = elem.selectedIndex > -1 ?
702 jQuery.map( elem.options, function( elem ) {
703 return elem.selected;
707 } else if ( elem.nodeName.toLowerCase() === "select" ) {
708 val = elem.selectedIndex;
714 testChange = function testChange( e ) {
715 var elem = e.target, data, val;
717 if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
721 data = jQuery.data( elem, "_change_data" );
724 // the current data will be also retrieved by beforeactivate
725 if ( e.type !== "focusout" || elem.type !== "radio" ) {
726 jQuery.data( elem, "_change_data", val );
729 if ( data === undefined || val === data ) {
733 if ( data != null || val ) {
735 return jQuery.event.trigger( e, arguments[1], elem );
739 jQuery.event.special.change = {
741 focusout: testChange,
743 click: function( e ) {
744 var elem = e.target, type = elem.type;
746 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
747 return testChange.call( this, e );
751 // Change has to be called before submit
752 // Keydown will be called before keypress, which is used in submit-event delegation
753 keydown: function( e ) {
754 var elem = e.target, type = elem.type;
756 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
757 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
758 type === "select-multiple" ) {
759 return testChange.call( this, e );
763 // Beforeactivate happens also before the previous element is blurred
764 // with this event you can't trigger a change event, but you can store
765 // information/focus[in] is not needed anymore
766 beforeactivate: function( e ) {
768 jQuery.data( elem, "_change_data", getVal(elem) );
772 setup: function( data, namespaces ) {
773 if ( this.type === "file" ) {
777 for ( var type in changeFilters ) {
778 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
781 return formElems.test( this.nodeName );
784 teardown: function( namespaces ) {
785 jQuery.event.remove( this, ".specialChange" );
787 return formElems.test( this.nodeName );
791 changeFilters = jQuery.event.special.change.filters;
794 function trigger( type, elem, args ) {
796 return jQuery.event.handle.apply( elem, args );
799 // Create "bubbling" focus and blur events
800 if ( document.addEventListener ) {
801 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
802 jQuery.event.special[ fix ] = {
804 this.addEventListener( orig, handler, true );
806 teardown: function() {
807 this.removeEventListener( orig, handler, true );
811 function handler( e ) {
812 e = jQuery.event.fix( e );
814 return jQuery.event.handle.call( this, e );
819 jQuery.each(["bind", "one"], function( i, name ) {
820 jQuery.fn[ name ] = function( type, data, fn ) {
821 // Handle object literals
822 if ( typeof type === "object" ) {
823 for ( var key in type ) {
824 this[ name ](key, data, type[key], fn);
829 if ( jQuery.isFunction( data ) ) {
834 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
835 jQuery( this ).unbind( event, handler );
836 return fn.apply( this, arguments );
839 if ( type === "unload" && name !== "one" ) {
840 this.one( type, data, fn );
843 for ( var i = 0, l = this.length; i < l; i++ ) {
844 jQuery.event.add( this[i], type, handler, data );
853 unbind: function( type, fn ) {
854 // Handle object literals
855 if ( typeof type === "object" && !type.preventDefault ) {
856 for ( var key in type ) {
857 this.unbind(key, type[key]);
861 for ( var i = 0, l = this.length; i < l; i++ ) {
862 jQuery.event.remove( this[i], type, fn );
869 delegate: function( selector, types, data, fn ) {
870 return this.live( types, data, fn, selector );
873 undelegate: function( selector, types, fn ) {
874 if ( arguments.length === 0 ) {
875 return this.unbind( "live" );
878 return this.die( types, null, fn, selector );
882 trigger: function( type, data ) {
883 return this.each(function() {
884 jQuery.event.trigger( type, data, this );
888 triggerHandler: function( type, data ) {
890 var event = jQuery.Event( type );
891 event.preventDefault();
892 event.stopPropagation();
893 jQuery.event.trigger( event, data, this[0] );
898 toggle: function( fn ) {
899 // Save reference to arguments for access in closure
900 var args = arguments, i = 1;
902 // link all the functions, so any of them can unbind this click handler
903 while ( i < args.length ) {
904 jQuery.proxy( fn, args[ i++ ] );
907 return this.click( jQuery.proxy( fn, function( event ) {
908 // Figure out which function to execute
909 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
910 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
912 // Make sure that clicks stop
913 event.preventDefault();
915 // and execute the function
916 return args[ lastToggle ].apply( this, arguments ) || false;
920 hover: function( fnOver, fnOut ) {
921 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
928 mouseenter: "mouseover",
929 mouseleave: "mouseout"
932 jQuery.each(["live", "die"], function( i, name ) {
933 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
934 var type, i = 0, match, namespaces, preType,
935 selector = origSelector || this.selector,
936 context = origSelector ? this : jQuery( this.context );
938 if ( jQuery.isFunction( data ) ) {
943 types = (types || "").split(" ");
945 while ( (type = types[ i++ ]) != null ) {
946 match = rnamespaces.exec( type );
950 namespaces = match[0];
951 type = type.replace( rnamespaces, "" );
954 if ( type === "hover" ) {
955 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
961 if ( type === "focus" || type === "blur" ) {
962 types.push( liveMap[ type ] + namespaces );
963 type = type + namespaces;
966 type = (liveMap[ type ] || type) + namespaces;
969 if ( name === "live" ) {
971 context.each(function(){
972 jQuery.event.add( this, liveConvert( type, selector ),
973 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
977 // unbind live handler
978 context.unbind( liveConvert( type, selector ), fn );
986 function liveHandler( event ) {
987 var stop, maxLevel, elems = [], selectors = [],
988 related, match, handleObj, elem, j, i, l, data, close,
989 events = jQuery.data( this, "events" );
991 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
992 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
996 event.liveFired = this;
998 var live = events.live.slice(0);
1000 for ( j = 0; j < live.length; j++ ) {
1001 handleObj = live[j];
1003 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1004 selectors.push( handleObj.selector );
1007 live.splice( j--, 1 );
1011 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1013 for ( i = 0, l = match.length; i < l; i++ ) {
1016 for ( j = 0; j < live.length; j++ ) {
1017 handleObj = live[j];
1019 if ( close.selector === handleObj.selector ) {
1023 // Those two events require additional checking
1024 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1025 event.type = handleObj.preType;
1026 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1029 if ( !related || related !== elem ) {
1030 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1036 for ( i = 0, l = elems.length; i < l; i++ ) {
1039 if ( maxLevel && match.level > maxLevel ) {
1043 event.currentTarget = match.elem;
1044 event.data = match.handleObj.data;
1045 event.handleObj = match.handleObj;
1047 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1049 if ( ret === false || event.isPropagationStopped() ) {
1050 maxLevel = match.level;
1052 if ( ret === false ) {
1061 function liveConvert( type, selector ) {
1062 return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
1065 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1066 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1067 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1069 // Handle event binding
1070 jQuery.fn[ name ] = function( fn ) {
1071 return fn ? this.bind( name, fn ) : this.trigger( name );
1074 if ( jQuery.attrFn ) {
1075 jQuery.attrFn[ name ] = true;
1079 // Prevent memory leaks in IE
1080 // Window isn't included so as not to unbind existing unload events
1082 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
1083 if ( window.attachEvent && !window.addEventListener ) {
1084 window.attachEvent("onunload", function() {
1085 for ( var id in jQuery.cache ) {
1086 if ( jQuery.cache[ id ].handle ) {
1087 // Try/Catch is to handle iframes being unloaded, see #4280
1089 jQuery.event.remove( jQuery.cache[ id ].handle.elem );