3 var rnamespaces = /\.(.*)$/,
4 rformElems = /^(?:textarea|input|select)$/i,
7 rescape = /[^\w\s.|`]/g,
8 fcleanup = function( nm ) {
9 return nm.replace(rescape, "\\$&");
13 * A number of helper functions used for managing events.
14 * Many of the ideas behind this code originated from
15 * Dean Edwards' addEvent library.
19 // Bind an event to an element
20 // Original by Dean Edwards
21 add: function( elem, types, handler, data ) {
22 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
26 // For whatever reason, IE has trouble passing the window object
27 // around, causing it to be cloned in the process
28 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
32 if ( handler === false ) {
33 handler = returnFalse;
34 } else if ( !handler ) {
35 // Fixes bug #7229. Fix recommended by jdalton
39 var handleObjIn, handleObj;
41 if ( handler.handler ) {
42 handleObjIn = handler;
43 handler = handleObjIn.handler;
46 // Make sure that the function being executed has a unique ID
47 if ( !handler.guid ) {
48 handler.guid = jQuery.guid++;
51 // Init the element's event structure
52 var elemData = jQuery._data( elem );
54 // If no elemData is found then we must be trying to bind to one of the
55 // banned noData elements
60 var events = elemData.events,
61 eventHandle = elemData.handle;
64 elemData.events = events = {};
68 elemData.handle = eventHandle = function() {
69 // Handle the second event of a trigger and when
70 // an event is called after a page has unloaded
71 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
72 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
77 // Add elem as a property of the handle function
78 // This is to prevent a memory leak with non-native events in IE.
79 eventHandle.elem = elem;
81 // Handle multiple events separated by a space
82 // jQuery(...).bind("mouseover mouseout", fn);
83 types = types.split(" ");
85 var type, i = 0, namespaces;
87 while ( (type = types[ i++ ]) ) {
88 handleObj = handleObjIn ?
89 jQuery.extend({}, handleObjIn) :
90 { handler: handler, data: data };
92 // Namespaced event handlers
93 if ( type.indexOf(".") > -1 ) {
94 namespaces = type.split(".");
95 type = namespaces.shift();
96 handleObj.namespace = namespaces.slice(0).sort().join(".");
100 handleObj.namespace = "";
103 handleObj.type = type;
104 if ( !handleObj.guid ) {
105 handleObj.guid = handler.guid;
108 // Get the current list of functions bound to this event
109 var handlers = events[ type ],
110 special = jQuery.event.special[ type ] || {};
112 // Init the event handler queue
114 handlers = events[ type ] = [];
116 // Check for a special event handler
117 // Only use addEventListener/attachEvent if the special
118 // events handler returns false
119 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
120 // Bind the global event handler to the element
121 if ( elem.addEventListener ) {
122 elem.addEventListener( type, eventHandle, false );
124 } else if ( elem.attachEvent ) {
125 elem.attachEvent( "on" + type, eventHandle );
131 special.add.call( elem, handleObj );
133 if ( !handleObj.handler.guid ) {
134 handleObj.handler.guid = handler.guid;
138 // Add the function to the element's handler list
139 handlers.push( handleObj );
141 // Keep track of which events have been used, for global triggering
142 jQuery.event.global[ type ] = true;
145 // Nullify elem to prevent memory leaks in IE
151 // Detach an event or set of events from an element
152 remove: function( elem, types, handler, pos ) {
153 // don't do events on text and comment nodes
154 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
158 if ( handler === false ) {
159 handler = returnFalse;
162 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
163 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
164 events = elemData && elemData.events;
166 if ( !elemData || !events ) {
170 // types is actually an event object here
171 if ( types && types.type ) {
172 handler = types.handler;
176 // Unbind all events for the element
177 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
180 for ( type in events ) {
181 jQuery.event.remove( elem, type + types );
187 // Handle multiple events separated by a space
188 // jQuery(...).unbind("mouseover mouseout", fn);
189 types = types.split(" ");
191 while ( (type = types[ i++ ]) ) {
194 all = type.indexOf(".") < 0;
198 // Namespaced event handlers
199 namespaces = type.split(".");
200 type = namespaces.shift();
202 namespace = new RegExp("(^|\\.)" +
203 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
206 eventType = events[ type ];
213 for ( j = 0; j < eventType.length; j++ ) {
214 handleObj = eventType[ j ];
216 if ( all || namespace.test( handleObj.namespace ) ) {
217 jQuery.event.remove( elem, origType, handleObj.handler, j );
218 eventType.splice( j--, 1 );
225 special = jQuery.event.special[ type ] || {};
227 for ( j = pos || 0; j < eventType.length; j++ ) {
228 handleObj = eventType[ j ];
230 if ( handler.guid === handleObj.guid ) {
231 // remove the given handler for the given type
232 if ( all || namespace.test( handleObj.namespace ) ) {
234 eventType.splice( j--, 1 );
237 if ( special.remove ) {
238 special.remove.call( elem, handleObj );
248 // remove generic event handler if no more handlers exist
249 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
250 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
251 jQuery.removeEvent( elem, type, elemData.handle );
255 delete events[ type ];
259 // Remove the expando if it's no longer used
260 if ( jQuery.isEmptyObject( events ) ) {
261 var handle = elemData.handle;
266 delete elemData.events;
267 delete elemData.handle;
269 if ( jQuery.isEmptyObject( elemData ) ) {
270 jQuery.removeData( elem, undefined, true );
275 // bubbling is internal
276 trigger: function( event, data, elem /*, bubbling */ ) {
277 // Event object or event type
278 var type = event.type || event,
279 bubbling = arguments[3];
282 event = typeof event === "object" ?
283 // jQuery.Event object
284 event[ jQuery.expando ] ? event :
286 jQuery.extend( jQuery.Event(type), event ) :
287 // Just the event type (string)
290 if ( type.indexOf("!") >= 0 ) {
291 event.type = type = type.slice(0, -1);
292 event.exclusive = true;
295 // Handle a global trigger
297 // Don't bubble custom events when global (to avoid too much overhead)
298 event.stopPropagation();
300 // Only trigger if we've ever bound an event for it
301 if ( jQuery.event.global[ type ] ) {
302 // XXX This code smells terrible. event.js should not be directly
303 // inspecting the data cache
304 jQuery.each( jQuery.cache, function() {
305 // internalKey variable is just used to make it easier to find
306 // and potentially change this stuff later; currently it just
307 // points to jQuery.expando
308 var internalKey = jQuery.expando,
309 internalCache = this[ internalKey ];
310 if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
311 jQuery.event.trigger( event, data, internalCache.handle.elem );
317 // Handle triggering a single element
319 // don't do events on text and comment nodes
320 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
324 // Clean up in case it is reused
325 event.result = undefined;
328 // Clone the incoming data, if any
329 data = jQuery.makeArray( data );
330 data.unshift( event );
333 event.currentTarget = elem;
335 // Trigger the event, it is assumed that "handle" is a function
336 var handle = jQuery._data( elem, "handle" );
339 handle.apply( elem, data );
342 var parent = elem.parentNode || elem.ownerDocument;
344 // Trigger an inline bound script
346 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
347 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
348 event.result = false;
349 event.preventDefault();
353 // prevent IE from throwing an error for some elements with some event types, see #3533
354 } catch (inlineError) {}
356 if ( !event.isPropagationStopped() && parent ) {
357 jQuery.event.trigger( event, data, parent, true );
359 } else if ( !event.isDefaultPrevented() ) {
361 target = event.target,
362 targetType = type.replace( rnamespaces, "" ),
363 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
364 special = jQuery.event.special[ targetType ] || {};
366 if ( (!special._default || special._default.call( elem, event ) === false) &&
367 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
370 if ( target[ targetType ] ) {
371 // Make sure that we don't accidentally re-trigger the onFOO events
372 old = target[ "on" + targetType ];
375 target[ "on" + targetType ] = null;
378 jQuery.event.triggered = true;
379 target[ targetType ]();
382 // prevent IE from throwing an error for some elements with some event types, see #3533
383 } catch (triggerError) {}
386 target[ "on" + targetType ] = old;
389 jQuery.event.triggered = false;
394 handle: function( event ) {
395 var all, handlers, namespaces, namespace_re, events,
397 args = jQuery.makeArray( arguments );
399 event = args[0] = jQuery.event.fix( event || window.event );
400 event.currentTarget = this;
402 // Namespaced event handlers
403 all = event.type.indexOf(".") < 0 && !event.exclusive;
406 namespaces = event.type.split(".");
407 event.type = namespaces.shift();
408 namespace_sort = namespaces.slice(0).sort();
409 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
412 event.namespace = event.namespace || namespace_sort.join(".");
414 events = jQuery._data(this, "events");
416 handlers = (events || {})[ event.type ];
418 if ( events && handlers ) {
419 // Clone the handlers to prevent manipulation
420 handlers = handlers.slice(0);
422 for ( var j = 0, l = handlers.length; j < l; j++ ) {
423 var handleObj = handlers[ j ];
425 // Filter the functions by class
426 if ( all || namespace_re.test( handleObj.namespace ) ) {
427 // Pass in a reference to the handler function itself
428 // So that we can later remove it
429 event.handler = handleObj.handler;
430 event.data = handleObj.data;
431 event.handleObj = handleObj;
433 var ret = handleObj.handler.apply( this, args );
435 if ( ret !== undefined ) {
437 if ( ret === false ) {
438 event.preventDefault();
439 event.stopPropagation();
443 if ( event.isImmediatePropagationStopped() ) {
453 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(" "),
455 fix: function( event ) {
456 if ( event[ jQuery.expando ] ) {
460 // store a copy of the original event object
461 // and "clone" to set read-only properties
462 var originalEvent = event;
463 event = jQuery.Event( originalEvent );
465 for ( var i = this.props.length, prop; i; ) {
466 prop = this.props[ --i ];
467 event[ prop ] = originalEvent[ prop ];
470 // Fix target property, if necessary
471 if ( !event.target ) {
472 // Fixes #1925 where srcElement might not be defined either
473 event.target = event.srcElement || document;
476 // check if target is a textnode (safari)
477 if ( event.target.nodeType === 3 ) {
478 event.target = event.target.parentNode;
481 // Add relatedTarget, if necessary
482 if ( !event.relatedTarget && event.fromElement ) {
483 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
486 // Calculate pageX/Y if missing and clientX/Y available
487 if ( event.pageX == null && event.clientX != null ) {
488 var doc = document.documentElement,
489 body = document.body;
491 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
492 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
495 // Add which for key events
496 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
497 event.which = event.charCode != null ? event.charCode : event.keyCode;
500 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
501 if ( !event.metaKey && event.ctrlKey ) {
502 event.metaKey = event.ctrlKey;
505 // Add which for click: 1 === left; 2 === middle; 3 === right
506 // Note: button is not normalized, so don't use it
507 if ( !event.which && event.button !== undefined ) {
508 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
514 // Deprecated, use jQuery.guid instead
517 // Deprecated, use jQuery.proxy instead
522 // Make sure the ready event is setup
523 setup: jQuery.bindReady,
524 teardown: jQuery.noop
528 add: function( handleObj ) {
529 jQuery.event.add( this,
530 liveConvert( handleObj.origType, handleObj.selector ),
531 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
534 remove: function( handleObj ) {
535 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
540 setup: function( data, namespaces, eventHandle ) {
541 // We only want to do this special case on windows
542 if ( jQuery.isWindow( this ) ) {
543 this.onbeforeunload = eventHandle;
547 teardown: function( namespaces, eventHandle ) {
548 if ( this.onbeforeunload === eventHandle ) {
549 this.onbeforeunload = null;
556 jQuery.removeEvent = document.removeEventListener ?
557 function( elem, type, handle ) {
558 if ( elem.removeEventListener ) {
559 elem.removeEventListener( type, handle, false );
562 function( elem, type, handle ) {
563 if ( elem.detachEvent ) {
564 elem.detachEvent( "on" + type, handle );
568 jQuery.Event = function( src ) {
569 // Allow instantiation without the 'new' keyword
570 if ( !this.preventDefault ) {
571 return new jQuery.Event( src );
575 if ( src && src.type ) {
576 this.originalEvent = src;
577 this.type = src.type;
579 // Events bubbling up the document may have been marked as prevented
580 // by a handler lower down the tree; reflect the correct value.
581 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
582 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
589 // timeStamp is buggy for some events on Firefox(#3843)
590 // So we won't rely on the native value
591 this.timeStamp = jQuery.now();
594 this[ jQuery.expando ] = true;
597 function returnFalse() {
600 function returnTrue() {
604 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
605 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
606 jQuery.Event.prototype = {
607 preventDefault: function() {
608 this.isDefaultPrevented = returnTrue;
610 var e = this.originalEvent;
615 // if preventDefault exists run it on the original event
616 if ( e.preventDefault ) {
619 // otherwise set the returnValue property of the original event to false (IE)
621 e.returnValue = false;
624 stopPropagation: function() {
625 this.isPropagationStopped = returnTrue;
627 var e = this.originalEvent;
631 // if stopPropagation exists run it on the original event
632 if ( e.stopPropagation ) {
635 // otherwise set the cancelBubble property of the original event to true (IE)
636 e.cancelBubble = true;
638 stopImmediatePropagation: function() {
639 this.isImmediatePropagationStopped = returnTrue;
640 this.stopPropagation();
642 isDefaultPrevented: returnFalse,
643 isPropagationStopped: returnFalse,
644 isImmediatePropagationStopped: returnFalse
647 // Checks if an event happened on an element within another element
648 // Used in jQuery.event.special.mouseenter and mouseleave handlers
649 var withinElement = function( event ) {
650 // Check if mouse(over|out) are still within the same parent element
651 var parent = event.relatedTarget;
653 // Firefox sometimes assigns relatedTarget a XUL element
654 // which we cannot access the parentNode property of
655 // Chrome does something similar, the parentNode property
656 // can be accessed but is null.
658 // Traverse up the tree
659 while ( parent && parent !== this ) {
660 parent = parent.parentNode;
663 if ( parent && parent !== this ) {
664 // set the correct event type
665 event.type = event.data;
667 // handle event if we actually just moused on to a non sub-element
668 jQuery.event.handle.apply( this, arguments );
671 // assuming we've left the element since we most likely mousedover a xul element
675 // In case of event delegation, we only need to rename the event.type,
676 // liveHandler will take care of the rest.
677 delegate = function( event ) {
678 event.type = event.data;
679 jQuery.event.handle.apply( this, arguments );
682 // Create mouseenter and mouseleave events
684 mouseenter: "mouseover",
685 mouseleave: "mouseout"
686 }, function( orig, fix ) {
687 jQuery.event.special[ orig ] = {
688 setup: function( data ) {
689 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
691 teardown: function( data ) {
692 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
698 if ( !jQuery.support.submitBubbles ) {
700 jQuery.event.special.submit = {
701 setup: function( data, namespaces ) {
702 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
703 jQuery.event.add(this, "click.specialSubmit", function( e ) {
707 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
708 e.liveFired = undefined;
709 return trigger( "submit", this, arguments );
713 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
717 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
718 e.liveFired = undefined;
719 return trigger( "submit", this, arguments );
728 teardown: function( namespaces ) {
729 jQuery.event.remove( this, ".specialSubmit" );
735 // change delegation, happens here so we have bind.
736 if ( !jQuery.support.changeBubbles ) {
740 getVal = function( elem ) {
741 var type = elem.type, val = elem.value;
743 if ( type === "radio" || type === "checkbox" ) {
746 } else if ( type === "select-multiple" ) {
747 val = elem.selectedIndex > -1 ?
748 jQuery.map( elem.options, function( elem ) {
749 return elem.selected;
753 } else if ( elem.nodeName.toLowerCase() === "select" ) {
754 val = elem.selectedIndex;
760 testChange = function testChange( e ) {
761 var elem = e.target, data, val;
763 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
767 data = jQuery._data( elem, "_change_data" );
770 // the current data will be also retrieved by beforeactivate
771 if ( e.type !== "focusout" || elem.type !== "radio" ) {
772 jQuery._data( elem, "_change_data", val );
775 if ( data === undefined || val === data ) {
779 if ( data != null || val ) {
781 e.liveFired = undefined;
782 return jQuery.event.trigger( e, arguments[1], elem );
786 jQuery.event.special.change = {
788 focusout: testChange,
790 beforedeactivate: testChange,
792 click: function( e ) {
793 var elem = e.target, type = elem.type;
795 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
796 return testChange.call( this, e );
800 // Change has to be called before submit
801 // Keydown will be called before keypress, which is used in submit-event delegation
802 keydown: function( e ) {
803 var elem = e.target, type = elem.type;
805 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
806 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
807 type === "select-multiple" ) {
808 return testChange.call( this, e );
812 // Beforeactivate happens also before the previous element is blurred
813 // with this event you can't trigger a change event, but you can store
815 beforeactivate: function( e ) {
817 jQuery._data( elem, "_change_data", getVal(elem) );
821 setup: function( data, namespaces ) {
822 if ( this.type === "file" ) {
826 for ( var type in changeFilters ) {
827 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
830 return rformElems.test( this.nodeName );
833 teardown: function( namespaces ) {
834 jQuery.event.remove( this, ".specialChange" );
836 return rformElems.test( this.nodeName );
840 changeFilters = jQuery.event.special.change.filters;
842 // Handle when the input is .focus()'d
843 changeFilters.focus = changeFilters.beforeactivate;
846 function trigger( type, elem, args ) {
848 return jQuery.event.handle.apply( elem, args );
851 // Create "bubbling" focus and blur events
852 if ( document.addEventListener ) {
853 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
854 jQuery.event.special[ fix ] = {
856 this.addEventListener( orig, handler, true );
858 teardown: function() {
859 this.removeEventListener( orig, handler, true );
863 function handler( e ) {
864 e = jQuery.event.fix( e );
866 return jQuery.event.handle.call( this, e );
871 jQuery.each(["bind", "one"], function( i, name ) {
872 jQuery.fn[ name ] = function( type, data, fn ) {
873 // Handle object literals
874 if ( typeof type === "object" ) {
875 for ( var key in type ) {
876 this[ name ](key, data, type[key], fn);
881 if ( jQuery.isFunction( data ) || data === false ) {
886 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
887 jQuery( this ).unbind( event, handler );
888 return fn.apply( this, arguments );
891 if ( type === "unload" && name !== "one" ) {
892 this.one( type, data, fn );
895 for ( var i = 0, l = this.length; i < l; i++ ) {
896 jQuery.event.add( this[i], type, handler, data );
905 unbind: function( type, fn ) {
906 // Handle object literals
907 if ( typeof type === "object" && !type.preventDefault ) {
908 for ( var key in type ) {
909 this.unbind(key, type[key]);
913 for ( var i = 0, l = this.length; i < l; i++ ) {
914 jQuery.event.remove( this[i], type, fn );
921 delegate: function( selector, types, data, fn ) {
922 return this.live( types, data, fn, selector );
925 undelegate: function( selector, types, fn ) {
926 if ( arguments.length === 0 ) {
927 return this.unbind( "live" );
930 return this.die( types, null, fn, selector );
934 trigger: function( type, data ) {
935 return this.each(function() {
936 jQuery.event.trigger( type, data, this );
940 triggerHandler: function( type, data ) {
942 var event = jQuery.Event( type );
943 event.preventDefault();
944 event.stopPropagation();
945 jQuery.event.trigger( event, data, this[0] );
950 toggle: function( fn ) {
951 // Save reference to arguments for access in closure
952 var args = arguments,
955 // link all the functions, so any of them can unbind this click handler
956 while ( i < args.length ) {
957 jQuery.proxy( fn, args[ i++ ] );
960 return this.click( jQuery.proxy( fn, function( event ) {
961 // Figure out which function to execute
962 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
963 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
965 // Make sure that clicks stop
966 event.preventDefault();
968 // and execute the function
969 return args[ lastToggle ].apply( this, arguments ) || false;
973 hover: function( fnOver, fnOut ) {
974 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
981 mouseenter: "mouseover",
982 mouseleave: "mouseout"
985 jQuery.each(["live", "die"], function( i, name ) {
986 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
987 var type, i = 0, match, namespaces, preType,
988 selector = origSelector || this.selector,
989 context = origSelector ? this : jQuery( this.context );
991 if ( typeof types === "object" && !types.preventDefault ) {
992 for ( var key in types ) {
993 context[ name ]( key, data, types[key], selector );
999 if ( jQuery.isFunction( data ) ) {
1004 types = (types || "").split(" ");
1006 while ( (type = types[ i++ ]) != null ) {
1007 match = rnamespaces.exec( type );
1011 namespaces = match[0];
1012 type = type.replace( rnamespaces, "" );
1015 if ( type === "hover" ) {
1016 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1022 if ( type === "focus" || type === "blur" ) {
1023 types.push( liveMap[ type ] + namespaces );
1024 type = type + namespaces;
1027 type = (liveMap[ type ] || type) + namespaces;
1030 if ( name === "live" ) {
1031 // bind live handler
1032 for ( var j = 0, l = context.length; j < l; j++ ) {
1033 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1034 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1038 // unbind live handler
1039 context.unbind( "live." + liveConvert( type, selector ), fn );
1047 function liveHandler( event ) {
1048 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1051 events = jQuery._data( this, "events" );
1053 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1054 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1058 if ( event.namespace ) {
1059 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1062 event.liveFired = this;
1064 var live = events.live.slice(0);
1066 for ( j = 0; j < live.length; j++ ) {
1067 handleObj = live[j];
1069 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1070 selectors.push( handleObj.selector );
1073 live.splice( j--, 1 );
1077 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1079 for ( i = 0, l = match.length; i < l; i++ ) {
1082 for ( j = 0; j < live.length; j++ ) {
1083 handleObj = live[j];
1085 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1089 // Those two events require additional checking
1090 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1091 event.type = handleObj.preType;
1092 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1095 if ( !related || related !== elem ) {
1096 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1102 for ( i = 0, l = elems.length; i < l; i++ ) {
1105 if ( maxLevel && match.level > maxLevel ) {
1109 event.currentTarget = match.elem;
1110 event.data = match.handleObj.data;
1111 event.handleObj = match.handleObj;
1113 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1115 if ( ret === false || event.isPropagationStopped() ) {
1116 maxLevel = match.level;
1118 if ( ret === false ) {
1121 if ( event.isImmediatePropagationStopped() ) {
1130 function liveConvert( type, selector ) {
1131 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1134 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1135 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1136 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1138 // Handle event binding
1139 jQuery.fn[ name ] = function( data, fn ) {
1145 return arguments.length > 0 ?
1146 this.bind( name, data, fn ) :
1147 this.trigger( name );
1150 if ( jQuery.attrFn ) {
1151 jQuery.attrFn[ name ] = true;