From 84d2307e0e20e9245523731a4450314cc0de6a95 Mon Sep 17 00:00:00 2001 From: Dave Methvin Date: Mon, 24 Oct 2011 11:17:24 -0400 Subject: [PATCH] Fix #10563. Ensure event.currentTarget==this if delegated. Now, event.delegateTarget is always the element where the event was handled, regardless of whether delegated handlers are attached. --- src/event.js | 10 +++++----- test/unit/event.js | 38 +++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/event.js b/src/event.js index 488d3bae9..a6cd82379 100644 --- a/src/event.js +++ b/src/event.js @@ -412,7 +412,7 @@ jQuery.event = { // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; - event.currentTarget = this; + event.delegateTarget = this; // Determine handlers that should run if there are delegated events // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) @@ -447,8 +447,11 @@ jQuery.event = { handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); } + // Run delegates first; they may want to stop propagation beneath us for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { handleObj = matched.matches[ j ]; @@ -456,9 +459,6 @@ jQuery.event = { // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; event.data = handleObj.data; event.handleObj = handleObj; @@ -929,7 +929,7 @@ jQuery.fn.extend({ if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event var handleObj = types.handleObj; - jQuery( types.currentTarget ).off( + jQuery( types.delegateTarget ).off( handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, handleObj.selector, handleObj.handler diff --git a/test/unit/event.js b/test/unit/event.js index bb622f577..ef2bc19c8 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -1060,7 +1060,7 @@ test("trigger(eventObject, [data], [fn])", function() { // Tries bubbling equals( e.type, "foo", "Verify event type when passed passing an event object" ); equals( e.target.id, "child", "Verify event.target when passed passing an event object" ); - equals( e.currentTarget.id, "par", "Verify event.target when passed passing an event object" ); + equals( e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object" ); equals( e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object" ); }); @@ -1160,18 +1160,20 @@ test("jQuery.Event( type, props )", function() { }); test("jQuery.Event.currentTarget", function(){ - expect(1); - - var counter = 0, - $elem = jQuery("").click(function(e){ - equals( e.currentTarget, this, "Check currentTarget on "+(counter++?"native":"fake") +" event" ); - }); - - // Fake event - $elem.trigger("click"); - - // Cleanup - $elem.unbind(); + expect(2); + + jQuery('

') + .on( "click", "p", function( e ){ + equals( e.currentTarget, this, "Check delegated currentTarget on event" ); + }) + .find( "button" ) + .on( "click", function( e ){ + equals( e.currentTarget, this, "Check currentTarget on event" ); + }) + .click() + .off( "click" ) + .end() + .off( "click" ); }); test("toggle(Function, Function, ...)", function() { @@ -1253,7 +1255,7 @@ test("toggle(Function, Function, ...)", function() { }); test(".live()/.die()", function() { - expect(65); + expect(66); var submit = 0, div = 0, livea = 0, liveb = 0; @@ -1476,7 +1478,8 @@ test(".live()/.die()", function() { // Test this, target and currentTarget are correct jQuery("span#liveSpan1").live("click", function(e){ equals( this.id, "liveSpan1", "Check the this within a live handler" ); - equals( e.currentTarget, document, "Check the event.currentTarget within a live handler" ); + equals( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a live handler" ); + equals( e.delegateTarget, document, "Check the event.delegateTarget within a live handler" ); equals( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a live handler" ); }); @@ -1784,7 +1787,7 @@ test("live with special events", function() { }); test(".delegate()/.undelegate()", function() { - expect(64); + expect(65); var submit = 0, div = 0, livea = 0, liveb = 0; @@ -2008,7 +2011,8 @@ test(".delegate()/.undelegate()", function() { // Test this, target and currentTarget are correct jQuery("#body").delegate("span#liveSpan1", "click", function(e){ equals( this.id, "liveSpan1", "Check the this within a delegate handler" ); - equals( e.currentTarget, document.body, "Check the event.currentTarget within a delegate handler" ); + equals( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a delegate handler" ); + equals( e.delegateTarget, document.body, "Check the event.delegateTarget within a delegate handler" ); equals( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a delegate handler" ); }); -- 2.39.5