From: Dave Methvin Date: Fri, 11 Nov 2011 02:53:07 +0000 (-0500) Subject: Avoid collateral damage when removing bindType/delegateType special events. X-Git-Tag: 1.7.1rc1~19 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=774eba33881093efa592d350a831ca1a812428a8;p=jquery.git Avoid collateral damage when removing bindType/delegateType special events. --- diff --git a/src/event.js b/src/event.js index cd946dadb..e95707563 100644 --- a/src/event.js +++ b/src/event.js @@ -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 ); } } } diff --git a/test/unit/event.js b/test/unit/event.js index 0852554eb..dbfc5d909 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -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('

') .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( '

target

' ), 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( '

target

' ); 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('
x
'); 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( '
' ) + .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( '

Strange Pursuit

' ) .on( "click", timingx ) .on( "click.duty", timingx )