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
657 // Chrome does something similar, the parentNode property
658 // can be accessed but is null.
659 if ( parent !== document && !parent.parentNode ) {
662 // Traverse up the tree
663 while ( parent && parent !== this ) {
664 parent = parent.parentNode;
667 if ( parent !== this ) {
668 // set the correct event type
669 event.type = event.data;
671 // handle event if we actually just moused on to a non sub-element
672 jQuery.event.handle.apply( this, arguments );
675 // assuming we've left the element since we most likely mousedover a xul element
679 // In case of event delegation, we only need to rename the event.type,
680 // liveHandler will take care of the rest.
681 delegate = function( event ) {
682 event.type = event.data;
683 jQuery.event.handle.apply( this, arguments );
686 // Create mouseenter and mouseleave events
688 mouseenter: "mouseover",
689 mouseleave: "mouseout"
690 }, function( orig, fix ) {
691 jQuery.event.special[ orig ] = {
692 setup: function( data ) {
693 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
695 teardown: function( data ) {
696 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
702 if ( !jQuery.support.submitBubbles ) {
704 jQuery.event.special.submit = {
705 setup: function( data, namespaces ) {
706 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
707 jQuery.event.add(this, "click.specialSubmit", function( e ) {
711 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
712 e.liveFired = undefined;
713 return trigger( "submit", this, arguments );
717 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
721 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
722 e.liveFired = undefined;
723 return trigger( "submit", this, arguments );
732 teardown: function( namespaces ) {
733 jQuery.event.remove( this, ".specialSubmit" );
739 // change delegation, happens here so we have bind.
740 if ( !jQuery.support.changeBubbles ) {
744 getVal = function( elem ) {
745 var type = elem.type, val = elem.value;
747 if ( type === "radio" || type === "checkbox" ) {
750 } else if ( type === "select-multiple" ) {
751 val = elem.selectedIndex > -1 ?
752 jQuery.map( elem.options, function( elem ) {
753 return elem.selected;
757 } else if ( elem.nodeName.toLowerCase() === "select" ) {
758 val = elem.selectedIndex;
764 testChange = function testChange( e ) {
765 var elem = e.target, data, val;
767 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
771 data = jQuery._data( elem, "_change_data" );
774 // the current data will be also retrieved by beforeactivate
775 if ( e.type !== "focusout" || elem.type !== "radio" ) {
776 jQuery._data( elem, "_change_data", val );
779 if ( data === undefined || val === data ) {
783 if ( data != null || val ) {
785 e.liveFired = undefined;
786 return jQuery.event.trigger( e, arguments[1], elem );
790 jQuery.event.special.change = {
792 focusout: testChange,
794 beforedeactivate: testChange,
796 click: function( e ) {
797 var elem = e.target, type = elem.type;
799 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
800 return testChange.call( this, e );
804 // Change has to be called before submit
805 // Keydown will be called before keypress, which is used in submit-event delegation
806 keydown: function( e ) {
807 var elem = e.target, type = elem.type;
809 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
810 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
811 type === "select-multiple" ) {
812 return testChange.call( this, e );
816 // Beforeactivate happens also before the previous element is blurred
817 // with this event you can't trigger a change event, but you can store
819 beforeactivate: function( e ) {
821 jQuery._data( elem, "_change_data", getVal(elem) );
825 setup: function( data, namespaces ) {
826 if ( this.type === "file" ) {
830 for ( var type in changeFilters ) {
831 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
834 return rformElems.test( this.nodeName );
837 teardown: function( namespaces ) {
838 jQuery.event.remove( this, ".specialChange" );
840 return rformElems.test( this.nodeName );
844 changeFilters = jQuery.event.special.change.filters;
846 // Handle when the input is .focus()'d
847 changeFilters.focus = changeFilters.beforeactivate;
850 function trigger( type, elem, args ) {
852 return jQuery.event.handle.apply( elem, args );
855 // Create "bubbling" focus and blur events
856 if ( document.addEventListener ) {
857 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
858 jQuery.event.special[ fix ] = {
860 this.addEventListener( orig, handler, true );
862 teardown: function() {
863 this.removeEventListener( orig, handler, true );
867 function handler( e ) {
868 e = jQuery.event.fix( e );
870 return jQuery.event.handle.call( this, e );
875 jQuery.each(["bind", "one"], function( i, name ) {
876 jQuery.fn[ name ] = function( type, data, fn ) {
877 // Handle object literals
878 if ( typeof type === "object" ) {
879 for ( var key in type ) {
880 this[ name ](key, data, type[key], fn);
885 if ( jQuery.isFunction( data ) || data === false ) {
890 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
891 jQuery( this ).unbind( event, handler );
892 return fn.apply( this, arguments );
895 if ( type === "unload" && name !== "one" ) {
896 this.one( type, data, fn );
899 for ( var i = 0, l = this.length; i < l; i++ ) {
900 jQuery.event.add( this[i], type, handler, data );
909 unbind: function( type, fn ) {
910 // Handle object literals
911 if ( typeof type === "object" && !type.preventDefault ) {
912 for ( var key in type ) {
913 this.unbind(key, type[key]);
917 for ( var i = 0, l = this.length; i < l; i++ ) {
918 jQuery.event.remove( this[i], type, fn );
925 delegate: function( selector, types, data, fn ) {
926 return this.live( types, data, fn, selector );
929 undelegate: function( selector, types, fn ) {
930 if ( arguments.length === 0 ) {
931 return this.unbind( "live" );
934 return this.die( types, null, fn, selector );
938 trigger: function( type, data ) {
939 return this.each(function() {
940 jQuery.event.trigger( type, data, this );
944 triggerHandler: function( type, data ) {
946 var event = jQuery.Event( type );
947 event.preventDefault();
948 event.stopPropagation();
949 jQuery.event.trigger( event, data, this[0] );
954 toggle: function( fn ) {
955 // Save reference to arguments for access in closure
956 var args = arguments,
959 // link all the functions, so any of them can unbind this click handler
960 while ( i < args.length ) {
961 jQuery.proxy( fn, args[ i++ ] );
964 return this.click( jQuery.proxy( fn, function( event ) {
965 // Figure out which function to execute
966 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
967 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
969 // Make sure that clicks stop
970 event.preventDefault();
972 // and execute the function
973 return args[ lastToggle ].apply( this, arguments ) || false;
977 hover: function( fnOver, fnOut ) {
978 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
985 mouseenter: "mouseover",
986 mouseleave: "mouseout"
989 jQuery.each(["live", "die"], function( i, name ) {
990 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
991 var type, i = 0, match, namespaces, preType,
992 selector = origSelector || this.selector,
993 context = origSelector ? this : jQuery( this.context );
995 if ( typeof types === "object" && !types.preventDefault ) {
996 for ( var key in types ) {
997 context[ name ]( key, data, types[key], selector );
1003 if ( jQuery.isFunction( data ) ) {
1008 types = (types || "").split(" ");
1010 while ( (type = types[ i++ ]) != null ) {
1011 match = rnamespaces.exec( type );
1015 namespaces = match[0];
1016 type = type.replace( rnamespaces, "" );
1019 if ( type === "hover" ) {
1020 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1026 if ( type === "focus" || type === "blur" ) {
1027 types.push( liveMap[ type ] + namespaces );
1028 type = type + namespaces;
1031 type = (liveMap[ type ] || type) + namespaces;
1034 if ( name === "live" ) {
1035 // bind live handler
1036 for ( var j = 0, l = context.length; j < l; j++ ) {
1037 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1038 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1042 // unbind live handler
1043 context.unbind( "live." + liveConvert( type, selector ), fn );
1051 function liveHandler( event ) {
1052 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1055 events = jQuery._data( this, "events" );
1057 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1058 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1062 if ( event.namespace ) {
1063 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1066 event.liveFired = this;
1068 var live = events.live.slice(0);
1070 for ( j = 0; j < live.length; j++ ) {
1071 handleObj = live[j];
1073 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1074 selectors.push( handleObj.selector );
1077 live.splice( j--, 1 );
1081 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1083 for ( i = 0, l = match.length; i < l; i++ ) {
1086 for ( j = 0; j < live.length; j++ ) {
1087 handleObj = live[j];
1089 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1093 // Those two events require additional checking
1094 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1095 event.type = handleObj.preType;
1096 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1099 if ( !related || related !== elem ) {
1100 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1106 for ( i = 0, l = elems.length; i < l; i++ ) {
1109 if ( maxLevel && match.level > maxLevel ) {
1113 event.currentTarget = match.elem;
1114 event.data = match.handleObj.data;
1115 event.handleObj = match.handleObj;
1117 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1119 if ( ret === false || event.isPropagationStopped() ) {
1120 maxLevel = match.level;
1122 if ( ret === false ) {
1125 if ( event.isImmediatePropagationStopped() ) {
1134 function liveConvert( type, selector ) {
1135 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1138 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1139 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1140 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1142 // Handle event binding
1143 jQuery.fn[ name ] = function( data, fn ) {
1149 return arguments.length > 0 ?
1150 this.bind( name, data, fn ) :
1151 this.trigger( name );
1154 if ( jQuery.attrFn ) {
1155 jQuery.attrFn[ name ] = true;