Added support for multiple live event handlers, live hover, and live focus/blur ...
[jquery.git] / src / event.js
index 6871327..0128dc5 100644 (file)
@@ -57,6 +57,12 @@ jQuery.event = {
                        handle = jQuery.data( elem, "handle", eventHandle );
                }
 
+               // If no handle is found then we must be trying to bind to one of the
+               // banned noData elements
+               if ( !handle ) {
+                       return;
+               }
+
                // Add elem as a property of the handle function
                // This is to prevent a memory leak with non-native
                // event in IE.
@@ -422,6 +428,8 @@ jQuery.event = {
                                jQuery.extend( proxy, data || {} );
 
                                proxy.guid += data.selector + data.live; 
+                               data.liveProxy = proxy;
+
                                jQuery.event.add( this, data.live, liveHandler, data ); 
                                
                        },
@@ -662,9 +670,9 @@ function testChange( e ) {
                        jQuery.data( elem, "_change_data", val );
                }
 
-               if ( elem.type !== "select" && (data != null || val) ) {
+               if ( data != null || val ) {
                        e.type = "change";
-                       return jQuery.event.trigger( e, arguments[1], this );
+                       return jQuery.event.trigger( e, arguments[1], elem );
                }
 }
 
@@ -755,12 +763,10 @@ jQuery.each(["bind", "one"], function( i, name ) {
                        for ( var key in type ) {
                                this[ name ](key, data, type[key], fn);
                        }
-
                        return this;
                }
                
                if ( jQuery.isFunction( data ) ) {
-                       thisObject = fn;
                        fn = data;
                        data = undefined;
                }
@@ -770,17 +776,11 @@ jQuery.each(["bind", "one"], function( i, name ) {
                        return fn.apply( this, arguments );
                }) : fn;
 
-               if ( type === "unload" && name !== "one" ) {
-                       this.one( type, data, fn, thisObject );
-
-               } else {
-                       // Deprecated: Please don't expect an empty jQuery set to bind to document
-                       (!this.selector && !this.context ? jQuery(document) : this).each(function() {
+               return type === "unload" && name !== "one" ?
+                       this.one( type, data, fn ) :
+                       this.each(function() {
                                jQuery.event.add( this, type, handler, data );
                        });
-               }
-
-               return this;
        };
 });
 
@@ -794,20 +794,14 @@ jQuery.fn.extend({
                        return this;
                }
 
-               // Deprecated: Please don't expect an empty jQuery set to bind to document
-               (!this.selector && !this.context ? jQuery(document) : this).each(function() {
+               return this.each(function() {
                        jQuery.event.remove( this, type, fn );
                });
-
-               return this;
        },
        trigger: function( type, data ) {
-               // Deprecated: Please don't expect an empty jQuery set to bind to document
-               (!this.selector && !this.context ? jQuery(document) : this).each(function() {
+               return this.each(function() {
                        jQuery.event.trigger( type, data, this );
                });
-
-               return this;
        },
 
        triggerHandler: function( type, data ) {
@@ -844,32 +838,52 @@ jQuery.fn.extend({
 
        hover: function( fnOver, fnOut ) {
                return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
-       },
+       }
+});
+
+jQuery.each(["live", "die"], function( i, name ) {
+       jQuery.fn[ name ] = function( types, data, fn ) {
+               var type, i = 0;
 
-       live: function( type, data, fn ) {
                if ( jQuery.isFunction( data ) ) {
                        fn = data;
                        data = undefined;
                }
 
-               jQuery( this.context ).bind( liveConvert( type, this.selector ), {
-                       data: data, selector: this.selector, live: type
-               }, fn );
+               types = types.split( /\s+/ );
 
-               return this;
-       },
+               while ( (type = types[ i++ ]) ) {
+                       type = type === "focus" ? "focusin" : // focus --> focusin
+                                       type === "blur" ? "focusout" : // blur --> focusout
+                                       type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
+                                       type;
+                       
+                       if ( name === "live" ) {
+                               // bind live handler
+                               jQuery( this.context ).bind( liveConvert( type, this.selector ), {
+                                       data: data, selector: this.selector, live: type
+                               }, fn );
 
-       die: function( type, fn ) {
-               jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
+                       } else {
+                               // unbind live handler
+                               jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
+                       }
+               }
+               
                return this;
        }
 });
 
 function liveHandler( event ) {
-       var stop = true, elems = [], selectors = [], args = arguments,
-               related, match, fn, elem, j, i, data,
+       var stop, elems = [], selectors = [], args = arguments,
+               related, match, fn, elem, j, i, l, data,
                live = jQuery.extend({}, jQuery.data( this, "events" ).live);
 
+       // Make sure we avoid non-left-click bubbling in Firefox (#3861)
+       if ( event.button && event.type === "click" ) {
+               return;
+       }
+
        for ( j in live ) {
                fn = live[j];
                if ( fn.live === event.type ||
@@ -923,7 +937,7 @@ function liveConvert( type, selector ) {
        return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "&")].join(".");
 }
 
-jQuery.each( ("blur focus load resize scroll unload click dblclick " +
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 
@@ -932,8 +946,8 @@ jQuery.each( ("blur focus load resize scroll unload click dblclick " +
                return fn ? this.bind( name, fn ) : this.trigger( name );
        };
 
-       if ( jQuery.fnAttr ) {
-               jQuery.fnAttr[ name ] = true;
+       if ( jQuery.attrFn ) {
+               jQuery.attrFn[ name ] = true;
        }
 });