DecPK
DecPK

Reputation: 25408

Does stopPropagation() stops executing the event from capture phase?

This image is taken from DOM ENLIGHTENMENT book. It says stopPropagation() will stop the capture and bubble event flow phases.

DOM enlightment book snippet

I know stopPropagation() will stop propagation and won't execute the callback function in the bubbling phase.

But in the following code snippet after using the stopPropagation() on the button, the body event callback method is still executed.

Does stopPropagation() also stop the event flow phase in the capture phase also?

const button = document.querySelector('button');

document.body.addEventListener('click', e => {
  console.log('Body event triggered');
}, true);

button.addEventListener('click', e => {
  console.log('button is clicked 1');
});

button.addEventListener('click', e => {
  e.stopPropagation();
  console.log('button is clicked 2');
});

button.addEventListener('click', e => {
  console.log('button is clicked 3');
});
<button> click me </button>

Upvotes: 0

Views: 222

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074595

But in the following code snippet after using the stopPropagation() on the button, the body event callback method is still executed.

All your button click handlers are target/bubbling handlers, not capture handlers. At the point you're calling stopPropagation, the capture phase is already done. If you had a target/bubbling handler on document.body, you'd see that it wasn't called.

Note that propagation relates to moving from one element to its parent (bubbling) or descendant (capture) but doesn't affect processing other handlers on the same element, which is why your handler calling stopPropgation didn't stop the other handlers on button both firing. (If you'd used stopImmediatePropagation, you would have stopped the third handler because it stops things right away, even in the middle of the current element's handlers.)

Here's an example cancelling propagation during the capture phase:

const div = document.getElementById("middle");
const button = document.getElementById("button");

// Capture phase on body
document.body.addEventListener("click", e => {
    console.log("body capture handler");
}, true);

// Target/bubbling phase on body
document.body.addEventListener("click", e => {
    console.log("body target/bubbling handler");
});

// Capture phase on middle
middle.addEventListener("click", e => {
    console.log("middle capture handler - stopping propagation");
    e.stopPropagation();
}, true);

// Target/bubbling phase on middle
middle.addEventListener("click", e => {
    console.log("middle target/bubbling handler");
});

// Capture phase on button
button.addEventListener("click", e => {
    console.log("button capture handler");
}, true);

// Target/bubbling phase on button
button.addEventListener("click", e => {
    console.log("button target/bubbling handler");
});
<div id="middle">
    <input type="button" id="button" value="Click me">
</div>

Notice that:

  1. The capture phase handler on button didn't fire, because propagation was stopped before it got there; and

  2. None of the target/bubbling phase handlers fired, since propagation was stopped before the target phase (and thus before the bubbling phase).

I find this diagram from the DOM3 Events spec really useful for picturing this stuff:

enter image description here

Upvotes: 2

Related Questions