stopPropagation vs. stopImmediatePropagation
Asked Answered
D

10

461

What's the difference between event.stopPropagation() and event.stopImmediatePropagation()?

Devinne answered 14/3, 2011 at 14:12 Comment(1)
I encourage the reader not just to stick to the accepted answer, but also to read the others, especially that of Robert Siemer which is very enlightening. A good knowledge of how propagation works is needed to well understand it.Dhobi
P
409

stopPropagation will prevent any parent handlers from being executed stopImmediatePropagation will prevent any parent handlers and also any other handlers from executing

Quick example from the jquery documentation:

$("p").click(function(event) {
  event.stopImmediatePropagation();
});

$("p").click(function(event) {
  // This function won't be executed
  $(this).css("background-color", "#f00");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>example</p>

Note that the order of the event binding is important here!

$("p").click(function(event) {
  // This function will now trigger
  $(this).css("background-color", "#f00");
});

$("p").click(function(event) {
  event.stopImmediatePropagation();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>example</p>
Progenitor answered 14/3, 2011 at 14:19 Comment(3)
You emphasize “parent”, but in reality both also stops entering children as well if called in the capture phase! See my answer for details.Grenadine
Is it possible to prevent other handlers but not parent handlers?Seaweed
@AndrewFount Yes, if you have full control over the code: move the relevant handlers to the capture phase, which comes before the bubble phase and allows you to interrupt the call chain on the way down (and not on the way up).Grenadine
G
141

Surprisingly, all other answers only say half the truth or are actually wrong!

  • e.stopImmediatePropagation() stops any further handler from being called for this event, no exceptions
  • e.stopPropagation() is similar, but does still call all handlers for this phase on this element if not called already

What phase?

E.g. a click event will always first go all the way down the DOM (called “capture phase”), finally reach the origin of the event (“target phase”) and then bubble up again (“bubble phase”). And with addEventListener() you can register multiple handlers for both capture and bubble phase independently. (Target phase calls handlers of both types on the target without distinguishing.)

And this is what the other answers are incorrect about:

  • quote: “event.stopPropagation() allows other handlers on the same element to be executed”
    • correction: if stopped in the capture phase, bubble phase handlers will never be reached, also skipping them on the same element
  • quote: “event.stopPropagation() [...] is used to stop executions of its corresponding parent handler only”
    • correction: if propagation is stopped in the capture phase, handlers on any children, including the target aren’t called either, not only parents
    • ...and: if propagation is stopped in the bubble phase, all capture phase handlers have already been called, including those on parents

A fiddle and mozilla.org event phase explanation with demo.

Grenadine answered 26/3, 2020 at 7:1 Comment(7)
hi @Robert Siemer + 1 excellent answer - Target phase calls handlers of both types on the target without distinguishing - That means that the target phase is executed 2 times, once for the capture phase and once for the bubbling phase, right? (assuming I don't use stopPropagation or stopImmediatePropagation).Kigali
@Coder23 No, not right.—The list of handlers of the target element will only be visited once. And all handlers will be called, ignoring the boolean which otherwise decides if it will be called on the way down or up. I.e. an earlier registered handler will be called earlier, even if that boolean is False indicating “bubble phase”. While a later registered handler showing True (“capture phase”) will be called after that.Grenadine
hi @Robert Siemer +1, by way of summary, they work the same in the sense of at what stage the propagation stops, correct? The difference is that stopImmediatePropagation() stops the "pending" handlers of the same event of the element in question, while stopPropagation() does not, only the further handlers of other elements, ALL THIS CONSIDERING THE PHASE, right?Harp
i.e. both stop one phase (or even both in case the stop was in capturing phase) @Robert SiemerHarp
@GeorgeMeijer I think “yes”, but am not sure whether I understood you correctly. Both stop event handling, but not necessarily on “phase borders”. The phases don’t overlap. By the number of elements visited, the capture phase is (usually) a long phase with many elements to visit. The target phase is only for one element. Then the bubble phase (usually) revisits all elements visited in the capture phase but in reverse order.—So a handler on an element in the “middle” off the capture phase can “stop” 2.5 phases, so to say: Half the capture phase will be skipped, so will target and bubble phase.Grenadine
@GeorgeMeijer ...and that is the same with both stop...Propagation(). (The “non-immediate” version only allows the rest of the handlers on this element to run normal, before cutting short.)Grenadine
thank you @Robert Siemer +2, now I understand, this is the best explanation for this questionHarp
B
64

A small example to demonstrate how both these propagation stoppages work.

var state = {
  stopPropagation: false,
  stopImmediatePropagation: false
};

function handlePropagation(event) {
  if (state.stopPropagation) {
    event.stopPropagation();
  }

  if (state.stopImmediatePropagation) {
    event.stopImmediatePropagation();
  }
}

$("#child").click(function(e) {
  handlePropagation(e);
  console.log("First event handler on #child");
});


$("#child").click(function(e) {
  handlePropagation(e);
  console.log("Second event handler on #child");
});

// First this event will fire on the child element, then propogate up and
// fire for the parent element.
$("div").click(function(e) {
  handlePropagation(e);
  console.log("Event handler on div: #" + this.id);
});


// Enable/disable propogation
$("button").click(function() {
  var objectId = this.id;
  $(this).toggleClass('active');
  state[objectId] = $(this).hasClass('active');
  console.log('---------------------');
});
div {
  padding: 1em;
}

#parent {
  background-color: #CCC;
}

#child {
  background-color: #000;
  padding: 5em;
}

button {
  padding: 1em;
  font-size: 1em;
}

.active {
  background-color: green;
  color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
  <div id="child">&nbsp;</div>
</div>

<button id="stopPropagation">Stop Propogation</button>
<button id="stopImmediatePropagation" ">Stop Immediate Propogation</button>

There are three event handlers bound. If we don’t stop any propagation, then there should be four alerts - three on the child div, and one on the parent div.

If we stop the event from propagating, then there will be 3 alerts (all on the inner child div). Since the event won’t propagate up the DOM hierarchy, the parent div won’t see it, and its handler won’t fire.

If we stop propagation immediately, then there will only be 1 alert. Even though there are three event handlers attached to the inner child div, only 1 is executed and any further propagation is killed immediately, even within the same element.

Blackthorn answered 26/3, 2012 at 22:37 Comment(1)
Both stopPropagation() variants will also stop propagating down the DOM hierarchy. Not just up. Please check my answer for details with the capture phase.Grenadine
E
38

I am a late comer, but maybe I can say this with a specific example:

Say, if you have a <table>, with <tr>, and then <td>. Now, let's say you set 3 event handlers for the <td> element, then if you do event.stopPropagation() in the first event handler you set for <td>, then all event handlers for <td> will still run, but the event just won't propagate to <tr> or <table> (and won't go up and up to <body>, <html>, document, and window).

Now, however, if you use event.stopImmediatePropagation() in your first event handler, then, the other two event handlers for <td> WILL NOT run, and won't propagate up to <tr>, <table> (and won't go up and up to <body>, <html>, document, and window).

Note that it is not just for <td>. For other elements, it will follow the same principle.

Elastance answered 24/1, 2016 at 10:34 Comment(0)
S
34

event.stopPropagation will prevent handlers on parent elements from running.
Calling event.stopImmediatePropagation will also prevent other handlers on the same element from running.

Sequestered answered 14/3, 2011 at 14:13 Comment(1)
Worth mentioning is that event handlers are executed in the order in which they have been attached to the element.Passer
R
30

From the jQuery API:

In addition to keeping any additional handlers on an element from being executed, this method also stops the bubbling by implicitly calling event.stopPropagation(). To simply prevent the event from bubbling to ancestor elements but allow other event handlers to execute on the same element, we can use event.stopPropagation() instead.

Use event.isImmediatePropagationStopped() to know whether this method was ever called (on that event object).

In short: event.stopPropagation() allows other handlers on the same element to be executed, while event.stopImmediatePropagation() prevents every event from running.

Rectal answered 14/3, 2011 at 14:14 Comment(3)
Just to be sure, the native javascript version of event.stopImmediatePropagation doesn't stop bubbling right?Fiorenza
It does, bubbling is when the event is propagated to the parent elements, stopImmediatePropagation stops the event from being propagated period, both of them should prevent bubbling, it's worth nothing that you can also change the mode to capture which will trigger the outermost elements first and only then go down to the children (bubbling is the default, and works in the opposite direction)Crosshatch
Not exact, to say the least. Stopping in the capture phase will not allow bubble handlers on the same element to be executed as explained in my answer.Grenadine
E
14

Here is a demo to illustrate the difference:

document.querySelectorAll("button")[0].addEventListener('click', e=>{
  e.stopPropagation();
  alert(1);
});
document.querySelectorAll("button")[1].addEventListener('click', e=>{
  e.stopImmediatePropagation();
  alert(1);
});
document.querySelectorAll("button")[0].addEventListener('click', e=>{
  alert(2);
});
document.querySelectorAll("button")[1].addEventListener('click', e=>{
  alert(2);
});
<div onclick="alert(3)">
   <button>1...2</button>
   <button>1</button>
</div>

Notice that you can attach multiple event handlers to an event on an element.

Eckman answered 27/9, 2020 at 19:17 Comment(2)
So the difference here is that since the div is the parent of the button that got clicked, stopPropagation() makes sure that 3 is never alerted, whereas stopImmediatePropagation() makes sure that not even other event listeners registered on the button itself, i.e. 2, are executed.Chlordane
I think its best representation of difference, gjDefaulter
F
12

1)event.stopPropagation(): =>It is used to stop executions of its corresponding parent handler only.

2) event.stopImmediatePropagation(): => It is used to stop the execution of its corresponding parent handler and also handler or function attached to itself except the current handler. => It also stops all the handler attached to the current element of entire DOM.

Here is the example: Jsfiddle!

Thanks, -Sahil

Flask answered 30/3, 2017 at 10:3 Comment(0)
D
2

event.stopPropagation() allows other handlers on the same element to be executed, while event.stopImmediatePropagation() prevents every event from running. For example, see below jQuery code block.

$("p").click(function(event)
{ event.stopImmediatePropagation();
});
$("p").click(function(event)
{ // This function won't be executed 
$(this).css("color", "#fff7e3");
});

If event.stopPropagation was used in previous example, then the next click event on p element which changes the css will fire, but in case event.stopImmediatePropagation(), the next p click event will not fire.

Dispensary answered 12/2, 2014 at 14:12 Comment(0)
S
2

Here I am adding my JSfiddle example for stopPropagation vs stopImmediatePropagation. JSFIDDLE

let stopProp = document.getElementById('stopPropagation');
let stopImmediate = document.getElementById('stopImmediatebtn');
let defaultbtn = document.getElementById("defalut-btn");


stopProp.addEventListener("click", function(event){
	event.stopPropagation();
  console.log('stopPropagation..')
  
})
stopProp.addEventListener("click", function(event){
  console.log('AnotherClick')
  
})
stopImmediate.addEventListener("click", function(event){
		event.stopImmediatePropagation();
    console.log('stopimmediate')
})

stopImmediate.addEventListener("click", function(event){
    console.log('ImmediateStop Another event wont work')
})

defaultbtn.addEventListener("click", function(event){
    alert("Default Clik");
})
defaultbtn.addEventListener("click", function(event){
    console.log("Second event defined will also work same time...")
})
div{
  margin: 10px;
}
<p>
The simple example for event.stopPropagation and stopImmediatePropagation?
Please open console to view the results and click both button.
</p>
<div >
<button id="stopPropagation">
stopPropagation-Button
</button>
</div>
<div  id="grand-div">
  <div class="new" id="parent-div">
    <button id="stopImmediatebtn">
    StopImmediate
    </button>
  </div>
</div>
<div>
<button id="defalut-btn">
Normat Button
</button>
</div>
Swum answered 7/6, 2018 at 14:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.