]> source.dussan.org Git - jquery.git/commitdiff
Avoid collateral damage when removing bindType/delegateType special events.
authorDave Methvin <dave.methvin@gmail.com>
Fri, 11 Nov 2011 02:53:07 +0000 (21:53 -0500)
committerDave Methvin <dave.methvin@gmail.com>
Fri, 11 Nov 2011 02:53:07 +0000 (21:53 -0500)
src/event.js
test/unit/event.js

index cd946dadb404dc092c8be4812853474ebde50849..e957075639c02084aa18f04f9401bfb36a5eaa61 100644 (file)
@@ -151,7 +151,7 @@ jQuery.event = {
        remove: function( elem, types, handler, selector ) {
 
                var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
-                       t, tns, type, namespaces, origCount,
+                       t, tns, type, origType, namespaces, origCount,
                        j, events, special, handle, eventType, handleObj;
 
                if ( !elemData || !(events = elemData.events) ) {
@@ -162,7 +162,7 @@ jQuery.event = {
                types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
                for ( t = 0; t < types.length; t++ ) {
                        tns = rtypenamespace.exec( types[t] ) || [];
-                       type = tns[1];
+                       type = origType = tns[1];
                        namespaces = tns[2];
 
                        // Unbind all events (on this namespace, if provided) for the element
@@ -181,22 +181,21 @@ jQuery.event = {
                        namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
 
                        // Only need to loop for special events or selective removal
-                       if ( handler || namespaces || selector || special.remove ) {
+                       if ( handler || namespaces || selector || special.remove || origType !== type ) {
                                for ( j = 0; j < eventType.length; j++ ) {
                                        handleObj = eventType[ j ];
 
-                                       if ( !handler || handler.guid === handleObj.guid ) {
-                                               if ( !namespaces || namespaces.test( handleObj.namespace ) ) {
-                                                       if ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) {
-                                                               eventType.splice( j--, 1 );
-
-                                                               if ( handleObj.selector ) {
-                                                                       eventType.delegateCount--;
-                                                               }
-                                                               if ( special.remove ) {
-                                                                       special.remove.call( elem, handleObj );
-                                                               }
-                                                       }
+                                       if ( origType === handleObj.origType &&
+                                                ( !handler || handler.guid === handleObj.guid ) &&
+                                                ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+                                                ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+                                               eventType.splice( j--, 1 );
+
+                                               if ( handleObj.selector ) {
+                                                       eventType.delegateCount--;
+                                               }
+                                               if ( special.remove ) {
+                                                       special.remove.call( elem, handleObj );
                                                }
                                        }
                                }
index 0852554ebd355c2a4bfd30607f6b7326fe9eac03..dbfc5d90987ecd051448b5785d45246800c2ae9b 100644 (file)
@@ -1146,7 +1146,7 @@ test(".trigger() bubbling on disconnected elements (#10489)", function() {
                        ok( true, "click fired on div" );
                })
                .find( "p" )
-                       .on( "click", function() { 
+                       .on( "click", function() {
                                ok( true, "click fired on p" );
                        })
                        .click()
@@ -1203,7 +1203,7 @@ test("jQuery.Event( type, props )", function() {
 
 test("jQuery.Event.currentTarget", function(){
        expect(2);
-       
+
        jQuery('<div><p><button>shiny</button></p></div>')
                .on( "click", "p", function( e ){
                                equal( e.currentTarget, this, "Check delegated currentTarget on event" );
@@ -2101,7 +2101,7 @@ test(".delegate()/.undelegate()", function() {
 
 test("jQuery.off using dispatched jQuery.Event", function() {
        expect(1);
-       
+
        var markup = jQuery( '<p><a href="#">target</a></p>' ),
                count = 0;
        markup
@@ -2115,7 +2115,7 @@ test("jQuery.off using dispatched jQuery.Event", function() {
 
 test("stopPropagation() stops directly-bound events on delegated target", function() {
        expect(1);
-       
+
        var markup = jQuery( '<div><p><a href="#">target</a></p></div>' );
        markup
                .on( "click", function() {
@@ -2296,7 +2296,7 @@ test("Non DOM element events", function() {
 
 test("inline handler returning false stops default", function() {
        expect(1);
-       
+
        var markup = jQuery('<div><a href="#" onclick="return false">x</a></div>');
        markup.click(function(e) {
                ok( e.isDefaultPrevented(), "inline handler prevented default");
@@ -2461,15 +2461,50 @@ test(".on and .off", function() {
        jQuery("#onandoff").remove();
 });
 
+test("special bind/delegate name mapping", function() {
+       expect( 7 );
+
+       jQuery.event.special.slap = {
+               bindType: "click",
+               delegateType: "swing",
+               handle: function( event ) {
+                       equal( event.handleObj.origType, "slap", "event type is correct for " + event.type );
+                       equal( event.target.id, "mammy", "slapped your mammy" );
+               }
+       };
+
+       var comeback = function( event ) {
+                       ok( true, "event " + event.type + " triggered" );
+       };
+
+       jQuery( '<div><button id="mammy">Are We Not Men?</button></div>' )
+               .on( "slap", "button", jQuery.noop )
+               .on( "swing", "button", comeback )
+               .find( "button" )
+                       .on( "slap", jQuery.noop )
+                       .on( "click", comeback )
+                       .trigger( "click" )             // bindType-slap and click
+                       .off( "slap" )
+                       .trigger( "click" )             // click
+                       .off( "click" )
+                       .trigger( "swing" )             // delegateType-slap and swing
+               .end()
+               .off( "slap swing" )
+               .find( "button " )                      // everything should be gone
+                       .trigger( "slap" )
+                       .trigger( "click" )
+                       .trigger( "swing" )
+               .end();
+});
 
 test(".on and .off, selective mixed removal (#10705)", function() {
        expect(7);
 
        var clockout = 0,
-               timingx = function( e ) { 
+               timingx = function( e ) {
                        ok( true, "triggered " + e.type );
                };
-       
+
        jQuery( '<p>Strange Pursuit</p>' )
                .on( "click", timingx )
                .on( "click.duty", timingx )