Expose jQuery.uuid (use with caution) and make sure the expando property is used...
[jquery.git] / src / event.js
index 2fda802..45f2202 100644 (file)
@@ -25,6 +25,10 @@ jQuery.event = {
                        elem = window;
                }
 
                        elem = window;
                }
 
+               if ( handler === false ) {
+                       handler = returnFalse;
+               }
+
                var handleObjIn, handleObj;
 
                if ( handler.handler ) {
                var handleObjIn, handleObj;
 
                if ( handler.handler ) {
@@ -47,7 +51,7 @@ jQuery.event = {
                }
 
                var events = elemData.events = elemData.events || {},
                }
 
                var events = elemData.events = elemData.events || {},
-                       eventHandle = elemData.handle, eventHandle;
+                       eventHandle = elemData.handle;
 
                if ( !eventHandle ) {
                        elemData.handle = eventHandle = function() {
 
                if ( !eventHandle ) {
                        elemData.handle = eventHandle = function() {
@@ -86,7 +90,9 @@ jQuery.event = {
                        }
 
                        handleObj.type = type;
                        }
 
                        handleObj.type = type;
-                       handleObj.guid = handler.guid;
+                       if ( !handleObj.guid ) {
+                               handleObj.guid = handler.guid;
+                       }
 
                        // Get the current list of functions bound to this event
                        var handlers = events[ type ],
 
                        // Get the current list of functions bound to this event
                        var handlers = events[ type ],
@@ -112,6 +118,10 @@ jQuery.event = {
                        
                        if ( special.add ) { 
                                special.add.call( elem, handleObj ); 
                        
                        if ( special.add ) { 
                                special.add.call( elem, handleObj ); 
+
+                               if ( !handleObj.handler.guid ) {
+                                       handleObj.handler.guid = handler.guid;
+                               }
                        }
 
                        // Add the function to the element's handler list
                        }
 
                        // Add the function to the element's handler list
@@ -134,7 +144,11 @@ jQuery.event = {
                        return;
                }
 
                        return;
                }
 
-               var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+               if ( handler === false ) {
+                       handler = returnFalse;
+               }
+
+               var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
                        elemData = jQuery.data( elem ),
                        events = elemData && elemData.events;
 
                        elemData = jQuery.data( elem ),
                        events = elemData && elemData.events;
 
@@ -175,7 +189,7 @@ jQuery.event = {
                                type = namespaces.shift();
 
                                namespace = new RegExp("(^|\\.)" + 
                                type = namespaces.shift();
 
                                namespace = new RegExp("(^|\\.)" + 
-                                       jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
+                                       jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
                        }
 
                        eventType = events[ type ];
                        }
 
                        eventType = events[ type ];
@@ -185,7 +199,7 @@ jQuery.event = {
                        }
 
                        if ( !handler ) {
                        }
 
                        if ( !handler ) {
-                               for ( var j = 0; j < eventType.length; j++ ) {
+                               for ( j = 0; j < eventType.length; j++ ) {
                                        handleObj = eventType[ j ];
 
                                        if ( all || namespace.test( handleObj.namespace ) ) {
                                        handleObj = eventType[ j ];
 
                                        if ( all || namespace.test( handleObj.namespace ) ) {
@@ -199,7 +213,7 @@ jQuery.event = {
 
                        special = jQuery.event.special[ type ] || {};
 
 
                        special = jQuery.event.special[ type ] || {};
 
-                       for ( var j = pos || 0; j < eventType.length; j++ ) {
+                       for ( j = pos || 0; j < eventType.length; j++ ) {
                                handleObj = eventType[ j ];
 
                                if ( handler.guid === handleObj.guid ) {
                                handleObj = eventType[ j ];
 
                                if ( handler.guid === handleObj.guid ) {
@@ -221,7 +235,7 @@ jQuery.event = {
                        }
 
                        // remove generic event handler if no more handlers exist
                        }
 
                        // remove generic event handler if no more handlers exist
-                       if ( jQuery.isEmptyObject( events[ type ] ) ) {
+                       if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
                                if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
                                        removeEvent( elem, type, elemData.handle );
                                }
                                if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
                                        removeEvent( elem, type, elemData.handle );
                                }
@@ -256,7 +270,7 @@ jQuery.event = {
                if ( !bubbling ) {
                        event = typeof event === "object" ?
                                // jQuery.Event object
                if ( !bubbling ) {
                        event = typeof event === "object" ?
                                // jQuery.Event object
-                               event[expando] ? event :
+                               event[ jQuery.expando ] ? event :
                                // Object literal
                                jQuery.extend( jQuery.Event(type), event ) :
                                // Just the event type (string)
                                // Object literal
                                jQuery.extend( jQuery.Event(type), event ) :
                                // Just the event type (string)
@@ -317,37 +331,37 @@ jQuery.event = {
                        }
 
                // prevent IE from throwing an error for some elements with some event types, see #3533
                        }
 
                // prevent IE from throwing an error for some elements with some event types, see #3533
-               } catch (e) {}
+               } catch (inlineError) {}
 
                if ( !event.isPropagationStopped() && parent ) {
                        jQuery.event.trigger( event, data, parent, true );
 
                } else if ( !event.isDefaultPrevented() ) {
 
                if ( !event.isPropagationStopped() && parent ) {
                        jQuery.event.trigger( event, data, parent, true );
 
                } else if ( !event.isDefaultPrevented() ) {
-                       var target = event.target, old,
-                               isClick = jQuery.nodeName(target, "a") && type === "click",
-                               special = jQuery.event.special[ type ] || {};
+                       var target = event.target, old, targetType = type.replace(/\..*$/, ""),
+                               isClick = jQuery.nodeName(target, "a") && targetType === "click",
+                               special = jQuery.event.special[ targetType ] || {};
 
                        if ( (!special._default || special._default.call( elem, event ) === false) && 
                                !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 
                                try {
 
                        if ( (!special._default || special._default.call( elem, event ) === false) && 
                                !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 
                                try {
-                                       if ( target[ type ] ) {
+                                       if ( target[ targetType ] ) {
                                                // Make sure that we don't accidentally re-trigger the onFOO events
                                                // Make sure that we don't accidentally re-trigger the onFOO events
-                                               old = target[ "on" + type ];
+                                               old = target[ "on" + targetType ];
 
                                                if ( old ) {
 
                                                if ( old ) {
-                                                       target[ "on" + type ] = null;
+                                                       target[ "on" + targetType ] = null;
                                                }
 
                                                jQuery.event.triggered = true;
                                                }
 
                                                jQuery.event.triggered = true;
-                                               target[ type ]();
+                                               target[ targetType ]();
                                        }
 
                                // prevent IE from throwing an error for some elements with some event types, see #3533
                                        }
 
                                // prevent IE from throwing an error for some elements with some event types, see #3533
-                               } catch (e) {}
+                               } catch (triggerError) {}
 
                                if ( old ) {
 
                                if ( old ) {
-                                       target[ "on" + type ] = old;
+                                       target[ "on" + targetType ] = old;
                                }
 
                                jQuery.event.triggered = false;
                                }
 
                                jQuery.event.triggered = false;
@@ -356,9 +370,9 @@ jQuery.event = {
        },
 
        handle: function( event ) {
        },
 
        handle: function( event ) {
-               var all, handlers, namespaces, namespace, events;
+               var all, handlers, namespaces, namespace_sort = [], namespace_re, events, args = jQuery.makeArray( arguments );
 
 
-               event = arguments[0] = jQuery.event.fix( event || window.event );
+               event = args[0] = jQuery.event.fix( event || window.event );
                event.currentTarget = this;
 
                // Namespaced event handlers
                event.currentTarget = this;
 
                // Namespaced event handlers
@@ -367,10 +381,14 @@ jQuery.event = {
                if ( !all ) {
                        namespaces = event.type.split(".");
                        event.type = namespaces.shift();
                if ( !all ) {
                        namespaces = event.type.split(".");
                        event.type = namespaces.shift();
-                       namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
+                       namespace_sort = namespaces.slice(0).sort();
+                       namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
                }
 
                }
 
-               var events = jQuery.data(this, "events"), handlers = events[ event.type ];
+               event.namespace = event.namespace || namespace_sort.join(".");
+
+               events = jQuery.data(this, "events");
+               handlers = (events || {})[ event.type ];
 
                if ( events && handlers ) {
                        // Clone the handlers to prevent manipulation
 
                if ( events && handlers ) {
                        // Clone the handlers to prevent manipulation
@@ -380,14 +398,14 @@ jQuery.event = {
                                var handleObj = handlers[ j ];
 
                                // Filter the functions by class
                                var handleObj = handlers[ j ];
 
                                // Filter the functions by class
-                               if ( all || namespace.test( handleObj.namespace ) ) {
+                               if ( all || namespace_re.test( handleObj.namespace ) ) {
                                        // Pass in a reference to the handler function itself
                                        // So that we can later remove it
                                        event.handler = handleObj.handler;
                                        event.data = handleObj.data;
                                        event.handleObj = handleObj;
        
                                        // Pass in a reference to the handler function itself
                                        // So that we can later remove it
                                        event.handler = handleObj.handler;
                                        event.data = handleObj.data;
                                        event.handleObj = handleObj;
        
-                                       var ret = handleObj.handler.apply( this, arguments );
+                                       var ret = handleObj.handler.apply( this, args );
 
                                        if ( ret !== undefined ) {
                                                event.result = ret;
 
                                        if ( ret !== undefined ) {
                                                event.result = ret;
@@ -410,7 +428,7 @@ jQuery.event = {
        props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
 
        fix: function( event ) {
        props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
 
        fix: function( event ) {
-               if ( event[ expando ] ) {
+               if ( event[ jQuery.expando ] ) {
                        return event;
                }
 
                        return event;
                }
 
@@ -480,25 +498,14 @@ jQuery.event = {
 
                live: {
                        add: function( handleObj ) {
 
                live: {
                        add: function( handleObj ) {
-                               jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); 
+                               jQuery.event.add( this,
+                                       liveConvert( handleObj.origType, handleObj.selector ),
+                                       jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); 
                        },
 
                        remove: function( handleObj ) {
                        },
 
                        remove: function( handleObj ) {
-                               var remove = true,
-                                       type = handleObj.origType.replace(rnamespaces, "");
-                               
-                               jQuery.each( jQuery.data(this, "events").live || [], function() {
-                                       if ( type === this.origType.replace(rnamespaces, "") ) {
-                                               remove = false;
-                                               return false;
-                                       }
-                               });
-
-                               if ( remove ) {
-                                       jQuery.event.remove( this, handleObj.origType, liveHandler );
-                               }
+                               jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
                        }
                        }
-
                },
 
                beforeunload: {
                },
 
                beforeunload: {
@@ -507,9 +514,8 @@ jQuery.event = {
                                if ( this.setInterval ) {
                                        this.onbeforeunload = eventHandle;
                                }
                                if ( this.setInterval ) {
                                        this.onbeforeunload = eventHandle;
                                }
-
-                               return false;
                        },
                        },
+
                        teardown: function( namespaces, eventHandle ) {
                                if ( this.onbeforeunload === eventHandle ) {
                                        this.onbeforeunload = null;
                        teardown: function( namespaces, eventHandle ) {
                                if ( this.onbeforeunload === eventHandle ) {
                                        this.onbeforeunload = null;
@@ -521,10 +527,14 @@ jQuery.event = {
 
 var removeEvent = document.removeEventListener ?
        function( elem, type, handle ) {
 
 var removeEvent = document.removeEventListener ?
        function( elem, type, handle ) {
-               elem.removeEventListener( type, handle, false );
+               if ( elem.removeEventListener ) {
+                       elem.removeEventListener( type, handle, false );
+               }
        } : 
        function( elem, type, handle ) {
        } : 
        function( elem, type, handle ) {
-               elem.detachEvent( "on" + type, handle );
+               if ( elem.detachEvent ) {
+                       elem.detachEvent( "on" + type, handle );
+               }
        };
 
 jQuery.Event = function( src ) {
        };
 
 jQuery.Event = function( src ) {
@@ -544,10 +554,10 @@ jQuery.Event = function( src ) {
 
        // timeStamp is buggy for some events on Firefox(#3843)
        // So we won't rely on the native value
 
        // timeStamp is buggy for some events on Firefox(#3843)
        // So we won't rely on the native value
-       this.timeStamp = now();
+       this.timeStamp = jQuery.now();
 
        // Mark it as fixed
 
        // Mark it as fixed
-       this[ expando ] = true;
+       this[ jQuery.expando ] = true;
 };
 
 function returnFalse() {
 };
 
 function returnFalse() {
@@ -604,27 +614,24 @@ var withinElement = function( event ) {
        // Check if mouse(over|out) are still within the same parent element
        var parent = event.relatedTarget;
 
        // Check if mouse(over|out) are still within the same parent element
        var parent = event.relatedTarget;
 
-       // Traverse up the tree
-       while ( parent && parent !== this ) {
-               // Firefox sometimes assigns relatedTarget a XUL element
-               // which we cannot access the parentNode property of
-               try {
+       // Firefox sometimes assigns relatedTarget a XUL element
+       // which we cannot access the parentNode property of
+       try {
+               // Traverse up the tree
+               while ( parent && parent !== this ) {
                        parent = parent.parentNode;
                        parent = parent.parentNode;
-
-               // assuming we've left the element since we most likely mousedover a xul element
-               } catch(e) {
-                       break;
                }
                }
-       }
 
 
-       if ( parent !== this ) {
-               // set the correct event type
-               event.type = event.data;
+               if ( parent !== this ) {
+                       // set the correct event type
+                       event.type = event.data;
 
 
-               // handle event if we actually just moused on to a non sub-element
-               jQuery.event.handle.apply( this, arguments );
-       }
+                       // handle event if we actually just moused on to a non sub-element
+                       jQuery.event.handle.apply( this, arguments );
+               }
 
 
+       // assuming we've left the element since we most likely mousedover a xul element
+       } catch(e) { }
 },
 
 // In case of event delegation, we only need to rename the event.type,
 },
 
 // In case of event delegation, we only need to rename the event.type,
@@ -652,64 +659,65 @@ jQuery.each({
 // submit delegation
 if ( !jQuery.support.submitBubbles ) {
 
 // submit delegation
 if ( !jQuery.support.submitBubbles ) {
 
-jQuery.event.special.submit = {
-       setup: function( data, namespaces ) {
-               if ( this.nodeName.toLowerCase() !== "form" ) {
-                       jQuery.event.add(this, "click.specialSubmit", function( e ) {
-                               var elem = e.target, type = elem.type;
+       jQuery.event.special.submit = {
+               setup: function( data, namespaces ) {
+                       if ( this.nodeName.toLowerCase() !== "form" ) {
+                               jQuery.event.add(this, "click.specialSubmit", function( e ) {
+                                       var elem = e.target, type = elem.type;
 
 
-                               if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
-                                       return trigger( "submit", this, arguments );
-                               }
-                       });
+                                       if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+                                               return trigger( "submit", this, arguments );
+                                       }
+                               });
         
         
-                       jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
-                               var elem = e.target, type = elem.type;
+                               jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+                                       var elem = e.target, type = elem.type;
 
 
-                               if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
-                                       return trigger( "submit", this, arguments );
-                               }
-                       });
+                                       if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+                                               return trigger( "submit", this, arguments );
+                                       }
+                               });
 
 
-               } else {
-                       return false;
-               }
-       },
+                       } else {
+                               return false;
+                       }
+               },
 
 
-       teardown: function( namespaces ) {
-               jQuery.event.remove( this, "click.specialSubmit" );
-               jQuery.event.remove( this, "keypress.specialSubmit" );
-       }
-};
+               teardown: function( namespaces ) {
+                       jQuery.event.remove( this, ".specialSubmit" );
+               }
+       };
 
 }
 
 // change delegation, happens here so we have bind.
 if ( !jQuery.support.changeBubbles ) {
 
 
 }
 
 // change delegation, happens here so we have bind.
 if ( !jQuery.support.changeBubbles ) {
 
-var formElems = /textarea|input|select/i;
+       var formElems = /textarea|input|select/i,
 
 
-function getVal( elem ) {
-       var type = elem.type, val = elem.value;
+       changeFilters,
 
 
-       if ( type === "radio" || type === "checkbox" ) {
-               val = elem.checked;
+       getVal = function( elem ) {
+               var type = elem.type, val = elem.value;
 
 
-       } else if ( type === "select-multiple" ) {
-               val = elem.selectedIndex > -1 ?
-                       jQuery.map( elem.options, function( elem ) {
-                               return elem.selected;
-                       }).join("-") :
-                       "";
+               if ( type === "radio" || type === "checkbox" ) {
+                       val = elem.checked;
 
 
-       } else if ( elem.nodeName.toLowerCase() === "select" ) {
-               val = elem.selectedIndex;
-       }
+               } else if ( type === "select-multiple" ) {
+                       val = elem.selectedIndex > -1 ?
+                               jQuery.map( elem.options, function( elem ) {
+                                       return elem.selected;
+                               }).join("-") :
+                               "";
 
 
-       return val;
-}
+               } else if ( elem.nodeName.toLowerCase() === "select" ) {
+                       val = elem.selectedIndex;
+               }
+
+               return val;
+       },
 
 
-function testChange( e ) {
+       testChange = function testChange( e ) {
                var elem = e.target, data, val;
 
                if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
                var elem = e.target, data, val;
 
                if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
@@ -732,60 +740,61 @@ function testChange( e ) {
                        e.type = "change";
                        return jQuery.event.trigger( e, arguments[1], elem );
                }
                        e.type = "change";
                        return jQuery.event.trigger( e, arguments[1], elem );
                }
-}
+       };
 
 
-jQuery.event.special.change = {
-       filters: {
-               focusout: testChange, 
+       jQuery.event.special.change = {
+               filters: {
+                       focusout: testChange, 
 
 
-               click: function( e ) {
-                       var elem = e.target, type = elem.type;
+                       click: function( e ) {
+                               var elem = e.target, type = elem.type;
 
 
-                       if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
-                               return testChange.call( this, e );
-                       }
-               },
+                               if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+                                       return testChange.call( this, e );
+                               }
+                       },
 
 
-               // Change has to be called before submit
-               // Keydown will be called before keypress, which is used in submit-event delegation
-               keydown: function( e ) {
-                       var elem = e.target, type = elem.type;
+                       // Change has to be called before submit
+                       // Keydown will be called before keypress, which is used in submit-event delegation
+                       keydown: function( e ) {
+                               var elem = e.target, type = elem.type;
 
 
-                       if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
-                               (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
-                               type === "select-multiple" ) {
-                               return testChange.call( this, e );
+                               if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+                                       (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+                                       type === "select-multiple" ) {
+                                       return testChange.call( this, e );
+                               }
+                       },
+
+                       // Beforeactivate happens also before the previous element is blurred
+                       // with this event you can't trigger a change event, but you can store
+                       // information/focus[in] is not needed anymore
+                       beforeactivate: function( e ) {
+                               var elem = e.target;
+                               jQuery.data( elem, "_change_data", getVal(elem) );
                        }
                },
 
                        }
                },
 
-               // Beforeactivate happens also before the previous element is blurred
-               // with this event you can't trigger a change event, but you can store
-               // information/focus[in] is not needed anymore
-               beforeactivate: function( e ) {
-                       var elem = e.target;
-                       jQuery.data( elem, "_change_data", getVal(elem) );
-               }
-       },
-
-       setup: function( data, namespaces ) {
-               for ( var type in changeFilters ) {
-                       jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
-               }
+               setup: function( data, namespaces ) {
+                       if ( this.type === "file" ) {
+                               return false;
+                       }
 
 
-               return formElems.test( this.nodeName );
-       },
+                       for ( var type in changeFilters ) {
+                               jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+                       }
 
 
-       teardown: function( namespaces ) {
-               for ( var type in changeFilters ) {
-                       jQuery.event.remove( this, type + ".specialChange", changeFilters[type] );
-               }
+                       return formElems.test( this.nodeName );
+               },
 
 
-               return formElems.test( this.nodeName );
-       }
-};
+               teardown: function( namespaces ) {
+                       jQuery.event.remove( this, ".specialChange" );
 
 
-var changeFilters = jQuery.event.special.change.filters;
+                       return formElems.test( this.nodeName );
+               }
+       };
 
 
+       changeFilters = jQuery.event.special.change.filters;
 }
 
 function trigger( type, elem, args ) {
 }
 
 function trigger( type, elem, args ) {
@@ -823,7 +832,7 @@ jQuery.each(["bind", "one"], function( i, name ) {
                        return this;
                }
                
                        return this;
                }
                
-               if ( jQuery.isFunction( data ) ) {
+               if ( jQuery.isFunction( data ) || data === false ) {
                        fn = data;
                        data = undefined;
                }
                        fn = data;
                        data = undefined;
                }
@@ -919,9 +928,16 @@ jQuery.fn.extend({
        }
 });
 
        }
 });
 
+var liveMap = {
+       focus: "focusin",
+       blur: "focusout",
+       mouseenter: "mouseover",
+       mouseleave: "mouseout"
+};
+
 jQuery.each(["live", "die"], function( i, name ) {
        jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
 jQuery.each(["live", "die"], function( i, name ) {
        jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
-               var type, i = 0, match, namespaces,
+               var type, i = 0, match, namespaces, preType,
                        selector = origSelector || this.selector,
                        context = origSelector ? this : jQuery( this.context );
 
                        selector = origSelector || this.selector,
                        context = origSelector ? this : jQuery( this.context );
 
@@ -941,40 +957,52 @@ jQuery.each(["live", "die"], function( i, name ) {
                                type = type.replace( rnamespaces, "" );
                        }
 
                                type = type.replace( rnamespaces, "" );
                        }
 
-                       type = type === "focus" ? "focusin" : // focus --> focusin
-                                       type === "blur" ? "focusout" : // blur --> focusout
-                                       type === "hover" ? types.push("mouseleave" + namespaces) && "mouseenter" : // hover support
-                                       type;
+                       if ( type === "hover" ) {
+                               types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+                               continue;
+                       }
+
+                       preType = type;
 
 
-                       type += namespaces;
+                       if ( type === "focus" || type === "blur" ) {
+                               types.push( liveMap[ type ] + namespaces );
+                               type = type + namespaces;
+
+                       } else {
+                               type = (liveMap[ type ] || type) + namespaces;
+                       }
 
                        if ( name === "live" ) {
                                // bind live handler
 
                        if ( name === "live" ) {
                                // bind live handler
-                               context.each(function(){
-                                       jQuery.event.add( this, liveConvert( type, selector ),
-                                               { data: data, selector: selector, handler: fn, origType: type, origHandler: fn } );
-                               });
+                               for ( var j = 0, l = context.length; j < l; j++ ) {
+                                       jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
+                                               { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+                               }
 
                        } else {
                                // unbind live handler
 
                        } else {
                                // unbind live handler
-                               context.unbind( liveConvert( type, selector ), fn );
+                               context.unbind( "live." + liveConvert( type, selector ), fn );
                        }
                }
                
                return this;
                        }
                }
                
                return this;
-       }
+       };
 });
 
 function liveHandler( event ) {
 });
 
 function liveHandler( event ) {
-       var stop, elems = [], selectors = [], args = arguments,
-               related, match, handleObj, elem, j, i, l, data,
+       var stop, maxLevel, elems = [], selectors = [],
+               related, match, handleObj, elem, j, i, l, data, close, namespace,
                events = jQuery.data( this, "events" );
 
        // Make sure we avoid non-left-click bubbling in Firefox (#3861)
                events = jQuery.data( this, "events" );
 
        // Make sure we avoid non-left-click bubbling in Firefox (#3861)
-       if ( event.liveFired === this || !events || event.button && event.type === "click" ) {
+       if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
                return;
        }
 
                return;
        }
 
+       if ( event.namespace ) {
+               namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
+       }
+
        event.liveFired = this;
 
        var live = events.live.slice(0);
        event.liveFired = this;
 
        var live = events.live.slice(0);
@@ -993,20 +1021,23 @@ function liveHandler( event ) {
        match = jQuery( event.target ).closest( selectors, event.currentTarget );
 
        for ( i = 0, l = match.length; i < l; i++ ) {
        match = jQuery( event.target ).closest( selectors, event.currentTarget );
 
        for ( i = 0, l = match.length; i < l; i++ ) {
+               close = match[i];
+
                for ( j = 0; j < live.length; j++ ) {
                        handleObj = live[j];
 
                for ( j = 0; j < live.length; j++ ) {
                        handleObj = live[j];
 
-                       if ( match[i].selector === handleObj.selector ) {
-                               elem = match[i].elem;
+                       if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
+                               elem = close.elem;
                                related = null;
 
                                // Those two events require additional checking
                                related = null;
 
                                // Those two events require additional checking
-                               if ( handleObj.origType === "mouseenter" || handleObj.origType === "mouseleave" ) {
+                               if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+                                       event.type = handleObj.preType;
                                        related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
                                }
 
                                if ( !related || related !== elem ) {
                                        related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
                                }
 
                                if ( !related || related !== elem ) {
-                                       elems.push({ elem: elem, handleObj: handleObj });
+                                       elems.push({ elem: elem, handleObj: handleObj, level: close.level });
                                }
                        }
                }
                                }
                        }
                }
@@ -1014,13 +1045,23 @@ function liveHandler( event ) {
 
        for ( i = 0, l = elems.length; i < l; i++ ) {
                match = elems[i];
 
        for ( i = 0, l = elems.length; i < l; i++ ) {
                match = elems[i];
+
+               if ( maxLevel && match.level > maxLevel ) {
+                       break;
+               }
+
                event.currentTarget = match.elem;
                event.data = match.handleObj.data;
                event.handleObj = match.handleObj;
 
                event.currentTarget = match.elem;
                event.data = match.handleObj.data;
                event.handleObj = match.handleObj;
 
-               if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
-                       stop = false;
-                       break;
+               ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+               if ( ret === false || event.isPropagationStopped() ) {
+                       maxLevel = match.level;
+
+                       if ( ret === false ) {
+                               stop = false;
+                       }
                }
        }
 
                }
        }
 
@@ -1028,7 +1069,7 @@ function liveHandler( event ) {
 }
 
 function liveConvert( type, selector ) {
 }
 
 function liveConvert( type, selector ) {
-       return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
+       return (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
 }
 
 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
 }
 
 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
@@ -1036,8 +1077,15 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
        "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 
        // Handle event binding
        "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 
        // Handle event binding
-       jQuery.fn[ name ] = function( fn ) {
-               return fn ? this.bind( name, fn ) : this.trigger( name );
+       jQuery.fn[ name ] = function( data, fn ) {
+               if ( fn == null ) {
+                       fn = data;
+                       data = null;
+               }
+
+               return arguments.length > 0 ?
+                       this.bind( name, data, fn ) :
+                       this.trigger( name );
        };
 
        if ( jQuery.attrFn ) {
        };
 
        if ( jQuery.attrFn ) {