diff --git a/src/core.js b/src/core.js index db988a9b5c..3df7623810 100644 --- a/src/core.js +++ b/src/core.js @@ -785,6 +785,8 @@ jQuery.extend({ return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; + proxy.context = context; + // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; diff --git a/src/event.js b/src/event.js index 9ff6fae831..cd474e18b6 100644 --- a/src/event.js +++ b/src/event.js @@ -221,7 +221,7 @@ jQuery.event = { for ( j = pos || 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; - if ( handler.guid === handleObj.guid ) { + if ( handler.guid === handleObj.guid && ( ( handler.context && handler.context === handleObj.handler.context ) || !handler.context ) ) { // remove the given handler for the given type if ( all || namespace.test( handleObj.namespace ) ) { if ( pos == null ) { diff --git a/test/unit/event.js b/test/unit/event.js index 4e475da066..690f2b24c8 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -2209,6 +2209,50 @@ test("custom events with colons (#3533, #8272)", function() { }); +test("Unbind proxied functions (#9278)", function() { + expect(4); + + var result = []; + + function eventHandler() { + result.push(this.name); + } + + var eventSource = {}; + + var firstContext = { name: 'Marx Brothers' }; + var secondContext = { name: 'Team Possible' }; + + var eventHandler$firstContext = jQuery.proxy(eventHandler, firstContext); + var eventHandler$secondContext = jQuery.proxy(eventHandler, secondContext); + + // no handlers + jQuery(eventSource).triggerHandler('customEvent'); + equals(result.length, 0, 'No handlers bound'); + + // 3 handlers bound (1 of the first, 2 of the second) + jQuery(eventSource).bind('customEvent', eventHandler$firstContext); + jQuery(eventSource).bind('customEvent', eventHandler$secondContext); + jQuery(eventSource).bind('customEvent', eventHandler$secondContext); + jQuery(eventSource).triggerHandler('customEvent'); + ok(result.length === 3 && + result[0] === firstContext.name && + result[1] === secondContext.name && + result[2] === secondContext.name, 'All three proxies get triggered'); + result.length = 0; + + // unbind second one + jQuery(eventSource).unbind('customEvent', eventHandler$secondContext); + jQuery(eventSource).triggerHandler('customEvent'); + ok(result.length === 1 && result[0] === firstContext.name, 'Remaining proxy get triggered'); + result.length = 0; + + // unbind remaining handler + jQuery(eventSource).unbind('customEvent', eventHandler$firstContext); + jQuery(eventSource).triggerHandler('customEvent'); + equals(result.length, 0, 'No handlers remaining'); +}); + (function(){ // This code must be run before DOM ready! var notYetReady, noEarlyExecution,