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
656 // Traverse up the tree
657 while ( parent && parent !== this ) {
658 parent = parent.parentNode;
661 if ( parent !== this ) {
662 // set the correct event type
663 event.type = event.data;
665 // handle event if we actually just moused on to a non sub-element
666 jQuery.event.handle.apply( this, arguments );
669 // assuming we've left the element since we most likely mousedover a xul element
673 // In case of event delegation, we only need to rename the event.type,
674 // liveHandler will take care of the rest.
675 delegate = function( event ) {
676 event.type = event.data;
677 jQuery.event.handle.apply( this, arguments );
680 // Create mouseenter and mouseleave events
682 mouseenter: "mouseover",
683 mouseleave: "mouseout"
684 }, function( orig, fix ) {
685 jQuery.event.special[ orig ] = {
686 setup: function( data ) {
687 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
689 teardown: function( data ) {
690 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
696 if ( !jQuery.support.submitBubbles ) {
698 jQuery.event.special.submit = {
699 setup: function( data, namespaces ) {
700 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
701 jQuery.event.add(this, "click.specialSubmit", function( e ) {
705 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
706 e.liveFired = undefined;
707 return trigger( "submit", this, arguments );
711 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
715 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
716 e.liveFired = undefined;
717 return trigger( "submit", this, arguments );
726 teardown: function( namespaces ) {
727 jQuery.event.remove( this, ".specialSubmit" );
733 // change delegation, happens here so we have bind.
734 if ( !jQuery.support.changeBubbles ) {
738 getVal = function( elem ) {
739 var type = elem.type, val = elem.value;
741 if ( type === "radio" || type === "checkbox" ) {
744 } else if ( type === "select-multiple" ) {
745 val = elem.selectedIndex > -1 ?
746 jQuery.map( elem.options, function( elem ) {
747 return elem.selected;
751 } else if ( elem.nodeName.toLowerCase() === "select" ) {
752 val = elem.selectedIndex;
758 testChange = function testChange( e ) {
759 var elem = e.target, data, val;
761 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
765 data = jQuery._data( elem, "_change_data" );
768 // the current data will be also retrieved by beforeactivate
769 if ( e.type !== "focusout" || elem.type !== "radio" ) {
770 jQuery._data( elem, "_change_data", val );
773 if ( data === undefined || val === data ) {
777 if ( data != null || val ) {
779 e.liveFired = undefined;
780 return jQuery.event.trigger( e, arguments[1], elem );
784 jQuery.event.special.change = {
786 focusout: testChange,
788 beforedeactivate: testChange,
790 click: function( e ) {
791 var elem = e.target, type = elem.type;
793 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
794 return testChange.call( this, e );
798 // Change has to be called before submit
799 // Keydown will be called before keypress, which is used in submit-event delegation
800 keydown: function( e ) {
801 var elem = e.target, type = elem.type;
803 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
804 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
805 type === "select-multiple" ) {
806 return testChange.call( this, e );
810 // Beforeactivate happens also before the previous element is blurred
811 // with this event you can't trigger a change event, but you can store
813 beforeactivate: function( e ) {
815 jQuery._data( elem, "_change_data", getVal(elem) );
819 setup: function( data, namespaces ) {
820 if ( this.type === "file" ) {
824 for ( var type in changeFilters ) {
825 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
828 return rformElems.test( this.nodeName );
831 teardown: function( namespaces ) {
832 jQuery.event.remove( this, ".specialChange" );
834 return rformElems.test( this.nodeName );
838 changeFilters = jQuery.event.special.change.filters;
840 // Handle when the input is .focus()'d
841 changeFilters.focus = changeFilters.beforeactivate;
844 function trigger( type, elem, args ) {
846 return jQuery.event.handle.apply( elem, args );
849 // Create "bubbling" focus and blur events
850 if ( document.addEventListener ) {
851 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
852 jQuery.event.special[ fix ] = {
854 this.addEventListener( orig, handler, true );
856 teardown: function() {
857 this.removeEventListener( orig, handler, true );
861 function handler( e ) {
862 e = jQuery.event.fix( e );
864 return jQuery.event.handle.call( this, e );
869 jQuery.each(["bind", "one"], function( i, name ) {
870 jQuery.fn[ name ] = function( type, data, fn ) {
871 // Handle object literals
872 if ( typeof type === "object" ) {
873 for ( var key in type ) {
874 this[ name ](key, data, type[key], fn);
879 if ( jQuery.isFunction( data ) || data === false ) {
884 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
885 jQuery( this ).unbind( event, handler );
886 return fn.apply( this, arguments );
889 if ( type === "unload" && name !== "one" ) {
890 this.one( type, data, fn );
893 for ( var i = 0, l = this.length; i < l; i++ ) {
894 jQuery.event.add( this[i], type, handler, data );
903 unbind: function( type, fn ) {
904 // Handle object literals
905 if ( typeof type === "object" && !type.preventDefault ) {
906 for ( var key in type ) {
907 this.unbind(key, type[key]);
911 for ( var i = 0, l = this.length; i < l; i++ ) {
912 jQuery.event.remove( this[i], type, fn );
919 delegate: function( selector, types, data, fn ) {
920 return this.live( types, data, fn, selector );
923 undelegate: function( selector, types, fn ) {
924 if ( arguments.length === 0 ) {
925 return this.unbind( "live" );
928 return this.die( types, null, fn, selector );
932 trigger: function( type, data ) {
933 return this.each(function() {
934 jQuery.event.trigger( type, data, this );
938 triggerHandler: function( type, data ) {
940 var event = jQuery.Event( type );
941 event.preventDefault();
942 event.stopPropagation();
943 jQuery.event.trigger( event, data, this[0] );
948 toggle: function( fn ) {
949 // Save reference to arguments for access in closure
950 var args = arguments,
953 // link all the functions, so any of them can unbind this click handler
954 while ( i < args.length ) {
955 jQuery.proxy( fn, args[ i++ ] );
958 return this.click( jQuery.proxy( fn, function( event ) {
959 // Figure out which function to execute
960 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
961 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
963 // Make sure that clicks stop
964 event.preventDefault();
966 // and execute the function
967 return args[ lastToggle ].apply( this, arguments ) || false;
971 hover: function( fnOver, fnOut ) {
972 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
979 mouseenter: "mouseover",
980 mouseleave: "mouseout"
983 jQuery.each(["live", "die"], function( i, name ) {
984 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
985 var type, i = 0, match, namespaces, preType,
986 selector = origSelector || this.selector,
987 context = origSelector ? this : jQuery( this.context );
989 if ( typeof types === "object" && !types.preventDefault ) {
990 for ( var key in types ) {
991 context[ name ]( key, data, types[key], selector );
997 if ( jQuery.isFunction( data ) ) {
1002 types = (types || "").split(" ");
1004 while ( (type = types[ i++ ]) != null ) {
1005 match = rnamespaces.exec( type );
1009 namespaces = match[0];
1010 type = type.replace( rnamespaces, "" );
1013 if ( type === "hover" ) {
1014 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1020 if ( type === "focus" || type === "blur" ) {
1021 types.push( liveMap[ type ] + namespaces );
1022 type = type + namespaces;
1025 type = (liveMap[ type ] || type) + namespaces;
1028 if ( name === "live" ) {
1029 // bind live handler
1030 for ( var j = 0, l = context.length; j < l; j++ ) {
1031 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1032 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1036 // unbind live handler
1037 context.unbind( "live." + liveConvert( type, selector ), fn );
1045 function liveHandler( event ) {
1046 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1049 events = jQuery._data( this, "events" );
1051 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1052 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1056 if ( event.namespace ) {
1057 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1060 event.liveFired = this;
1062 var live = events.live.slice(0);
1064 for ( j = 0; j < live.length; j++ ) {
1065 handleObj = live[j];
1067 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1068 selectors.push( handleObj.selector );
1071 live.splice( j--, 1 );
1075 match = jQuery( event.target ).closest( selectors, event.currentTarget );
1077 for ( i = 0, l = match.length; i < l; i++ ) {
1080 for ( j = 0; j < live.length; j++ ) {
1081 handleObj = live[j];
1083 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1087 // Those two events require additional checking
1088 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1089 event.type = handleObj.preType;
1090 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1093 if ( !related || related !== elem ) {
1094 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1100 for ( i = 0, l = elems.length; i < l; i++ ) {
1103 if ( maxLevel && match.level > maxLevel ) {
1107 event.currentTarget = match.elem;
1108 event.data = match.handleObj.data;
1109 event.handleObj = match.handleObj;
1111 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1113 if ( ret === false || event.isPropagationStopped() ) {
1114 maxLevel = match.level;
1116 if ( ret === false ) {
1119 if ( event.isImmediatePropagationStopped() ) {
1128 function liveConvert( type, selector ) {
1129 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1132 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1133 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1134 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1136 // Handle event binding
1137 jQuery.fn[ name ] = function( data, fn ) {
1143 return arguments.length > 0 ?
1144 this.bind( name, data, fn ) :
1145 this.trigger( name );
1148 if ( jQuery.attrFn ) {
1149 jQuery.attrFn[ name ] = true;