1 var fcleanup = function( nm ) {
2 return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
8 * A number of helper functions used for managing events.
9 * Many of the ideas behind this code originated from
10 * Dean Edwards' addEvent library.
14 // Bind an event to an element
15 // Original by Dean Edwards
16 add: function( elem, types, handler, data ) {
17 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
21 // For whatever reason, IE has trouble passing the window object
22 // around, causing it to be cloned in the process
23 if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
27 // Make sure that the function being executed has a unique ID
28 if ( !handler.guid ) {
29 handler.guid = jQuery.guid++;
32 // if data is passed, bind to handler
33 if ( data !== undefined ) {
34 // Create temporary function pointer to original handler
37 // Create unique handler function, wrapped around original handler
38 handler = jQuery.proxy( fn );
40 // Store data in unique handler
44 // Init the element's event structure
45 var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ),
46 handle = jQuery.data( elem, "handle" ), eventHandle;
49 eventHandle = function() {
50 // Handle the second event of a trigger and when
51 // an event is called after a page has unloaded
52 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
53 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
57 handle = jQuery.data( elem, "handle", eventHandle );
60 // If no handle is found then we must be trying to bind to one of the
61 // banned noData elements
66 // Add elem as a property of the handle function
67 // This is to prevent a memory leak with non-native
71 // Handle multiple events separated by a space
72 // jQuery(...).bind("mouseover mouseout", fn);
73 types = types.split( /\s+/ );
77 while ( (type = types[ i++ ]) ) {
78 // Namespaced event handlers
79 var namespaces = type.split(".");
80 type = namespaces.shift();
83 handler = jQuery.proxy( handler );
85 if ( data !== undefined ) {
90 handler.type = namespaces.slice(0).sort().join(".");
92 // Get the current list of functions bound to this event
93 var handlers = events[ type ],
94 special = this.special[ type ] || {};
96 // Init the event handler queue
98 handlers = events[ type ] = {};
100 // Check for a special event handler
101 // Only use addEventListener/attachEvent if the special
102 // events handler returns false
103 if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) {
104 // Bind the global event handler to the element
105 if ( elem.addEventListener ) {
106 elem.addEventListener( type, handle, false );
107 } else if ( elem.attachEvent ) {
108 elem.attachEvent( "on" + type, handle );
114 var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers );
115 if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) {
116 modifiedHandler.guid = modifiedHandler.guid || handler.guid;
117 handler = modifiedHandler;
121 // Add the function to the element's handler list
122 handlers[ handler.guid ] = handler;
124 // Keep track of which events have been used, for global triggering
125 this.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 ) {
136 // don't do events on text and comment nodes
137 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
141 var events = jQuery.data( elem, "events" ), ret, type, fn;
144 // Unbind all events for the element
145 if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) {
146 for ( type in events ) {
147 this.remove( elem, type + (types || "") );
150 // types is actually an event object here
152 handler = types.handler;
156 // Handle multiple events separated by a space
157 // jQuery(...).unbind("mouseover mouseout", fn);
158 types = types.split(/\s+/);
160 while ( (type = types[ i++ ]) ) {
161 // Namespaced event handlers
162 var namespaces = type.split(".");
163 type = namespaces.shift();
164 var all = !namespaces.length,
165 cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
166 namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
167 special = this.special[ type ] || {};
169 if ( events[ type ] ) {
170 // remove the given handler for the given type
172 fn = events[ type ][ handler.guid ];
173 delete events[ type ][ handler.guid ];
175 // remove all handlers for the given type
177 for ( var handle in events[ type ] ) {
178 // Handle the removal of namespaced events
179 if ( all || namespace.test( events[ type ][ handle ].type ) ) {
180 delete events[ type ][ handle ];
185 if ( special.remove ) {
186 special.remove.call( elem, namespaces, fn);
189 // remove generic event handler if no more handlers exist
190 for ( ret in events[ type ] ) {
194 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
195 if ( elem.removeEventListener ) {
196 elem.removeEventListener( type, jQuery.data( elem, "handle" ), false );
197 } else if ( elem.detachEvent ) {
198 elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) );
202 delete events[ type ];
208 // Remove the expando if it's no longer used
209 for ( ret in events ) {
213 var handle = jQuery.data( elem, "handle" );
217 jQuery.removeData( elem, "events" );
218 jQuery.removeData( elem, "handle" );
223 // bubbling is internal
224 trigger: function( event, data, elem /*, bubbling */ ) {
225 // Event object or event type
226 var type = event.type || event,
227 bubbling = arguments[3];
230 event = typeof event === "object" ?
231 // jQuery.Event object
232 event[expando] ? event :
234 jQuery.extend( jQuery.Event(type), event ) :
235 // Just the event type (string)
238 if ( type.indexOf("!") >= 0 ) {
239 event.type = type = type.slice(0, -1);
240 event.exclusive = true;
243 // Handle a global trigger
245 // Don't bubble custom events when global (to avoid too much overhead)
246 event.stopPropagation();
248 // Only trigger if we've ever bound an event for it
249 if ( this.global[ type ] ) {
250 jQuery.each( jQuery.cache, function() {
251 if ( this.events && this.events[type] ) {
252 jQuery.event.trigger( event, data, this.handle.elem );
258 // Handle triggering a single element
260 // don't do events on text and comment nodes
261 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
265 // Clean up in case it is reused
266 event.result = undefined;
269 // Clone the incoming data, if any
270 data = jQuery.makeArray( data );
271 data.unshift( event );
274 event.currentTarget = elem;
276 // Trigger the event, it is assumed that "handle" is a function
277 var handle = jQuery.data( elem, "handle" );
279 handle.apply( elem, data );
282 var parent = elem.parentNode || elem.ownerDocument;
284 // Trigger an inline bound script
286 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
287 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
288 event.result = false;
292 // prevent IE from throwing an error for some elements with some event types, see #3533
295 if ( !event.isPropagationStopped() && parent ) {
296 jQuery.event.trigger( event, data, parent, true );
298 } else if ( !event.isDefaultPrevented() ) {
299 var target = event.target, old,
300 isClick = jQuery.nodeName(target, "a") && type === "click";
302 if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
304 if ( target[ type ] ) {
305 // Make sure that we don't accidentally re-trigger the onFOO events
306 old = target[ "on" + type ];
309 target[ "on" + type ] = null;
312 this.triggered = true;
316 // prevent IE from throwing an error for some elements with some event types, see #3533
320 target[ "on" + type ] = old;
323 this.triggered = false;
328 handle: function( event ) {
329 // returned undefined or false
332 event = arguments[0] = jQuery.event.fix( event || window.event );
333 event.currentTarget = this;
335 // Namespaced event handlers
336 var namespaces = event.type.split(".");
337 event.type = namespaces.shift();
339 // Cache this now, all = true means, any handler
340 all = !namespaces.length && !event.exclusive;
342 var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
344 handlers = ( jQuery.data(this, "events") || {} )[ event.type ];
346 for ( var j in handlers ) {
347 var handler = handlers[ j ];
349 // Filter the functions by class
350 if ( all || namespace.test(handler.type) ) {
351 // Pass in a reference to the handler function itself
352 // So that we can later remove it
353 event.handler = handler;
354 event.data = handler.data;
356 var ret = handler.apply( this, arguments );
358 if ( ret !== undefined ) {
360 if ( ret === false ) {
361 event.preventDefault();
362 event.stopPropagation();
366 if ( event.isImmediatePropagationStopped() ) {
376 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(" "),
378 fix: function( event ) {
379 if ( event[ expando ] ) {
383 // store a copy of the original event object
384 // and "clone" to set read-only properties
385 var originalEvent = event;
386 event = jQuery.Event( originalEvent );
388 for ( var i = this.props.length, prop; i; ) {
389 prop = this.props[ --i ];
390 event[ prop ] = originalEvent[ prop ];
393 // Fix target property, if necessary
394 if ( !event.target ) {
395 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
398 // check if target is a textnode (safari)
399 if ( event.target.nodeType === 3 ) {
400 event.target = event.target.parentNode;
403 // Add relatedTarget, if necessary
404 if ( !event.relatedTarget && event.fromElement ) {
405 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
408 // Calculate pageX/Y if missing and clientX/Y available
409 if ( event.pageX == null && event.clientX != null ) {
410 var doc = document.documentElement, body = document.body;
411 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
412 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
415 // Add which for key events
416 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
417 event.which = event.charCode || event.keyCode;
420 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
421 if ( !event.metaKey && event.ctrlKey ) {
422 event.metaKey = event.ctrlKey;
425 // Add which for click: 1 === left; 2 === middle; 3 === right
426 // Note: button is not normalized, so don't use it
427 if ( !event.which && event.button !== undefined ) {
428 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
434 // Deprecated, use jQuery.guid instead
437 // Deprecated, use jQuery.proxy instead
442 // Make sure the ready event is setup
443 setup: jQuery.bindReady,
444 teardown: jQuery.noop
448 add: function( proxy, data, namespaces, live ) {
449 jQuery.extend( proxy, data || {} );
451 proxy.guid += data.selector + data.live;
452 data.liveProxy = proxy;
454 jQuery.event.add( this, data.live, liveHandler, data );
458 remove: function( namespaces ) {
459 if ( namespaces.length ) {
460 var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
462 jQuery.each( (jQuery.data(this, "events").live || {}), function() {
463 if ( name.test(this.type) ) {
469 jQuery.event.remove( this, namespaces[0], liveHandler );
476 setup: function( data, namespaces, fn ) {
477 // We only want to do this special case on windows
478 if ( this.setInterval ) {
479 this.onbeforeunload = fn;
484 teardown: function( namespaces, fn ) {
485 if ( this.onbeforeunload === fn ) {
486 this.onbeforeunload = null;
493 jQuery.Event = function( src ) {
494 // Allow instantiation without the 'new' keyword
495 if ( !this.preventDefault ) {
496 return new jQuery.Event( src );
500 if ( src && src.type ) {
501 this.originalEvent = src;
502 this.type = src.type;
508 // timeStamp is buggy for some events on Firefox(#3843)
509 // So we won't rely on the native value
510 this.timeStamp = now();
513 this[ expando ] = true;
516 function returnFalse() {
519 function returnTrue() {
523 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
524 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
525 jQuery.Event.prototype = {
526 preventDefault: function() {
527 this.isDefaultPrevented = returnTrue;
529 var e = this.originalEvent;
534 // if preventDefault exists run it on the original event
535 if ( e.preventDefault ) {
538 // otherwise set the returnValue property of the original event to false (IE)
539 e.returnValue = false;
541 stopPropagation: function() {
542 this.isPropagationStopped = returnTrue;
544 var e = this.originalEvent;
548 // if stopPropagation exists run it on the original event
549 if ( e.stopPropagation ) {
552 // otherwise set the cancelBubble property of the original event to true (IE)
553 e.cancelBubble = true;
555 stopImmediatePropagation: function() {
556 this.isImmediatePropagationStopped = returnTrue;
557 this.stopPropagation();
559 isDefaultPrevented: returnFalse,
560 isPropagationStopped: returnFalse,
561 isImmediatePropagationStopped: returnFalse
564 // Checks if an event happened on an element within another element
565 // Used in jQuery.event.special.mouseenter and mouseleave handlers
566 var withinElement = function( event ) {
567 // Check if mouse(over|out) are still within the same parent element
568 var parent = event.relatedTarget;
570 // Traverse up the tree
571 while ( parent && parent !== this ) {
572 // Firefox sometimes assigns relatedTarget a XUL element
573 // which we cannot access the parentNode property of
575 parent = parent.parentNode;
577 // assuming we've left the element since we most likely mousedover a xul element
583 if ( parent !== this ) {
584 // set the correct event type
585 event.type = event.data;
587 // handle event if we actually just moused on to a non sub-element
588 jQuery.event.handle.apply( this, arguments );
593 // In case of event delegation, we only need to rename the event.type,
594 // liveHandler will take care of the rest.
595 delegate = function( event ) {
596 event.type = event.data;
597 jQuery.event.handle.apply( this, arguments );
600 // Create mouseenter and mouseleave events
602 mouseenter: "mouseover",
603 mouseleave: "mouseout"
604 }, function( orig, fix ) {
605 jQuery.event.special[ orig ] = {
606 setup: function( data ) {
607 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
609 teardown: function( data ) {
610 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
616 if ( !jQuery.support.submitBubbles ) {
618 jQuery.event.special.submit = {
619 setup: function( data, namespaces, fn ) {
620 if ( this.nodeName.toLowerCase() !== "form" ) {
621 jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
622 var elem = e.target, type = elem.type;
624 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
625 return trigger( "submit", this, arguments );
629 jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
630 var elem = e.target, type = elem.type;
632 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
633 return trigger( "submit", this, arguments );
642 remove: function( namespaces, fn ) {
643 jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
644 jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
650 // change delegation, happens here so we have bind.
651 if ( !jQuery.support.changeBubbles ) {
653 var formElems = /textarea|input|select/i;
655 function getVal( elem ) {
656 var type = elem.type, val = elem.value;
658 if ( type === "radio" || type === "checkbox" ) {
661 } else if ( type === "select-multiple" ) {
662 val = elem.selectedIndex > -1 ?
663 jQuery.map( elem.options, function( elem ) {
664 return elem.selected;
668 } else if ( elem.nodeName.toLowerCase() === "select" ) {
669 val = elem.selectedIndex;
675 function testChange( e ) {
676 var elem = e.target, data, val;
678 if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
682 data = jQuery.data( elem, "_change_data" );
685 // the current data will be also retrieved by beforeactivate
686 if ( e.type !== "focusout" || elem.type !== "radio" ) {
687 jQuery.data( elem, "_change_data", val );
690 if ( data === undefined || val === data ) {
694 if ( data != null || val ) {
696 return jQuery.event.trigger( e, arguments[1], elem );
700 jQuery.event.special.change = {
702 focusout: testChange,
704 click: function( e ) {
705 var elem = e.target, type = elem.type;
707 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
708 return testChange.call( this, e );
712 // Change has to be called before submit
713 // Keydown will be called before keypress, which is used in submit-event delegation
714 keydown: function( e ) {
715 var elem = e.target, type = elem.type;
717 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
718 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
719 type === "select-multiple" ) {
720 return testChange.call( this, e );
724 // Beforeactivate happens also before the previous element is blurred
725 // with this event you can't trigger a change event, but you can store
726 // information/focus[in] is not needed anymore
727 beforeactivate: function( e ) {
730 if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
731 jQuery.data( elem, "_change_data", getVal(elem) );
735 setup: function( data, namespaces, fn ) {
736 for ( var type in changeFilters ) {
737 jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
740 return formElems.test( this.nodeName );
742 remove: function( namespaces, fn ) {
743 for ( var type in changeFilters ) {
744 jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
747 return formElems.test( this.nodeName );
751 var changeFilters = jQuery.event.special.change.filters;
755 function trigger( type, elem, args ) {
757 return jQuery.event.handle.apply( elem, args );
760 // Create "bubbling" focus and blur events
761 if ( document.addEventListener ) {
762 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
763 jQuery.event.special[ fix ] = {
765 this.addEventListener( orig, handler, true );
767 teardown: function() {
768 this.removeEventListener( orig, handler, true );
772 function handler( e ) {
773 e = jQuery.event.fix( e );
775 return jQuery.event.handle.call( this, e );
780 jQuery.each(["bind", "one"], function( i, name ) {
781 jQuery.fn[ name ] = function( type, data, fn ) {
782 // Handle object literals
783 if ( typeof type === "object" ) {
784 for ( var key in type ) {
785 this[ name ](key, data, type[key], fn);
790 if ( jQuery.isFunction( data ) ) {
795 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
796 jQuery( this ).unbind( event, handler );
797 return fn.apply( this, arguments );
800 return type === "unload" && name !== "one" ?
801 this.one( type, data, fn ) :
802 this.each(function() {
803 jQuery.event.add( this, type, handler, data );
809 unbind: function( type, fn ) {
810 // Handle object literals
811 if ( typeof type === "object" && !type.preventDefault ) {
812 for ( var key in type ) {
813 this.unbind(key, type[key]);
818 return this.each(function() {
819 jQuery.event.remove( this, type, fn );
822 trigger: function( type, data ) {
823 return this.each(function() {
824 jQuery.event.trigger( type, data, this );
828 triggerHandler: function( type, data ) {
830 var event = jQuery.Event( type );
831 event.preventDefault();
832 event.stopPropagation();
833 jQuery.event.trigger( event, data, this[0] );
838 toggle: function( fn ) {
839 // Save reference to arguments for access in closure
840 var args = arguments, i = 1;
842 // link all the functions, so any of them can unbind this click handler
843 while ( i < args.length ) {
844 jQuery.proxy( fn, args[ i++ ] );
847 return this.click( jQuery.proxy( fn, function( event ) {
848 // Figure out which function to execute
849 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
850 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
852 // Make sure that clicks stop
853 event.preventDefault();
855 // and execute the function
856 return args[ lastToggle ].apply( this, arguments ) || false;
860 hover: function( fnOver, fnOut ) {
861 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
865 jQuery.each(["live", "die"], function( i, name ) {
866 jQuery.fn[ name ] = function( types, data, fn ) {
869 if ( jQuery.isFunction( data ) ) {
874 types = (types || "").split( /\s+/ );
876 while ( (type = types[ i++ ]) != null ) {
877 type = type === "focus" ? "focusin" : // focus --> focusin
878 type === "blur" ? "focusout" : // blur --> focusout
879 type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
882 if ( name === "live" ) {
884 jQuery( this.context ).bind( liveConvert( type, this.selector ), {
885 data: data, selector: this.selector, live: type
889 // unbind live handler
890 jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
898 function liveHandler( event ) {
899 var stop, elems = [], selectors = [], args = arguments,
900 related, match, fn, elem, j, i, l, data,
901 live = jQuery.extend({}, jQuery.data( this, "events" ).live);
903 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
904 if ( event.button && event.type === "click" ) {
910 if ( fn.live === event.type ||
911 fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {
914 if ( !(data.beforeFilter && data.beforeFilter[event.type] &&
915 !data.beforeFilter[event.type](event)) ) {
916 selectors.push( fn.selector );
923 match = jQuery( event.target ).closest( selectors, event.currentTarget );
925 for ( i = 0, l = match.length; i < l; i++ ) {
928 elem = match[i].elem;
931 if ( match[i].selector === fn.selector ) {
932 // Those two events require additional checking
933 if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
934 related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
937 if ( !related || related !== elem ) {
938 elems.push({ elem: elem, fn: fn });
944 for ( i = 0, l = elems.length; i < l; i++ ) {
946 event.currentTarget = match.elem;
947 event.data = match.fn.data;
948 if ( match.fn.apply( match.elem, args ) === false ) {
957 function liveConvert( type, selector ) {
958 return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
961 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
962 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
963 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
965 // Handle event binding
966 jQuery.fn[ name ] = function( fn ) {
967 return fn ? this.bind( name, fn ) : this.trigger( name );
970 if ( jQuery.attrFn ) {
971 jQuery.attrFn[ name ] = true;
975 // Prevent memory leaks in IE
976 // Window isn't included so as not to unbind existing unload events
978 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
979 if ( window.attachEvent && !window.addEventListener ) {
980 window.attachEvent("onunload", function() {
981 for ( var id in jQuery.cache ) {
982 if ( jQuery.cache[ id ].handle ) {
983 // Try/Catch is to handle iframes being unloaded, see #4280
985 jQuery.event.remove( jQuery.cache[ id ].handle.elem );