diff options
author | Pierre Spring <pierre@nelm.io> | 2017-06-13 18:22:08 +0200 |
---|---|---|
committer | Timmy Willison <4timmywil@gmail.com> | 2017-07-10 11:55:32 -0400 |
commit | 490db839fb08a9b461e77dbe0138c7e6045aacd8 (patch) | |
tree | 0699ed90c27e478000bd1d5bfe03f3eb5b5e364d | |
parent | 0bf499ca24982714c816a836345c027939ccb3c6 (diff) | |
download | jquery-490db839fb08a9b461e77dbe0138c7e6045aacd8.tar.gz jquery-490db839fb08a9b461e77dbe0138c7e6045aacd8.zip |
Event: `stopPropagation()` on native event-handler
Fixes gh-3693
Close gh-3694
-rw-r--r-- | src/event/trigger.js | 21 | ||||
-rw-r--r-- | test/unit/event.js | 41 |
2 files changed, 58 insertions, 4 deletions
diff --git a/src/event/trigger.js b/src/event/trigger.js index ef391370f..c3b048026 100644 --- a/src/event/trigger.js +++ b/src/event/trigger.js @@ -10,18 +10,21 @@ define( [ "use strict"; -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/; +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; jQuery.extend( jQuery.event, { trigger: function( event, data, elem, onlyHandlers ) { - var i, cur, tmp, bubbleType, ontype, handle, special, + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, eventPath = [ elem || document ], type = hasOwn.call( event, "type" ) ? event.type : event, namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - cur = tmp = elem = elem || document; + cur = lastElement = tmp = elem = elem || document; // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { @@ -93,7 +96,7 @@ jQuery.extend( jQuery.event, { // Fire handlers on the event path i = 0; while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - + lastElement = cur; event.type = i > 1 ? bubbleType : special.bindType || type; @@ -136,7 +139,17 @@ jQuery.extend( jQuery.event, { // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + jQuery.event.triggered = undefined; if ( tmp ) { diff --git a/test/unit/event.js b/test/unit/event.js index 0c379d051..30e057a80 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -440,6 +440,47 @@ QUnit.test( "on bubbling, isDefaultPrevented, stopImmediatePropagation", functio $anchor2[ 0 ].removeEventListener( "click", neverCallMe ); } ); +QUnit.test( "triggered events stopPropagation() for natively-bound events", function( assert ) { + assert.expect( 1 ); + + var $button = jQuery( "#button" ), + $parent = $button.parent(), + neverCallMe = function() { + assert.ok( false, "propagation should have been stopped" ); + }, + stopPropagationCallback = function( e ) { + assert.ok( true, "propagation is stopped" ); + e.stopPropagation(); + }; + + $parent[ 0 ].addEventListener( "click", neverCallMe ); + $button.on( "click", stopPropagationCallback ); + $button.trigger( "click" ); + $parent[ 0 ].removeEventListener( "click", neverCallMe ); + $button.off( "click", stopPropagationCallback ); +} ); + +QUnit.test( "trigger() works with events that were previously stopped", function( assert ) { + assert.expect( 0 ); + + var $button = jQuery( "#button" ), + $parent = $button.parent(), + neverCallMe = function() { + assert.ok( false, "propagation should have been stopped" ); + }; + + $parent[ 0 ].addEventListener( "click", neverCallMe ); + $button.on( "click", neverCallMe ); + + var clickEvent = jQuery.Event( "click" ); + clickEvent.stopPropagation(); + $button.trigger( clickEvent ); + + $parent[ 0 ].removeEventListener( "click", neverCallMe ); + $button.off( "click", neverCallMe ); +} ); + + QUnit.test( "on(), iframes", function( assert ) { assert.expect( 1 ); |