The capturing phase does not get interrupted because in modern browsers events are registered by default in the bubbling phase (so the onclick()
event in your <div>
element does not interact with the separate event handler you registered in the capturing phase).
I am not aware of a way to register a capturing phase event handler via an html attribute (other than in certain older browsers where events were registered by default in the capturing phase).
See the snippet below for a modified version of your code that I think is probably what you originally intended. You will see that this code calls stopPropagation()
inside both the capturing phase and bubbling phase handlers (and results in the expected outcome in both cases).
for (const elem of document.querySelectorAll('*')) {
elem.addEventListener('click', (event) => {
if (elem.tagName === 'DIV') {
event.stopPropagation();
}
console.log(`Capturing: ${elem.tagName}`);
}, true);
elem.addEventListener('click', (event) => {
if (elem.tagName === 'DIV') {
event.stopPropagation();
}
console.log(`Bubbling: ${elem.tagName}`);
});
}
<form>
form
<div>
div (click here)
<p>p</p>
</div>
</form>
In the capturing phase, the browser processes the handlers starting with the outermost parent, so it does not encounter stopPropagation()
until it has already processed the click
handlers for all the parent elements <html>
, <body>
, etc.
In the bubbling phase, it processes the event handlers starting with the clicked element moving outward through the parent elements.