]> source.dussan.org Git - jquery.git/commitdiff
Event: `stopPropagation()` on native event-handler
authorPierre Spring <pierre@nelm.io>
Tue, 13 Jun 2017 16:22:08 +0000 (18:22 +0200)
committerTimmy Willison <4timmywil@gmail.com>
Mon, 10 Jul 2017 15:55:32 +0000 (11:55 -0400)
Fixes gh-3693
Close gh-3694

src/event/trigger.js
test/unit/event.js

index ef391370f0c3a46fcfb68f79e9bd3a947b34ca84..c3b048026d62d9f36fd394921d7090d7b5b7472b 100644 (file)
@@ -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 ) {
index 0c379d051d3ff1356c5c1a4767fdd887747016b9..30e057a80d971ee8502ba080e74966ee950f858d 100644 (file)
@@ -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 );