3 var rnamespaces = /\.(.*)$/,
4 rformElems = /^(?:textarea|input|select)$/i,
7 rescape = /[^\w\s.|`]/g,
8 fcleanup = function( nm ) {
9 return nm.replace(rescape, "\\$&");
11 focusCounts = { focusin: 0, focusout: 0 };
14 * A number of helper functions used for managing events.
15 * Many of the ideas behind this code originated from
16 * Dean Edwards' addEvent library.
20 // Bind an event to an element
21 // Original by Dean Edwards
22 add: function( elem, types, handler, data ) {
23 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
27 // For whatever reason, IE has trouble passing the window object
28 // around, causing it to be cloned in the process
29 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
33 if ( handler === false ) {
34 handler = returnFalse;
35 } else if ( !handler ) {
36 // Fixes bug #7229. Fix recommended by jdalton
40 var handleObjIn, handleObj;
42 if ( handler.handler ) {
43 handleObjIn = handler;
44 handler = handleObjIn.handler;
47 // Make sure that the function being executed has a unique ID
48 if ( !handler.guid ) {
49 handler.guid = jQuery.guid++;
52 // Init the element's event structure
53 var elemData = jQuery.data( elem );
55 // If no elemData is found then we must be trying to bind to one of the
56 // banned noData elements
61 // Use a key less likely to result in collisions for plain JS objects.
63 var eventKey = elem.nodeType ? "events" : "__events__",
64 events = elemData[ eventKey ],
65 eventHandle = elemData.handle;
67 if ( typeof events === "function" ) {
68 // On plain objects events is a fn that holds the the data
69 // which prevents this data from being JSON serialized
70 // the function does not need to be called, it just contains the data
71 eventHandle = events.handle;
72 events = events.events;
74 } else if ( !events ) {
75 if ( !elem.nodeType ) {
76 // On plain objects, create a fn that acts as the holder
77 // of the values to avoid JSON serialization of event data
78 elemData[ eventKey ] = elemData = function(){};
81 elemData.events = events = {};
85 elemData.handle = eventHandle = function() {
86 // Handle the second event of a trigger and when
87 // an event is called after a page has unloaded
88 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
89 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
94 // Add elem as a property of the handle function
95 // This is to prevent a memory leak with non-native events in IE.
96 eventHandle.elem = elem;
98 // Handle multiple events separated by a space
99 // jQuery(...).bind("mouseover mouseout", fn);
100 types = types.split(" ");
102 var type, i = 0, namespaces;
104 while ( (type = types[ i++ ]) ) {
105 handleObj = handleObjIn ?
106 jQuery.extend({}, handleObjIn) :
107 { handler: handler, data: data };
109 // Namespaced event handlers
110 if ( type.indexOf(".") > -1 ) {
111 namespaces = type.split(".");
112 type = namespaces.shift();
113 handleObj.namespace = namespaces.slice(0).sort().join(".");
117 handleObj.namespace = "";
120 handleObj.type = type;
121 if ( !handleObj.guid ) {
122 handleObj.guid = handler.guid;
125 // Get the current list of functions bound to this event
126 var handlers = events[ type ],
127 special = jQuery.event.special[ type ] || {};
129 // Init the event handler queue
131 handlers = events[ type ] = [];
133 // Check for a special event handler
134 // Only use addEventListener/attachEvent if the special
135 // events handler returns false
136 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
137 // Bind the global event handler to the element
138 if ( elem.addEventListener ) {
139 elem.addEventListener( type, eventHandle, false );
141 } else if ( elem.attachEvent ) {
142 elem.attachEvent( "on" + type, eventHandle );
148 special.add.call( elem, handleObj );
150 if ( !handleObj.handler.guid ) {
151 handleObj.handler.guid = handler.guid;
155 // Add the function to the element's handler list
156 handlers.push( handleObj );
158 // Keep track of which events have been used, for global triggering
159 jQuery.event.global[ type ] = true;
162 // Nullify elem to prevent memory leaks in IE
168 // Detach an event or set of events from an element
169 remove: function( elem, types, handler, pos ) {
170 // don't do events on text and comment nodes
171 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
175 if ( handler === false ) {
176 handler = returnFalse;
179 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
180 eventKey = elem.nodeType ? "events" : "__events__",
181 elemData = jQuery.data( elem ),
182 events = elemData && elemData[ eventKey ];
184 if ( !elemData || !events ) {
188 if ( typeof events === "function" ) {
190 events = events.events;
193 // types is actually an event object here
194 if ( types && types.type ) {
195 handler = types.handler;
199 // Unbind all events for the element
200 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
203 for ( type in events ) {
204 jQuery.event.remove( elem, type + types );
210 // Handle multiple events separated by a space
211 // jQuery(...).unbind("mouseover mouseout", fn);
212 types = types.split(" ");
214 while ( (type = types[ i++ ]) ) {
217 all = type.indexOf(".") < 0;
221 // Namespaced event handlers
222 namespaces = type.split(".");
223 type = namespaces.shift();
225 namespace = new RegExp("(^|\\.)" +
226 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
229 eventType = events[ type ];
236 for ( j = 0; j < eventType.length; j++ ) {
237 handleObj = eventType[ j ];
239 if ( all || namespace.test( handleObj.namespace ) ) {
240 jQuery.event.remove( elem, origType, handleObj.handler, j );
241 eventType.splice( j--, 1 );
248 special = jQuery.event.special[ type ] || {};
250 for ( j = pos || 0; j < eventType.length; j++ ) {
251 handleObj = eventType[ j ];
253 if ( handler.guid === handleObj.guid ) {
254 // remove the given handler for the given type
255 if ( all || namespace.test( handleObj.namespace ) ) {
257 eventType.splice( j--, 1 );
260 if ( special.remove ) {
261 special.remove.call( elem, handleObj );
271 // remove generic event handler if no more handlers exist
272 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
273 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
274 jQuery.removeEvent( elem, type, elemData.handle );
278 delete events[ type ];
282 // Remove the expando if it's no longer used
283 if ( jQuery.isEmptyObject( events ) ) {
284 var handle = elemData.handle;
289 delete elemData.events;
290 delete elemData.handle;
292 if ( typeof elemData === "function" ) {
293 jQuery.removeData( elem, eventKey );
295 } else if ( jQuery.isEmptyObject( elemData ) ) {
296 jQuery.removeData( elem );
301 // bubbling is internal
302 trigger: function( event, data, elem /*, bubbling */ ) {
303 // Event object or event type
304 var type = event.type || event,
305 bubbling = arguments[3];
308 event = typeof event === "object" ?
309 // jQuery.Event object
310 event[ jQuery.expando ] ? event :
312 jQuery.extend( jQuery.Event(type), event ) :
313 // Just the event type (string)
316 if ( type.indexOf("!") >= 0 ) {
317 event.type = type = type.slice(0, -1);
318 event.exclusive = true;
321 // Handle a global trigger
323 // Don't bubble custom events when global (to avoid too much overhead)
324 event.stopPropagation();
326 // Only trigger if we've ever bound an event for it
327 if ( jQuery.event.global[ type ] ) {
328 jQuery.each( jQuery.cache, function() {
329 if ( this.events && this.events[type] ) {
330 jQuery.event.trigger( event, data, this.handle.elem );
336 // Handle triggering a single element
338 // don't do events on text and comment nodes
339 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
343 // Clean up in case it is reused
344 event.result = undefined;
347 // Clone the incoming data, if any
348 data = jQuery.makeArray( data );
349 data.unshift( event );
352 event.currentTarget = elem;
354 // Trigger the event, it is assumed that "handle" is a function
355 var handle = elem.nodeType ?
356 jQuery.data( elem, "handle" ) :
357 (jQuery.data( elem, "__events__" ) || {}).handle;
360 handle.apply( elem, data );
363 var parent = elem.parentNode || elem.ownerDocument;
365 // Trigger an inline bound script
367 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
368 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
369 event.result = false;
370 event.preventDefault();
374 // prevent IE from throwing an error for some elements with some event types, see #3533
375 } catch (inlineError) {}
377 if ( !event.isPropagationStopped() && parent ) {
378 jQuery.event.trigger( event, data, parent, true );
380 } else if ( !event.isDefaultPrevented() ) {
381 var target = event.target, old, targetType = type.replace(rnamespaces, ""),
382 isClick = jQuery.nodeName(target, "a") && targetType === "click",
383 special = jQuery.event.special[ targetType ] || {};
385 if ( (!special._default || special._default.call( elem, event ) === false) &&
386 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
389 if ( target[ targetType ] ) {
390 // Make sure that we don't accidentally re-trigger the onFOO events
391 old = target[ "on" + targetType ];
394 target[ "on" + targetType ] = null;
397 jQuery.event.triggered = true;
398 target[ targetType ]();
401 // prevent IE from throwing an error for some elements with some event types, see #3533
402 } catch (triggerError) {}
405 target[ "on" + targetType ] = old;
408 jQuery.event.triggered = false;
413 handle: function( event ) {
414 var all, handlers, namespaces, namespace_sort = [], namespace_re, events, args = jQuery.makeArray( arguments );
416 event = args[0] = jQuery.event.fix( event || window.event );
417 event.currentTarget = this;
419 // Namespaced event handlers
420 all = event.type.indexOf(".") < 0 && !event.exclusive;
423 namespaces = event.type.split(".");
424 event.type = namespaces.shift();
425 namespace_sort = namespaces.slice(0).sort();
426 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
429 event.namespace = event.namespace || namespace_sort.join(".");
431 events = jQuery.data(this, this.nodeType ? "events" : "__events__");
433 if ( typeof events === "function" ) {
434 events = events.events;
437 handlers = (events || {})[ event.type ];
439 if ( events && handlers ) {
440 // Clone the handlers to prevent manipulation
441 handlers = handlers.slice(0);
443 for ( var j = 0, l = handlers.length; j < l; j++ ) {
444 var handleObj = handlers[ j ];
446 // Filter the functions by class
447 if ( all || namespace_re.test( handleObj.namespace ) ) {
448 // Pass in a reference to the handler function itself
449 // So that we can later remove it
450 event.handler = handleObj.handler;
451 event.data = handleObj.data;
452 event.handleObj = handleObj;
454 var ret = handleObj.handler.apply( this, args );
456 if ( ret !== undefined ) {
458 if ( ret === false ) {
459 event.preventDefault();
460 event.stopPropagation();
464 if ( event.isImmediatePropagationStopped() ) {
474 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
476 fix: function( event ) {
477 if ( event[ jQuery.expando ] ) {
481 // store a copy of the original event object
482 // and "clone" to set read-only properties
483 var originalEvent = event;
484 event = jQuery.Event( originalEvent );
486 for ( var i = this.props.length, prop; i; ) {
487 prop = this.props[ --i ];
488 event[ prop ] = originalEvent[ prop ];
491 // Fix target property, if necessary
492 if ( !event.target ) {
493 // Fixes #1925 where srcElement might not be defined either
494 event.target = event.srcElement || document;
497 // check if target is a textnode (safari)
498 if ( event.target.nodeType === 3 ) {
499 event.target = event.target.parentNode;
502 // Add relatedTarget, if necessary
503 if ( !event.relatedTarget && event.fromElement ) {
504 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
507 // Calculate pageX/Y if missing and clientX/Y available
508 if ( event.pageX == null && event.clientX != null ) {
509 var doc = document.documentElement, body = document.body;
510 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
511 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
514 // Add which for key events
515 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
516 event.which = event.charCode != null ? event.charCode : event.keyCode;
519 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
520 if ( !event.metaKey && event.ctrlKey ) {
521 event.metaKey = event.ctrlKey;
524 // Add which for click: 1 === left; 2 === middle; 3 === right
525 // Note: button is not normalized, so don't use it
526 if ( !event.which && event.button !== undefined ) {
527 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
533 // Deprecated, use jQuery.guid instead
536 // Deprecated, use jQuery.proxy instead
541 // Make sure the ready event is setup
542 setup: jQuery.bindReady,
543 teardown: jQuery.noop
547 add: function( handleObj ) {
548 jQuery.event.add( this,
549 liveConvert( handleObj.origType, handleObj.selector ),
550 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
553 remove: function( handleObj ) {
554 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
559 setup: function( data, namespaces, eventHandle ) {
560 // We only want to do this special case on windows
561 if ( jQuery.isWindow( this ) ) {
562 this.onbeforeunload = eventHandle;
566 teardown: function( namespaces, eventHandle ) {
567 if ( this.onbeforeunload === eventHandle ) {
568 this.onbeforeunload = null;
575 jQuery.removeEvent = document.removeEventListener ?
576 function( elem, type, handle ) {
577 if ( elem.removeEventListener ) {
578 elem.removeEventListener( type, handle, false );
581 function( elem, type, handle ) {
582 if ( elem.detachEvent ) {
583 elem.detachEvent( "on" + type, handle );
587 jQuery.Event = function( src ) {
588 // Allow instantiation without the 'new' keyword
589 if ( !this.preventDefault ) {
590 return new jQuery.Event( src );
594 if ( src && src.type ) {
595 this.originalEvent = src;
596 this.type = src.type;
602 // timeStamp is buggy for some events on Firefox(#3843)
603 // So we won't rely on the native value
604 this.timeStamp = jQuery.now();
607 this[ jQuery.expando ] = true;
610 function returnFalse() {
613 function returnTrue() {
617 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
618 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
619 jQuery.Event.prototype = {
620 preventDefault: function() {
621 this.isDefaultPrevented = returnTrue;
623 var e = this.originalEvent;
628 // if preventDefault exists run it on the original event
629 if ( e.preventDefault ) {
632 // otherwise set the returnValue property of the original event to false (IE)
634 e.returnValue = false;
637 stopPropagation: function() {
638 this.isPropagationStopped = returnTrue;
640 var e = this.originalEvent;
644 // if stopPropagation exists run it on the original event
645 if ( e.stopPropagation ) {
648 // otherwise set the cancelBubble property of the original event to true (IE)
649 e.cancelBubble = true;
651 stopImmediatePropagation: function() {
652 this.isImmediatePropagationStopped = returnTrue;
653 this.stopPropagation();
655 isDefaultPrevented: returnFalse,
656 isPropagationStopped: returnFalse,
657 isImmediatePropagationStopped: returnFalse
660 // Checks if an event happened on an element within another element
661 // Used in jQuery.event.special.mouseenter and mouseleave handlers
662 var withinElement = function( event ) {
663 // Check if mouse(over|out) are still within the same parent element
664 var parent = event.relatedTarget;
666 // Firefox sometimes assigns relatedTarget a XUL element
667 // which we cannot access the parentNode property of
669 // Traverse up the tree
670 while ( parent && parent !== this ) {
671 parent = parent.parentNode;
674 if ( parent !== this ) {
675 // set the correct event type
676 event.type = event.data;
678 // handle event if we actually just moused on to a non sub-element
679 jQuery.event.handle.apply( this, arguments );
682 // assuming we've left the element since we most likely mousedover a xul element
686 // In case of event delegation, we only need to rename the event.type,
687 // liveHandler will take care of the rest.
688 delegate = function( event ) {
689 event.type = event.data;
690 jQuery.event.handle.apply( this, arguments );
693 // Create mouseenter and mouseleave events
695 mouseenter: "mouseover",
696 mouseleave: "mouseout"
697 }, function( orig, fix ) {
698 jQuery.event.special[ orig ] = {
699 setup: function( data ) {
700 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
702 teardown: function( data ) {
703 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
709 if ( !jQuery.support.submitBubbles ) {
711 jQuery.event.special.submit = {
712 setup: function( data, namespaces ) {
713 if ( this.nodeName.toLowerCase() !== "form" ) {
714 jQuery.event.add(this, "click.specialSubmit", function( e ) {
715 var elem = e.target, type = elem.type;
717 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
718 e.liveFired = undefined;
719 return trigger( "submit", this, arguments );
723 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
724 var elem = e.target, type = elem.type;
726 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
727 e.liveFired = undefined;
728 return trigger( "submit", this, arguments );
737 teardown: function( namespaces ) {
738 jQuery.event.remove( this, ".specialSubmit" );
744 // change delegation, happens here so we have bind.
745 if ( !jQuery.support.changeBubbles ) {
749 getVal = function( elem ) {
750 var type = elem.type, val = elem.value;
752 if ( type === "radio" || type === "checkbox" ) {
755 } else if ( type === "select-multiple" ) {
756 val = elem.selectedIndex > -1 ?
757 jQuery.map( elem.options, function( elem ) {
758 return elem.selected;
762 } else if ( elem.nodeName.toLowerCase() === "select" ) {
763 val = elem.selectedIndex;
769 testChange = function testChange( e ) {
770 var elem = e.target, data, val;
772 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
776 data = jQuery.data( elem, "_change_data" );
779 // the current data will be also retrieved by beforeactivate
780 if ( e.type !== "focusout" || elem.type !== "radio" ) {
781 jQuery.data( elem, "_change_data", val );
784 if ( data === undefined || val === data ) {
788 if ( data != null || val ) {
790 e.liveFired = undefined;
791 return jQuery.event.trigger( e, arguments[1], elem );
795 jQuery.event.special.change = {
797 focusout: testChange,
799 beforedeactivate: testChange,
801 click: function( e ) {
802 var elem = e.target, type = elem.type;
804 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
805 return testChange.call( this, e );
809 // Change has to be called before submit
810 // Keydown will be called before keypress, which is used in submit-event delegation
811 keydown: function( e ) {
812 var elem = e.target, type = elem.type;
814 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
815 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
816 type === "select-multiple" ) {
817 return testChange.call( this, e );
821 // Beforeactivate happens also before the previous element is blurred
822 // with this event you can't trigger a change event, but you can store
824 beforeactivate: function( e ) {
826 jQuery.data( elem, "_change_data", getVal(elem) );
830 setup: function( data, namespaces ) {
831 if ( this.type === "file" ) {
835 for ( var type in changeFilters ) {
836 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
839 return rformElems.test( this.nodeName );
842 teardown: function( namespaces ) {
843 jQuery.event.remove( this, ".specialChange" );
845 return rformElems.test( this.nodeName );
849 changeFilters = jQuery.event.special.change.filters;
851 // Handle when the input is .focus()'d
852 changeFilters.focus = changeFilters.beforeactivate;
855 function trigger( type, elem, args ) {
857 return jQuery.event.handle.apply( elem, args );
860 // Create "bubbling" focus and blur events
861 if ( document.addEventListener ) {
862 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
863 jQuery.event.special[ fix ] = {
865 if ( focusCounts[fix]++ === 0 ) {
866 document.addEventListener( orig, handler, true );
869 teardown: function() {
870 if ( --focusCounts[fix] === 0 ) {
871 document.removeEventListener( orig, handler, true );
876 function handler( e ) {
877 e = jQuery.event.fix( e );
879 return jQuery.event.trigger( e, null, e.target );
884 jQuery.each(["bind", "one"], function( i, name ) {
885 jQuery.fn[ name ] = function( type, data, fn ) {
886 // Handle object literals
887 if ( typeof type === "object" ) {
888 for ( var key in type ) {
889 this[ name ](key, data, type[key], fn);
894 if ( jQuery.isFunction( data ) || data === false ) {
899 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
900 jQuery( this ).unbind( event, handler );
901 return fn.apply( this, arguments );
904 if ( type === "unload" && name !== "one" ) {
905 this.one( type, data, fn );
908 for ( var i = 0, l = this.length; i < l; i++ ) {
909 jQuery.event.add( this[i], type, handler, data );
918 unbind: function( type, fn ) {
919 // Handle object literals
920 if ( typeof type === "object" && !type.preventDefault ) {
921 for ( var key in type ) {
922 this.unbind(key, type[key]);
926 for ( var i = 0, l = this.length; i < l; i++ ) {
927 jQuery.event.remove( this[i], type, fn );
934 delegate: function( selector, types, data, fn ) {
935 return this.live( types, data, fn, selector );
938 undelegate: function( selector, types, fn ) {
939 if ( arguments.length === 0 ) {
940 return this.unbind( "live" );
943 return this.die( types, null, fn, selector );
947 trigger: function( type, data ) {
948 return this.each(function() {
949 jQuery.event.trigger( type, data, this );
953 triggerHandler: function( type, data ) {
955 var event = jQuery.Event( type );
956 event.preventDefault();
957 event.stopPropagation();
958 jQuery.event.trigger( event, data, this[0] );
963 toggle: function( fn ) {
964 // Save reference to arguments for access in closure
965 var args = arguments, i = 1;
967 // link all the functions, so any of them can unbind this click handler
968 while ( i < args.length ) {
969 jQuery.proxy( fn, args[ i++ ] );
972 return this.click( jQuery.proxy( fn, function( event ) {
973 // Figure out which function to execute
974 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
975 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
977 // Make sure that clicks stop
978 event.preventDefault();
980 // and execute the function
981 return args[ lastToggle ].apply( this, arguments ) || false;
985 hover: function( fnOver, fnOut ) {
986 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
993 mouseenter: "mouseover",
994 mouseleave: "mouseout"
997 jQuery.each(["live", "die"], function( i, name ) {
998 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
999 var type, i = 0, match, namespaces, preType,
1000 selector = origSelector || this.selector,
1001 context = origSelector ? this : jQuery( this.context );
1003 if ( typeof types === "object" && !types.preventDefault ) {
1004 for ( var key in types ) {
1005 context[ name ]( key, data, types[key], selector );
1011 if ( jQuery.isFunction( data ) ) {
1016 types = (types || "").split(" ");
1018 while ( (type = types[ i++ ]) != null ) {
1019 match = rnamespaces.exec( type );
1023 namespaces = match[0];
1024 type = type.replace( rnamespaces, "" );
1027 if ( type === "hover" ) {
1028 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1034 if ( type === "focus" || type === "blur" ) {
1035 types.push( liveMap[ type ] + namespaces );
1036 type = type + namespaces;
1039 type = (liveMap[ type ] || type) + namespaces;
1042 if ( name === "live" ) {
1043 // bind live handler
1044 for ( var j = 0, l = context.length; j < l; j++ ) {
1045 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1046 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1050 // unbind live handler
1051 context.unbind( "live." + liveConvert( type, selector ), fn );
1059 function liveHandler( event ) {
1060 var stop, maxLevel, elems = [], selectors = [],
1061 related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1062 events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
1064 if ( typeof events === "function" ) {
1065 events = events.events;
1068 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
1069 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
1073 if ( event.namespace ) {
1074 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1077 event.liveFired = this;
1079 var live = events.live.slice(0);
1081 for ( j = 0; j < live.length; j++ ) {
1082 handleObj = live[j];
1084 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1085 selectors.push( handleObj.selector );
1088 live.splice( j--, 1 );
1092 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1094 for ( i = 0, l = match.length; i < l; i++ ) {
1097 for ( j = 0; j < live.length; j++ ) {
1098 handleObj = live[j];
1100 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1104 // Those two events require additional checking
1105 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1106 event.type = handleObj.preType;
1107 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1110 if ( !related || related !== elem ) {
1111 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1117 for ( i = 0, l = elems.length; i < l; i++ ) {
1120 if ( maxLevel && match.level > maxLevel ) {
1124 event.currentTarget = match.elem;
1125 event.data = match.handleObj.data;
1126 event.handleObj = match.handleObj;
1128 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1130 if ( ret === false || event.isPropagationStopped() ) {
1131 maxLevel = match.level;
1133 if ( ret === false ) {
1136 if ( event.isImmediatePropagationStopped() ) {
1145 function liveConvert( type, selector ) {
1146 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1149 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1150 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1151 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1153 // Handle event binding
1154 jQuery.fn[ name ] = function( data, fn ) {
1160 return arguments.length > 0 ?
1161 this.bind( name, data, fn ) :
1162 this.trigger( name );
1165 if ( jQuery.attrFn ) {
1166 jQuery.attrFn[ name ] = true;
1170 // Prevent memory leaks in IE
1171 // Window isn't included so as not to unbind existing unload events
1173 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
1174 if ( window.attachEvent && !window.addEventListener ) {
1175 jQuery(window).bind("unload", function() {
1176 for ( var id in jQuery.cache ) {
1177 if ( jQuery.cache[ id ].handle ) {
1178 // Try/Catch is to handle iframes being unloaded, see #4280
1180 jQuery.event.remove( jQuery.cache[ id ].handle.elem );