Different ways of executing element's event handler in the capturing phase - javascript

I can get elements to execute their handlers in the capturing phase like so:
elem.addEventListener('event', handler, {once: false, capture: true});
Setting the third argument to true also works - any obvious reason why? Does doing it this way have any side-effects?

The boolean parameter was the original way how it worked, before the options object was introduced. That's the reason why it (still) works: for backwards compatibility.
See docs:
Syntax
target.addEventListener(type, listener [, options]);
target.addEventListener(type, listener [, useCapture]);
You can either pass a boolean useCapture (this exists for a longer time already) or an options object which allows you to specify capture too but other things as well (e.g. once).
So, addEventListener(..., true) is the same as addEventListener(..., { capture: true }), and there are no side-effects.
The options object form exists since ~2016. Check on caniuse to see which clients support it.

If you don't have other event listeners that may do stuff to the event or page, then it generally doesn't matter where you attach your listener. If this is the only listener, you can attach it to the element, or one of its parents, or to the document or window, and to any of those in the bubbling phase or capturing phase - and it won't make a difference in most cases.
The primary use of a capturing listener is to set the order in which event handlers execute. When an event is dispatched to the element, it first captures downward from the window, firing capturing listeners on the window, then on the document, then on intermediate elements, until it reaches the deepest element that resulted in the event. At the deepest element, both capturing and bubbling listeners will run, in the order they were attached. Then, the event will start "bubbling" up, triggering bubbling listeners on that deepest element, then on intermediate elements, then on the document, and then on the window.
To illustrate, see how the capturing listener runs first here, when the listeners are attached to a parent:
document.addEventListener('click', () => console.log('bubbling'));
document.addEventListener('click', () => console.log('capturing (method 1)'), true);
document.addEventListener('click', () => console.log('capturing (method 2)'), { capture: true });
<button>click</button>
If the element the listener is being attached to is the same element that dispatches the event (for example, if you have a button with no children, which gets clicked), then capturing vs bubbling has no effect - all listeners will run in the order they were attached, regardless of useCapture.
Bubbling listeners can be used to prevent the event from bubbling upward and triggering parent listeners. Similarly, capturing listeners can prevent the event from capturing downward and triggering child listeners.
window.addEventListener('click', (e) => {
e.stopPropagation();
console.log('capturing, stopPropagation')
}, true);
document.querySelector('button').addEventListener('click', () => console.log('at target'));
<button>click</button>
Above, the capturing listener called stopPropagation on the event, preventing it from propagating downward to the child listener, which would've run later were it not for stopPropagation.
For the third argument to addEventListener, you can either use { capture: useCapture } or just useCapture as the argument, per the specification:
The addEventListener(type, callback, options) method, when invoked, must run these steps:
Let capture, passive, and once be the result of flattening more options.
Where "flattening more" does:
Let capture be the result of flattening options.
Where "flattening" does:
If options is a boolean, then return options.
Return options’s capture.

Related

window scroll event – need prevent bubbling or not?

Which of these examples is more correct?
window.addEventListener('scroll', someFunc, false);
window.addEventListener('scroll', someFunc);
I know what is bubbling, it moves up from element to window. But what about any events on window – should we use callback false for this or not?
It looks like nonsense in this case, because the event has nowhere to go up, but I want to be sure.
The third parameter useCapture specifies whether the event should be executed in the capturing or in the bubbling phase.
If it should be executed later than element event handlers, you have to use false(default).
If it should be executed earlier than element event handlers, you have to use true.
If no child elements have event listener, you can ignore the useCapture parameter.

e.stopPropogation() Equivalent for Capture Phase of Click Event?

I'm looking for a way in JS to stop a click event from continuing down the DOM to a nested child element (capture phase) when the parent element was clicked.
It would be the inverse of the e.stopPropogation() function to prevent a click event from bubbling up.
Is there a native JS function for this?
Edit 03/10
Link to example
Edit 03/11
Typo in the function call - it's stopPropagation(), not stopPropogation(). Thanks to #JackPattishall for the find.
yes there is native js function for capturing event in capture phase.
In all browsers, except IE<9, there are two stages of event processing.
The event first goes down - that’s called capturing, and then bubbles up. This behavior is standartized in W3C specification.
All methods of event handling ignore the caputiring phase. Using addEventListener with last argument true is only the way to catch the event at capturing.
elem.addEventListener( type, handler, phase )
phase = true
The handler is set on the capturing phase.
phase = false
The handler is set on the bubbling phase.
For better understanding of event capturing and bubbling you can follow this link
okey, One thing you and do is use the stopPropogation() at the top in Dom.
eg. you have a table(#table1) and elements(tr,td).
so, if i do:
table1.addEventListener("click",function(event){
event.stopPropagation();
console.log(this);
},true);
tableElem[2].addEventListener("click",function(event){
console.log(this);
});
tableElem[2].addEventListener("click",function(event){
console.log("hii");
});
The event will be intercepted at top and propogation will be stopped.
stopPropogation() stops propagation irrespective of on which step event is intercepted.

How to catch event that was stopPropagation

For example we have a page with a link that has onclick event listener on it. But handler makes stopPropagation. How I can handle that click event was made, if it's not bubble to root anymore?
e.g.
document.addEventListener('click', function(e) {console.log(e);});
a.onclick = function(e) {e.stopPropagation();};
DOM event propagation works in three phases: the capture phase, the target phase and the bubble phase. Roughly, the event first works its way down to the target, reaches the target and then works its way back up.
By default, event handlers are attached in the final bubble phase. If you attach a click event listener in the first capture phase, it will run before the previous handler has had the chance to call stopPropagation.
See this question for a deeper explanation.
The simple answer is, add a third argument, true, when adding your event listener.
document.addEventListener('click', someFunction, true)
This flag (called useCapture) will call someFunction on all clicks in a document, even when the user clicked inside an element with a click handler that called event.stopPropagation.
With options
If you're already passing an object of options as the third argument, simply include capture: true in them:
document.addEventListener('click', someFunction, { capture: true, ...someMoreOptions })
Why?
Enabling the handler's useCapture mode like this means the listener listens during the earlier "capture" phase of the event (which starts at the outmost element then trickles down through children), instead of the later "bubble" phase (which starts at the innermost element and bubbles back up through ancestors, and is the one stopPropagation blocks).
Side effects
That also means that applying this setting changes the timing: your capture phase click event will occur before any click events of either type inside child or descendant elements.
For example, in the above function, if a user clicks on a button on the page, the someFunction attached to the document's capture phase will be called before any handlers attached to the button; whereas without setting use capture to true, you'd expect it to be called after.

difference between true and false in javascript eventlistener

i have a doubt in eventlistener concept.What is the difference between bellow two codes
i have doubt in the true/false section.no change happens when i replace the 1st code with the second code in my practice code.
a.addEventListener("click", modifyText, true);
a.addEventListener("click", modifyText, false);
true and false in addEventListener is Boolean that specifies whether the event needs to be captured or not.
Here's the syntax and detail:
object.addEventListener (eventName, function, useCapture);
eventName: String that specifies the name of the event to listen for. This parameter is case sensitive!
function: Represents the event listener function to be called when the event occurs.
When an event occurs, an event object is initialized and passed to the event handler as the first parameter. The type of the event object depends on the current event.
useCapture: Boolean that specifies whether the event needs to be captured or not.
One of the following values:
false -> Register the event handler for the bubbling phase.
true -> Register the event handler for the capturing phase.
Bubbling and Capturing Phases:
bubbling: the event object propagates through the target's ancestors in reverse order, starting with the target's parent and ending with the defaultView. This phase is also known as the bubbling phase. Event listeners registered for this phase must handle the event after it has reached its target.
capturing: the event object must propagate through the target's ancestors from the defaultView to the target's parent. This phase is also known as the capturing phase. Event listeners registered for this phase must handle the event before it reaches its target.
For more detail on event flow: DOM Event Architecture
Just have a look at some docu, e.g. MDN on addEventListener:
target.addEventListener(type, listener[, useCapture]);
useCapture
If true, useCapture indicates that the user wishes to initiate capture. After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. Events which are bubbling upward through the tree will not trigger a listener designated to use capture. See DOM Level 3 Events for a detailed explanation. Note that this parameter is not optional in all browser versions. If not specified, useCapture is false.
So basically it decides whether the event is handled in the capture or the bubble phase of event processing.
As long as no of the element's parents (or children) have any similar events attached, there is no real difference.

Event listeners to the same event target which is called first

If I register two event listeners to the same event target. Which event handler will be called first?
Example:
document.addEventListener("click", function() {
// do something 1
}, true); // using the capturing phase
document.addEventListener("click", function() {
// do something 2
}, true); // using the capturing phase
I do not found my answer in the w3c specification.
DOM-Level-3-Events
Bold emphasis added to answer the question (via the w3c specification: http://www.w3.org/TR/DOM-Level-3-Events/#event-phase)
First, the implementation must determine the current target. This must be the next pending event target in the partial propagation path, starting with the first. From the perspective of an event listener this must be the event target the listener has been registered on.
Next, the implementation must determine the current target's candidate event listeners. This must be the list of all event listeners that have been registered on the current target in their order of registration. [HTML5] defines the ordering of listeners registered through event handler attributes. Once determined, the candidate event listeners must not be changed; adding or removing listeners does not affect the current target's candidate event listeners.
Finally, the implementation must process all candidate event handlers in order and trigger each handler if all the following conditions are met...
I have personally always relied on this behavior, and I have not seen a modern browser behave differently than the spec describes.

Categories

Resources