Skip to content
Permalink
Browse files

Avoid collateral damage when removing bindType/delegateType special e…

…vents.
  • Loading branch information...
dmethvin committed Nov 11, 2011
1 parent 5ba7f60 commit 774eba33881093efa592d350a831ca1a812428a8
Showing with 56 additions and 22 deletions.
  1. +14 −15 src/event.js
  2. +42 −7 test/unit/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 );
}
}
}
@@ -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 )

0 comments on commit 774eba3

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.