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 );
117 // Add the function to the element's handler list
118 handlers.push( handleObj );
120 // Keep track of which events have been used, for global triggering
121 jQuery.event.global[ type ] = true;
124 // Nullify elem to prevent memory leaks in IE
130 // Detach an event or set of events from an element
131 remove: function( elem, types, handler, pos ) {
132 // don't do events on text and comment nodes
133 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
137 var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
138 elemData = jQuery.data( elem ),
139 events = elemData && elemData.events;
141 if ( !elemData || !events ) {
145 // types is actually an event object here
146 if ( types && types.type ) {
147 handler = types.handler;
151 // Unbind all events for the element
152 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
155 for ( type in events ) {
156 jQuery.event.remove( elem, type + types );
162 // Handle multiple events separated by a space
163 // jQuery(...).unbind("mouseover mouseout", fn);
164 types = types.split(" ");
166 while ( (type = types[ i++ ]) ) {
169 all = type.indexOf(".") < 0;
173 // Namespaced event handlers
174 namespaces = type.split(".");
175 type = namespaces.shift();
177 namespace = new RegExp("(^|\\.)" +
178 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
181 eventType = events[ type ];
188 for ( var j = 0; j < eventType.length; j++ ) {
189 handleObj = eventType[ j ];
191 if ( all || namespace.test( handleObj.namespace ) ) {
192 jQuery.event.remove( elem, origType, handleObj.handler, j );
193 eventType.splice( j--, 1 );
200 special = jQuery.event.special[ type ] || {};
202 for ( var j = pos || 0; j < eventType.length; j++ ) {
203 handleObj = eventType[ j ];
205 if ( handler.guid === handleObj.guid ) {
206 // remove the given handler for the given type
207 if ( all || namespace.test( handleObj.namespace ) ) {
209 eventType.splice( j--, 1 );
212 if ( special.remove ) {
213 special.remove.call( elem, handleObj );
223 // remove generic event handler if no more handlers exist
224 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
225 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
226 removeEvent( elem, type, elemData.handle );
230 delete events[ type ];
234 // Remove the expando if it's no longer used
235 if ( jQuery.isEmptyObject( events ) ) {
236 var handle = elemData.handle;
241 delete elemData.events;
242 delete elemData.handle;
244 if ( jQuery.isEmptyObject( elemData ) ) {
245 jQuery.removeData( elem );
250 // bubbling is internal
251 trigger: function( event, data, elem /*, bubbling */ ) {
252 // Event object or event type
253 var type = event.type || event,
254 bubbling = arguments[3];
257 event = typeof event === "object" ?
258 // jQuery.Event object
259 event[expando] ? event :
261 jQuery.extend( jQuery.Event(type), event ) :
262 // Just the event type (string)
265 if ( type.indexOf("!") >= 0 ) {
266 event.type = type = type.slice(0, -1);
267 event.exclusive = true;
270 // Handle a global trigger
272 // Don't bubble custom events when global (to avoid too much overhead)
273 event.stopPropagation();
275 // Only trigger if we've ever bound an event for it
276 if ( jQuery.event.global[ type ] ) {
277 jQuery.each( jQuery.cache, function() {
278 if ( this.events && this.events[type] ) {
279 jQuery.event.trigger( event, data, this.handle.elem );
285 // Handle triggering a single element
287 // don't do events on text and comment nodes
288 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
292 // Clean up in case it is reused
293 event.result = undefined;
296 // Clone the incoming data, if any
297 data = jQuery.makeArray( data );
298 data.unshift( event );
301 event.currentTarget = elem;
303 // Trigger the event, it is assumed that "handle" is a function
304 var handle = jQuery.data( elem, "handle" );
306 handle.apply( elem, data );
309 var parent = elem.parentNode || elem.ownerDocument;
311 // Trigger an inline bound script
313 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
314 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
315 event.result = false;
319 // prevent IE from throwing an error for some elements with some event types, see #3533
322 if ( !event.isPropagationStopped() && parent ) {
323 jQuery.event.trigger( event, data, parent, true );
325 } else if ( !event.isDefaultPrevented() ) {
326 var target = event.target, old,
327 isClick = jQuery.nodeName(target, "a") && type === "click",
328 special = jQuery.event.special[ type ] || {};
330 if ( (!special._default || special._default.call( elem, event ) === false) &&
331 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
334 if ( target[ type ] ) {
335 // Make sure that we don't accidentally re-trigger the onFOO events
336 old = target[ "on" + type ];
339 target[ "on" + type ] = null;
342 jQuery.event.triggered = true;
346 // prevent IE from throwing an error for some elements with some event types, see #3533
350 target[ "on" + type ] = old;
353 jQuery.event.triggered = false;
358 handle: function( event ) {
359 var all, handlers, namespaces, namespace, events;
361 event = arguments[0] = jQuery.event.fix( event || window.event );
362 event.currentTarget = this;
364 // Namespaced event handlers
365 all = event.type.indexOf(".") < 0 && !event.exclusive;
368 namespaces = event.type.split(".");
369 event.type = namespaces.shift();
370 namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
373 var events = jQuery.data(this, "events"), handlers = events[ event.type ];
375 if ( events && handlers ) {
376 // Clone the handlers to prevent manipulation
377 handlers = handlers.slice(0);
379 for ( var j = 0, l = handlers.length; j < l; j++ ) {
380 var handleObj = handlers[ j ];
382 // Filter the functions by class
383 if ( all || namespace.test( handleObj.namespace ) ) {
384 // Pass in a reference to the handler function itself
385 // So that we can later remove it
386 event.handler = handleObj.handler;
387 event.data = handleObj.data;
388 event.handleObj = handleObj;
390 var ret = handleObj.handler.apply( this, arguments );
392 if ( ret !== undefined ) {
394 if ( ret === false ) {
395 event.preventDefault();
396 event.stopPropagation();
400 if ( event.isImmediatePropagationStopped() ) {
410 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(" "),
412 fix: function( event ) {
413 if ( event[ expando ] ) {
417 // store a copy of the original event object
418 // and "clone" to set read-only properties
419 var originalEvent = event;
420 event = jQuery.Event( originalEvent );
422 for ( var i = this.props.length, prop; i; ) {
423 prop = this.props[ --i ];
424 event[ prop ] = originalEvent[ prop ];
427 // Fix target property, if necessary
428 if ( !event.target ) {
429 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
432 // check if target is a textnode (safari)
433 if ( event.target.nodeType === 3 ) {
434 event.target = event.target.parentNode;
437 // Add relatedTarget, if necessary
438 if ( !event.relatedTarget && event.fromElement ) {
439 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
442 // Calculate pageX/Y if missing and clientX/Y available
443 if ( event.pageX == null && event.clientX != null ) {
444 var doc = document.documentElement, body = document.body;
445 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
446 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
449 // Add which for key events
450 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
451 event.which = event.charCode || event.keyCode;
454 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
455 if ( !event.metaKey && event.ctrlKey ) {
456 event.metaKey = event.ctrlKey;
459 // Add which for click: 1 === left; 2 === middle; 3 === right
460 // Note: button is not normalized, so don't use it
461 if ( !event.which && event.button !== undefined ) {
462 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
468 // Deprecated, use jQuery.guid instead
471 // Deprecated, use jQuery.proxy instead
476 // Make sure the ready event is setup
477 setup: jQuery.bindReady,
478 teardown: jQuery.noop
482 add: function( handleObj ) {
483 jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
486 remove: function( handleObj ) {
488 type = handleObj.origType.replace(rnamespaces, "");
490 jQuery.each( jQuery.data(this, "events").live || [], function() {
491 if ( type === this.origType.replace(rnamespaces, "") ) {
498 jQuery.event.remove( this, handleObj.origType, liveHandler );
505 setup: function( data, namespaces, eventHandle ) {
506 // We only want to do this special case on windows
507 if ( this.setInterval ) {
508 this.onbeforeunload = eventHandle;
513 teardown: function( namespaces, eventHandle ) {
514 if ( this.onbeforeunload === eventHandle ) {
515 this.onbeforeunload = null;
522 var removeEvent = document.removeEventListener ?
523 function( elem, type, handle ) {
524 elem.removeEventListener( type, handle, false );
526 function( elem, type, handle ) {
527 elem.detachEvent( "on" + type, handle );
530 jQuery.Event = function( src ) {
531 // Allow instantiation without the 'new' keyword
532 if ( !this.preventDefault ) {
533 return new jQuery.Event( src );
537 if ( src && src.type ) {
538 this.originalEvent = src;
539 this.type = src.type;
545 // timeStamp is buggy for some events on Firefox(#3843)
546 // So we won't rely on the native value
547 this.timeStamp = now();
550 this[ expando ] = true;
553 function returnFalse() {
556 function returnTrue() {
560 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
561 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
562 jQuery.Event.prototype = {
563 preventDefault: function() {
564 this.isDefaultPrevented = returnTrue;
566 var e = this.originalEvent;
571 // if preventDefault exists run it on the original event
572 if ( e.preventDefault ) {
575 // otherwise set the returnValue property of the original event to false (IE)
576 e.returnValue = false;
578 stopPropagation: function() {
579 this.isPropagationStopped = returnTrue;
581 var e = this.originalEvent;
585 // if stopPropagation exists run it on the original event
586 if ( e.stopPropagation ) {
589 // otherwise set the cancelBubble property of the original event to true (IE)
590 e.cancelBubble = true;
592 stopImmediatePropagation: function() {
593 this.isImmediatePropagationStopped = returnTrue;
594 this.stopPropagation();
596 isDefaultPrevented: returnFalse,
597 isPropagationStopped: returnFalse,
598 isImmediatePropagationStopped: returnFalse
601 // Checks if an event happened on an element within another element
602 // Used in jQuery.event.special.mouseenter and mouseleave handlers
603 var withinElement = function( event ) {
604 // Check if mouse(over|out) are still within the same parent element
605 var parent = event.relatedTarget;
607 // Traverse up the tree
608 while ( parent && parent !== this ) {
609 // Firefox sometimes assigns relatedTarget a XUL element
610 // which we cannot access the parentNode property of
612 parent = parent.parentNode;
614 // assuming we've left the element since we most likely mousedover a xul element
620 if ( parent !== this ) {
621 // set the correct event type
622 event.type = event.data;
624 // handle event if we actually just moused on to a non sub-element
625 jQuery.event.handle.apply( this, arguments );
630 // In case of event delegation, we only need to rename the event.type,
631 // liveHandler will take care of the rest.
632 delegate = function( event ) {
633 event.type = event.data;
634 jQuery.event.handle.apply( this, arguments );
637 // Create mouseenter and mouseleave events
639 mouseenter: "mouseover",
640 mouseleave: "mouseout"
641 }, function( orig, fix ) {
642 jQuery.event.special[ orig ] = {
643 setup: function( data ) {
644 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
646 teardown: function( data ) {
647 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
653 if ( !jQuery.support.submitBubbles ) {
655 jQuery.event.special.submit = {
656 setup: function( data, namespaces ) {
657 if ( this.nodeName.toLowerCase() !== "form" ) {
658 jQuery.event.add(this, "click.specialSubmit", function( e ) {
659 var elem = e.target, type = elem.type;
661 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
662 return trigger( "submit", this, arguments );
666 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
667 var elem = e.target, type = elem.type;
669 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
670 return trigger( "submit", this, arguments );
679 teardown: function( namespaces ) {
680 jQuery.event.remove( this, ".specialSubmit" );
686 // change delegation, happens here so we have bind.
687 if ( !jQuery.support.changeBubbles ) {
689 var formElems = /textarea|input|select/i,
693 getVal = function( elem ) {
694 var type = elem.type, val = elem.value;
696 if ( type === "radio" || type === "checkbox" ) {
699 } else if ( type === "select-multiple" ) {
700 val = elem.selectedIndex > -1 ?
701 jQuery.map( elem.options, function( elem ) {
702 return elem.selected;
706 } else if ( elem.nodeName.toLowerCase() === "select" ) {
707 val = elem.selectedIndex;
713 testChange = function testChange( e ) {
714 var elem = e.target, data, val;
716 if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
720 data = jQuery.data( elem, "_change_data" );
723 // the current data will be also retrieved by beforeactivate
724 if ( e.type !== "focusout" || elem.type !== "radio" ) {
725 jQuery.data( elem, "_change_data", val );
728 if ( data === undefined || val === data ) {
732 if ( data != null || val ) {
734 return jQuery.event.trigger( e, arguments[1], elem );
738 jQuery.event.special.change = {
740 focusout: testChange,
742 click: function( e ) {
743 var elem = e.target, type = elem.type;
745 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
746 return testChange.call( this, e );
750 // Change has to be called before submit
751 // Keydown will be called before keypress, which is used in submit-event delegation
752 keydown: function( e ) {
753 var elem = e.target, type = elem.type;
755 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
756 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
757 type === "select-multiple" ) {
758 return testChange.call( this, e );
762 // Beforeactivate happens also before the previous element is blurred
763 // with this event you can't trigger a change event, but you can store
764 // information/focus[in] is not needed anymore
765 beforeactivate: function( e ) {
767 jQuery.data( elem, "_change_data", getVal(elem) );
771 setup: function( data, namespaces ) {
772 if ( this.type === "file" ) {
776 for ( var type in changeFilters ) {
777 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
780 return formElems.test( this.nodeName );
783 teardown: function( namespaces ) {
784 jQuery.event.remove( this, ".specialChange" );
786 return formElems.test( this.nodeName );
790 changeFilters = jQuery.event.special.change.filters;
793 function trigger( type, elem, args ) {
795 return jQuery.event.handle.apply( elem, args );
798 // Create "bubbling" focus and blur events
799 if ( document.addEventListener ) {
800 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
801 jQuery.event.special[ fix ] = {
803 this.addEventListener( orig, handler, true );
805 teardown: function() {
806 this.removeEventListener( orig, handler, true );
810 function handler( e ) {
811 e = jQuery.event.fix( e );
813 return jQuery.event.handle.call( this, e );
818 jQuery.each(["bind", "one"], function( i, name ) {
819 jQuery.fn[ name ] = function( type, data, fn ) {
820 // Handle object literals
821 if ( typeof type === "object" ) {
822 for ( var key in type ) {
823 this[ name ](key, data, type[key], fn);
828 if ( jQuery.isFunction( data ) ) {
833 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
834 jQuery( this ).unbind( event, handler );
835 return fn.apply( this, arguments );
838 if ( type === "unload" && name !== "one" ) {
839 this.one( type, data, fn );
842 for ( var i = 0, l = this.length; i < l; i++ ) {
843 jQuery.event.add( this[i], type, handler, data );
852 unbind: function( type, fn ) {
853 // Handle object literals
854 if ( typeof type === "object" && !type.preventDefault ) {
855 for ( var key in type ) {
856 this.unbind(key, type[key]);
860 for ( var i = 0, l = this.length; i < l; i++ ) {
861 jQuery.event.remove( this[i], type, fn );
868 delegate: function( selector, types, data, fn ) {
869 return this.live( types, data, fn, selector );
872 undelegate: function( selector, types, fn ) {
873 if ( arguments.length === 0 ) {
874 return this.unbind( "live" );
877 return this.die( types, null, fn, selector );
881 trigger: function( type, data ) {
882 return this.each(function() {
883 jQuery.event.trigger( type, data, this );
887 triggerHandler: function( type, data ) {
889 var event = jQuery.Event( type );
890 event.preventDefault();
891 event.stopPropagation();
892 jQuery.event.trigger( event, data, this[0] );
897 toggle: function( fn ) {
898 // Save reference to arguments for access in closure
899 var args = arguments, i = 1;
901 // link all the functions, so any of them can unbind this click handler
902 while ( i < args.length ) {
903 jQuery.proxy( fn, args[ i++ ] );
906 return this.click( jQuery.proxy( fn, function( event ) {
907 // Figure out which function to execute
908 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
909 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
911 // Make sure that clicks stop
912 event.preventDefault();
914 // and execute the function
915 return args[ lastToggle ].apply( this, arguments ) || false;
919 hover: function( fnOver, fnOut ) {
920 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
927 mouseenter: "mouseover",
928 mouseleave: "mouseout"
931 jQuery.each(["live", "die"], function( i, name ) {
932 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
933 var type, i = 0, match, namespaces, preType,
934 selector = origSelector || this.selector,
935 context = origSelector ? this : jQuery( this.context );
937 if ( jQuery.isFunction( data ) ) {
942 types = (types || "").split(" ");
944 while ( (type = types[ i++ ]) != null ) {
945 match = rnamespaces.exec( type );
949 namespaces = match[0];
950 type = type.replace( rnamespaces, "" );
953 if ( type === "hover" ) {
954 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
960 if ( type === "focus" || type === "blur" ) {
961 types.push( liveMap[ type ] + namespaces );
962 type = type + namespaces;
965 type = (liveMap[ type ] || type) + namespaces;
968 if ( name === "live" ) {
970 context.each(function(){
971 jQuery.event.add( this, liveConvert( type, selector ),
972 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
976 // unbind live handler
977 context.unbind( liveConvert( type, selector ), fn );
985 function liveHandler( event ) {
986 var stop, elems = [], selectors = [], args = arguments,
987 related, match, handleObj, elem, j, i, l, data,
988 events = jQuery.data( this, "events" );
990 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
991 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
995 event.liveFired = this;
997 var live = events.live.slice(0);
999 for ( j = 0; j < live.length; j++ ) {
1000 handleObj = live[j];
1002 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1003 selectors.push( handleObj.selector );
1006 live.splice( j--, 1 );
1010 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1012 for ( i = 0, l = match.length; i < l; i++ ) {
1013 for ( j = 0; j < live.length; j++ ) {
1014 handleObj = live[j];
1016 if ( match[i].selector === handleObj.selector ) {
1017 elem = match[i].elem;
1020 // Those two events require additional checking
1021 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1022 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1025 if ( !related || related !== elem ) {
1026 elems.push({ elem: elem, handleObj: handleObj });
1032 for ( i = 0, l = elems.length; i < l; i++ ) {
1034 event.currentTarget = match.elem;
1035 event.data = match.handleObj.data;
1036 event.handleObj = match.handleObj;
1038 if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
1047 function liveConvert( type, selector ) {
1048 return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
1051 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1052 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1053 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1055 // Handle event binding
1056 jQuery.fn[ name ] = function( fn ) {
1057 return fn ? this.bind( name, fn ) : this.trigger( name );
1060 if ( jQuery.attrFn ) {
1061 jQuery.attrFn[ name ] = true;
1065 // Prevent memory leaks in IE
1066 // Window isn't included so as not to unbind existing unload events
1068 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
1069 if ( window.attachEvent && !window.addEventListener ) {
1070 window.attachEvent("onunload", function() {
1071 for ( var id in jQuery.cache ) {
1072 if ( jQuery.cache[ id ].handle ) {
1073 // Try/Catch is to handle iframes being unloaded, see #4280
1075 jQuery.event.remove( jQuery.cache[ id ].handle.elem );