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 // Init the element's event structure
33 var elemData = jQuery.data( elem );
35 // If no elemData is found then we must be trying to bind to one of the
36 // banned noData elements
41 var events = elemData.events = elemData.events || {},
42 eventHandle = elemData.handle, eventHandle;
45 elemData.handle = eventHandle = function() {
46 // Handle the second event of a trigger and when
47 // an event is called after a page has unloaded
48 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
49 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
54 // Add elem as a property of the handle function
55 // This is to prevent a memory leak with non-native events in IE.
56 eventHandle.elem = elem;
58 // Handle multiple events separated by a space
59 // jQuery(...).bind("mouseover mouseout", fn);
60 types = types.split(" ");
62 var type, i = 0, namespaces;
64 while ( (type = types[ i++ ]) ) {
72 // Namespaced event handlers
73 if ( type.indexOf(".") > -1 ) {
74 namespaces = type.split(".");
75 type = namespaces.shift();
76 handleObj.namespace = namespaces.slice(0).sort().join(".");
82 handleObj.type = type;
84 // Get the current list of functions bound to this event
85 var handlers = events[ type ],
86 special = jQuery.event.special[ type ] || {};
88 // Init the event handler queue
90 handlers = events[ type ] = [];
92 // Check for a special event handler
93 // Only use addEventListener/attachEvent if the special
94 // events handler returns false
95 if ( !special.setup || special.setup.call( elem, data, namespaces, handler ) === false ) {
96 // Bind the global event handler to the element
97 if ( elem.addEventListener ) {
98 elem.addEventListener( type, eventHandle, false );
100 } else if ( elem.attachEvent ) {
101 elem.attachEvent( "on" + type, eventHandle );
107 special.add.call( elem, handleObj );
110 // Add the function to the element's handler list
111 handlers.push( handleObj );
113 // Keep track of which events have been used, for global triggering
114 jQuery.event.global[ type ] = true;
117 // Nullify elem to prevent memory leaks in IE
123 // Detach an event or set of events from an element
124 remove: function( elem, types, handler, pos ) {
125 // don't do events on text and comment nodes
126 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
130 var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
131 elemData = jQuery.data( elem ),
132 events = elemData && elemData.events;
134 if ( !elemData || !events ) {
138 // types is actually an event object here
139 if ( types && types.type ) {
140 handler = types.handler;
144 // Unbind all events for the element
145 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
148 for ( type in events ) {
149 jQuery.event.remove( elem, type + types );
155 // Handle multiple events separated by a space
156 // jQuery(...).unbind("mouseover mouseout", fn);
157 types = types.split(" ");
159 while ( (type = types[ i++ ]) ) {
162 all = type.indexOf(".") < 0;
166 // Namespaced event handlers
167 namespaces = type.split(".");
168 type = namespaces.shift();
170 namespace = new RegExp("(^|\\.)" +
171 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
174 eventType = events[ type ];
181 for ( var j = 0; j < eventType.length; j++ ) {
182 handleObj = eventType[ j ];
184 if ( all || namespace.test( handleObj.namespace ) ) {
185 jQuery.event.remove( elem, origType, handleObj.handler, j );
186 eventType.splice( j--, 1 );
193 special = jQuery.event.special[ type ] || {};
195 for ( var j = pos || 0; j < eventType.length; j++ ) {
196 handleObj = eventType[ j ];
198 if ( handler.guid === handleObj.guid ) {
199 // remove the given handler for the given type
200 if ( all || namespace.test( handleObj.namespace ) ) {
201 fn = handleObj.handler;
204 eventType.splice( j--, 1 );
207 if ( special.remove ) {
208 special.remove.call( elem, namespaces, handleObj );
218 // remove generic event handler if no more handlers exist
219 if ( jQuery.isEmptyObject( events[ type ] ) ) {
220 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
221 removeEvent( elem, type, elemData.handle );
225 delete events[ type ];
229 // Remove the expando if it's no longer used
230 if ( jQuery.isEmptyObject( events ) ) {
231 var handle = elemData.handle;
236 delete elemData.events;
237 delete elemData.handle;
239 if ( jQuery.isEmptyObject( elemData ) ) {
240 jQuery.removeData( elem );
245 // bubbling is internal
246 trigger: function( event, data, elem /*, bubbling */ ) {
247 // Event object or event type
248 var type = event.type || event,
249 bubbling = arguments[3];
252 event = typeof event === "object" ?
253 // jQuery.Event object
254 event[expando] ? event :
256 jQuery.extend( jQuery.Event(type), event ) :
257 // Just the event type (string)
260 if ( type.indexOf("!") >= 0 ) {
261 event.type = type = type.slice(0, -1);
262 event.exclusive = true;
265 // Handle a global trigger
267 // Don't bubble custom events when global (to avoid too much overhead)
268 event.stopPropagation();
270 // Only trigger if we've ever bound an event for it
271 if ( jQuery.event.global[ type ] ) {
272 jQuery.each( jQuery.cache, function() {
273 if ( this.events && this.events[type] ) {
274 jQuery.event.trigger( event, data, this.handle.elem );
280 // Handle triggering a single element
282 // don't do events on text and comment nodes
283 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
287 // Clean up in case it is reused
288 event.result = undefined;
291 // Clone the incoming data, if any
292 data = jQuery.makeArray( data );
293 data.unshift( event );
296 event.currentTarget = elem;
298 // Trigger the event, it is assumed that "handle" is a function
299 var handle = jQuery.data( elem, "handle" );
301 handle.apply( elem, data );
304 var parent = elem.parentNode || elem.ownerDocument;
306 // Trigger an inline bound script
308 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
309 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
310 event.result = false;
314 // prevent IE from throwing an error for some elements with some event types, see #3533
317 if ( !event.isPropagationStopped() && parent ) {
318 jQuery.event.trigger( event, data, parent, true );
320 } else if ( !event.isDefaultPrevented() ) {
321 var target = event.target, old,
322 isClick = jQuery.nodeName(target, "a") && type === "click",
323 special = jQuery.event.special[ type ] || {};
325 if ( (!special._default || special._default.call( elem, event ) === false) &&
326 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
329 if ( target[ type ] ) {
330 // Make sure that we don't accidentally re-trigger the onFOO events
331 old = target[ "on" + type ];
334 target[ "on" + type ] = null;
337 jQuery.event.triggered = true;
341 // prevent IE from throwing an error for some elements with some event types, see #3533
345 target[ "on" + type ] = old;
348 jQuery.event.triggered = false;
353 handle: function( event ) {
354 var all, handlers, namespaces, namespace, events;
356 event = arguments[0] = jQuery.event.fix( event || window.event );
357 event.currentTarget = this;
359 // Namespaced event handlers
360 all = event.type.indexOf(".") < 0;
363 namespaces = event.type.split(".");
364 event.type = namespaces.shift();
365 namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
368 var events = jQuery.data(this, "events"), handlers = events[ event.type ];
370 if ( events && handlers ) {
371 // Clone the handlers to prevent manipulation
372 handlers = handlers.slice(0);
374 for ( var j = 0, l = handlers.length; j < l; j++ ) {
375 var handleObj = handlers[ j ];
377 // Filter the functions by class
378 if ( (all && !event.exclusive) || namespace.test( handleObj.namespace ) ) {
379 // Pass in a reference to the handler function itself
380 // So that we can later remove it
381 event.handler = handleObj.handler;
382 event.data = handleObj.data;
384 var ret = handleObj.handler.apply( this, arguments );
386 if ( ret !== undefined ) {
388 if ( ret === false ) {
389 event.preventDefault();
390 event.stopPropagation();
394 if ( event.isImmediatePropagationStopped() ) {
404 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(" "),
406 fix: function( event ) {
407 if ( event[ expando ] ) {
411 // store a copy of the original event object
412 // and "clone" to set read-only properties
413 var originalEvent = event;
414 event = jQuery.Event( originalEvent );
416 for ( var i = this.props.length, prop; i; ) {
417 prop = this.props[ --i ];
418 event[ prop ] = originalEvent[ prop ];
421 // Fix target property, if necessary
422 if ( !event.target ) {
423 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
426 // check if target is a textnode (safari)
427 if ( event.target.nodeType === 3 ) {
428 event.target = event.target.parentNode;
431 // Add relatedTarget, if necessary
432 if ( !event.relatedTarget && event.fromElement ) {
433 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
436 // Calculate pageX/Y if missing and clientX/Y available
437 if ( event.pageX == null && event.clientX != null ) {
438 var doc = document.documentElement, body = document.body;
439 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
440 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
443 // Add which for key events
444 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
445 event.which = event.charCode || event.keyCode;
448 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
449 if ( !event.metaKey && event.ctrlKey ) {
450 event.metaKey = event.ctrlKey;
453 // Add which for click: 1 === left; 2 === middle; 3 === right
454 // Note: button is not normalized, so don't use it
455 if ( !event.which && event.button !== undefined ) {
456 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
462 // Deprecated, use jQuery.guid instead
465 // Deprecated, use jQuery.proxy instead
470 // Make sure the ready event is setup
471 setup: jQuery.bindReady,
472 teardown: jQuery.noop
476 add: function( proxy, data, namespaces, live ) {
477 jQuery.extend( proxy, data || {} );
479 proxy.guid += data.selector + data.live;
480 data.liveProxy = proxy;
482 jQuery.event.add( this, data.live, liveHandler, data );
486 remove: function( namespaces ) {
487 if ( namespaces.length ) {
488 var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
490 jQuery.each( (jQuery.data(this, "events").live || {}), function() {
491 if ( name.test(this.type) ) {
497 jQuery.event.remove( this, namespaces[0], liveHandler );
504 setup: function( data, namespaces, fn ) {
505 // We only want to do this special case on windows
506 if ( this.setInterval ) {
507 this.onbeforeunload = fn;
512 teardown: function( namespaces, fn ) {
513 if ( this.onbeforeunload === fn ) {
514 this.onbeforeunload = null;
521 var removeEvent = document.removeEventListener ?
522 function( elem, type, handle ) {
523 elem.removeEventListener( type, handle, false );
525 function( elem, type, handle ) {
526 elem.detachEvent( "on" + type, handle );
529 jQuery.Event = function( src ) {
530 // Allow instantiation without the 'new' keyword
531 if ( !this.preventDefault ) {
532 return new jQuery.Event( src );
536 if ( src && src.type ) {
537 this.originalEvent = src;
538 this.type = src.type;
544 // timeStamp is buggy for some events on Firefox(#3843)
545 // So we won't rely on the native value
546 this.timeStamp = now();
549 this[ expando ] = true;
552 function returnFalse() {
555 function returnTrue() {
559 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
560 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
561 jQuery.Event.prototype = {
562 preventDefault: function() {
563 this.isDefaultPrevented = returnTrue;
565 var e = this.originalEvent;
570 // if preventDefault exists run it on the original event
571 if ( e.preventDefault ) {
574 // otherwise set the returnValue property of the original event to false (IE)
575 e.returnValue = false;
577 stopPropagation: function() {
578 this.isPropagationStopped = returnTrue;
580 var e = this.originalEvent;
584 // if stopPropagation exists run it on the original event
585 if ( e.stopPropagation ) {
588 // otherwise set the cancelBubble property of the original event to true (IE)
589 e.cancelBubble = true;
591 stopImmediatePropagation: function() {
592 this.isImmediatePropagationStopped = returnTrue;
593 this.stopPropagation();
595 isDefaultPrevented: returnFalse,
596 isPropagationStopped: returnFalse,
597 isImmediatePropagationStopped: returnFalse
600 // Checks if an event happened on an element within another element
601 // Used in jQuery.event.special.mouseenter and mouseleave handlers
602 var withinElement = function( event ) {
603 // Check if mouse(over|out) are still within the same parent element
604 var parent = event.relatedTarget;
606 // Traverse up the tree
607 while ( parent && parent !== this ) {
608 // Firefox sometimes assigns relatedTarget a XUL element
609 // which we cannot access the parentNode property of
611 parent = parent.parentNode;
613 // assuming we've left the element since we most likely mousedover a xul element
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 );
629 // In case of event delegation, we only need to rename the event.type,
630 // liveHandler will take care of the rest.
631 delegate = function( event ) {
632 event.type = event.data;
633 jQuery.event.handle.apply( this, arguments );
636 // Create mouseenter and mouseleave events
638 mouseenter: "mouseover",
639 mouseleave: "mouseout"
640 }, function( orig, fix ) {
641 jQuery.event.special[ orig ] = {
642 setup: function( data ) {
643 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
645 teardown: function( data ) {
646 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
652 if ( !jQuery.support.submitBubbles ) {
654 jQuery.event.special.submit = {
655 setup: function( data, namespaces, fn ) {
656 if ( this.nodeName.toLowerCase() !== "form" ) {
657 jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
658 var elem = e.target, type = elem.type;
660 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
661 return trigger( "submit", this, arguments );
665 jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
666 var elem = e.target, type = elem.type;
668 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
669 return trigger( "submit", this, arguments );
678 remove: function( namespaces, fn ) {
679 jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
680 jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
686 // change delegation, happens here so we have bind.
687 if ( !jQuery.support.changeBubbles ) {
689 var formElems = /textarea|input|select/i;
691 function getVal( elem ) {
692 var type = elem.type, val = elem.value;
694 if ( type === "radio" || type === "checkbox" ) {
697 } else if ( type === "select-multiple" ) {
698 val = elem.selectedIndex > -1 ?
699 jQuery.map( elem.options, function( elem ) {
700 return elem.selected;
704 } else if ( elem.nodeName.toLowerCase() === "select" ) {
705 val = elem.selectedIndex;
711 function testChange( e ) {
712 var elem = e.target, data, val;
714 if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
718 data = jQuery.data( elem, "_change_data" );
721 // the current data will be also retrieved by beforeactivate
722 if ( e.type !== "focusout" || elem.type !== "radio" ) {
723 jQuery.data( elem, "_change_data", val );
726 if ( data === undefined || val === data ) {
730 if ( data != null || val ) {
732 return jQuery.event.trigger( e, arguments[1], elem );
736 jQuery.event.special.change = {
738 focusout: testChange,
740 click: function( e ) {
741 var elem = e.target, type = elem.type;
743 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
744 return testChange.call( this, e );
748 // Change has to be called before submit
749 // Keydown will be called before keypress, which is used in submit-event delegation
750 keydown: function( e ) {
751 var elem = e.target, type = elem.type;
753 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
754 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
755 type === "select-multiple" ) {
756 return testChange.call( this, e );
760 // Beforeactivate happens also before the previous element is blurred
761 // with this event you can't trigger a change event, but you can store
762 // information/focus[in] is not needed anymore
763 beforeactivate: function( e ) {
765 jQuery.data( elem, "_change_data", getVal(elem) );
768 setup: function( data, namespaces, fn ) {
769 for ( var type in changeFilters ) {
770 jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
773 return formElems.test( this.nodeName );
775 remove: function( namespaces, fn ) {
776 for ( var type in changeFilters ) {
777 jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
780 return formElems.test( this.nodeName );
784 var changeFilters = jQuery.event.special.change.filters;
788 function trigger( type, elem, args ) {
790 return jQuery.event.handle.apply( elem, args );
793 // Create "bubbling" focus and blur events
794 if ( document.addEventListener ) {
795 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
796 jQuery.event.special[ fix ] = {
798 this.addEventListener( orig, handler, true );
800 teardown: function() {
801 this.removeEventListener( orig, handler, true );
805 function handler( e ) {
806 e = jQuery.event.fix( e );
808 return jQuery.event.handle.call( this, e );
813 jQuery.each(["bind", "one"], function( i, name ) {
814 jQuery.fn[ name ] = function( type, data, fn ) {
815 // Handle object literals
816 if ( typeof type === "object" ) {
817 for ( var key in type ) {
818 this[ name ](key, data, type[key], fn);
823 if ( jQuery.isFunction( data ) ) {
828 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
829 jQuery( this ).unbind( event, handler );
830 return fn.apply( this, arguments );
833 if ( type === "unload" && name !== "one" ) {
834 this.one( type, data, fn );
837 for ( var i = 0, l = this.length; i < l; i++ ) {
838 jQuery.event.add( this[i], type, handler, data );
847 unbind: function( type, fn ) {
848 // Handle object literals
849 if ( typeof type === "object" && !type.preventDefault ) {
850 for ( var key in type ) {
851 this.unbind(key, type[key]);
855 for ( var i = 0, l = this.length; i < l; i++ ) {
856 jQuery.event.remove( this[i], type, fn );
863 delegate: function( selector, types, data, fn ) {
864 return this.live( types, data, fn, selector );
867 undelegate: function( selector, types, fn ) {
868 if ( arguments.length === 0 ) {
869 return this.unbind( "live" );
872 return this.die( types, null, fn, selector );
876 trigger: function( type, data ) {
877 return this.each(function() {
878 jQuery.event.trigger( type, data, this );
882 triggerHandler: function( type, data ) {
884 var event = jQuery.Event( type );
885 event.preventDefault();
886 event.stopPropagation();
887 jQuery.event.trigger( event, data, this[0] );
892 toggle: function( fn ) {
893 // Save reference to arguments for access in closure
894 var args = arguments, i = 1;
896 // link all the functions, so any of them can unbind this click handler
897 while ( i < args.length ) {
898 jQuery.proxy( fn, args[ i++ ] );
901 return this.click( jQuery.proxy( fn, function( event ) {
902 // Figure out which function to execute
903 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
904 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
906 // Make sure that clicks stop
907 event.preventDefault();
909 // and execute the function
910 return args[ lastToggle ].apply( this, arguments ) || false;
914 hover: function( fnOver, fnOut ) {
915 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
919 jQuery.each(["live", "die"], function( i, name ) {
920 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
922 selector = origSelector || this.selector,
923 context = origSelector ? this : jQuery( this.context );
925 if ( jQuery.isFunction( data ) ) {
930 types = (types || "").split( /\s+/ );
932 while ( (type = types[ i++ ]) != null ) {
933 type = type === "focus" ? "focusin" : // focus --> focusin
934 type === "blur" ? "focusout" : // blur --> focusout
935 type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
938 if ( name === "live" ) {
940 context.bind( liveConvert( type, selector ), {
941 data: data, selector: selector, live: type
945 // unbind live handler
946 context.unbind( liveConvert( type, selector ), fn ? { guid: fn.guid + selector + type } : null );
954 function liveHandler( event ) {
955 var stop, elems = [], selectors = [], args = arguments,
956 related, match, fn, elem, j, i, l, data,
957 live = jQuery.extend({}, jQuery.data( this, "events" ).live);
959 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
960 if ( event.button && event.type === "click" ) {
966 if ( fn.live === event.type ||
967 fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {
970 if ( !(data.beforeFilter && data.beforeFilter[event.type] &&
971 !data.beforeFilter[event.type](event)) ) {
972 selectors.push( fn.selector );
979 match = jQuery( event.target ).closest( selectors, event.currentTarget );
981 for ( i = 0, l = match.length; i < l; i++ ) {
984 elem = match[i].elem;
987 if ( match[i].selector === fn.selector ) {
988 // Those two events require additional checking
989 if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
990 related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
993 if ( !related || related !== elem ) {
994 elems.push({ elem: elem, fn: fn });
1000 for ( i = 0, l = elems.length; i < l; i++ ) {
1002 event.currentTarget = match.elem;
1003 event.data = match.fn.data;
1004 if ( match.fn.apply( match.elem, args ) === false ) {
1013 function liveConvert( type, selector ) {
1014 return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
1017 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1018 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1019 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1021 // Handle event binding
1022 jQuery.fn[ name ] = function( fn ) {
1023 return fn ? this.bind( name, fn ) : this.trigger( name );
1026 if ( jQuery.attrFn ) {
1027 jQuery.attrFn[ name ] = true;
1031 // Prevent memory leaks in IE
1032 // Window isn't included so as not to unbind existing unload events
1034 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
1035 if ( window.attachEvent && !window.addEventListener ) {
1036 window.attachEvent("onunload", function() {
1037 for ( var id in jQuery.cache ) {
1038 if ( jQuery.cache[ id ].handle ) {
1039 // Try/Catch is to handle iframes being unloaded, see #4280
1041 jQuery.event.remove( jQuery.cache[ id ].handle.elem );