Add .delegate() and .undelegate(). An alternative to using .live() which goes from...
[jquery.git] / src / event.js
index 2978bc6..f6b3d31 100644 (file)
@@ -187,6 +187,9 @@ jQuery.event = {
 
                                                namespace = new RegExp("(^|\\.)" + 
                                                        jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
+
+                                       } else {
+                                               namespaces = [];
                                        }
 
                                        var special = this.special[ type ] || {};
@@ -208,21 +211,17 @@ jQuery.event = {
                                                }
 
                                                if ( special.remove ) {
-                                                       special.remove.call( elem, namespaces || [], fn);
+                                                       special.remove.call( elem, namespaces, fn);
                                                }
 
                                                // remove generic event handler if no more handlers exist
                                                for ( ret in events[ type ] ) {
-
                                                        break;
                                                }
+
                                                if ( !ret ) {
                                                        if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
-                                                               if ( elem.removeEventListener ) {
-                                                                       elem.removeEventListener( type, elemData.handle, false );
-                                                               } else if ( elem.detachEvent ) {
-                                                                       elem.detachEvent( "on" + type, elemData.handle );
-                                                               }
+                                                               removeEvent( elem, type, elemData.handle );
                                                        }
 
                                                        ret = null;
@@ -330,9 +329,12 @@ jQuery.event = {
 
                } else if ( !event.isDefaultPrevented() ) {
                        var target = event.target, old,
-                               isClick = jQuery.nodeName(target, "a") && type === "click";
+                               isClick = jQuery.nodeName(target, "a") && type === "click",
+                               special = jQuery.event.special[ type ] || {};
+
+                       if ( (!special._default || special._default.call( elem, event ) === false) && 
+                               !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 
-                       if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
                                try {
                                        if ( target[ type ] ) {
                                                // Make sure that we don't accidentally re-trigger the onFOO events
@@ -523,6 +525,14 @@ jQuery.event = {
        }
 };
 
+var removeEvent = document.removeEventListener ?
+       function( elem, type, handle ) {
+               elem.removeEventListener( type, handle, false );
+       } : 
+       function( elem, type, handle ) {
+               elem.detachEvent( "on" + type, handle );
+       };
+
 jQuery.Event = function( src ) {
        // Allow instantiation without the 'new' keyword
        if ( !this.preventDefault ) {
@@ -856,6 +866,20 @@ jQuery.fn.extend({
 
                return this;
        },
+       
+       delegate: function( selector, types, data, fn ) {
+               return this.live( types, data, fn, selector );
+       },
+       
+       undelegate: function( selector, types, fn ) {
+               if ( arguments.length === 0 ) {
+                               return this.unbind( "live" );
+               
+               } else {
+                       return this.die( types, null, fn, selector );
+               }
+       },
+       
        trigger: function( type, data ) {
                return this.each(function() {
                        jQuery.event.trigger( type, data, this );
@@ -900,8 +924,10 @@ jQuery.fn.extend({
 });
 
 jQuery.each(["live", "die"], function( i, name ) {
-       jQuery.fn[ name ] = function( types, data, fn ) {
-               var type, i = 0;
+       jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+               var type, i = 0,
+                       selector = origSelector || this.selector,
+                       context = origSelector ? this : jQuery( this.context );
 
                if ( jQuery.isFunction( data ) ) {
                        fn = data;
@@ -918,13 +944,13 @@ jQuery.each(["live", "die"], function( i, name ) {
                        
                        if ( name === "live" ) {
                                // bind live handler
-                               jQuery( this.context ).bind( liveConvert( type, this.selector ), {
-                                       data: data, selector: this.selector, live: type
+                               context.bind( liveConvert( type, selector ), {
+                                       data: data, selector: selector, live: type
                                }, fn );
 
                        } else {
                                // unbind live handler
-                               jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
+                               context.unbind( liveConvert( type, selector ), fn ? { guid: fn.guid + selector + type } : null );
                        }
                }
                
@@ -992,7 +1018,7 @@ function liveHandler( event ) {
 }
 
 function liveConvert( type, selector ) {
-       return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
+       return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
 }
 
 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +