Unable to understand useCapture parameter in addEventListener
Events can be activated at two occasions: At the beginning ("capture"), and at the end ("bubble").
Events are executed in the order of how they're defined. Say, you define 4 event listeners:
window.addEventListener("click", function(){console.log(1)}, false);window.addEventListener("click", function(){console.log(2)}, true);window.addEventListener("click", function(){console.log(3)}, false);window.addEventListener("click", function(){console.log(4)}, true);
useCapture in addEventListener behaves strangely
Bubbling/capturing only relevant when an event bubbles/captures to a target element, not when the event is triggered directly on that element (this is the "target phase" of W3C events model). In the case that there is no "bubble" or "capture" — which is the case with the click
event on your <button>
— the events are processed in the order they are added.
For example, if you were to reverse the order of the listeners on your "wrapper" and click on the wrapper element (not the button) you would notice the same behavior (bubble would fire first):
// 1. "Wrapper Bubble" 2. "Wrapper Capture"
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);
However, if you were to use the same order (bubble before capture) and click on the button
the capture will fire before bubble. This is because the "click" event is being triggered on the button
and is "captured down" through the dom before "bubbling up" (the normal event flow).
I've created a JSBIN that will hopefully help clarify this (however, it may just add to the confusion). The "ordered" button / div triggers the order of your 1st snippet, and the "unordered" button and div use the order in you 2nd.
For additional info see this SO answer and the W3C Event Flow documentation, specifically the Target Phase.
EventTarget.addEventListener()'s useCapture argument use?
I think this diagram from the DOM events specification pretty much says it all:
Basically: The useCapture
argument is used to receive notification during the capture phase, rather than the bubbling phase. A capturing-phase handler will be called before any bubbling-phase handler. Note that Internet Explorer didn't support the capturing phase prior to IE9.
So a better example is two handlers on the same element, in the middle (but let's do all three levels for completeness):
hook("container", "- ");hook("wrapper", " - ");hook("testBtn", " - ");
function hook(id, prefix) { var element = document.getElementById(id); element.addEventListener("click", function(e) { display(id + "'s capturing handler called", prefix); }, true); element.addEventListener("click", function(e) { display(id + "'s bubbling called", prefix); }, false);}
function display(msg, prefix) { var p = document.createElement('p'); p.innerHTML = (prefix || "") + msg; document.body.appendChild(p);}
#container, #wrapper { padding : 10px; border : 1px solid green;}p { font-family: sans-serif; padding: 0; margin: 0;}
<div id="container"> <div id="wrapper"> <button id="testBtn">A button</button> </div></div>
What does the third parameter (false) indicate in document.addEventListener(deviceready,OnDeviceReady,false);
It's 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
registeredlistener
before being
dispatched to anyEventTarget
s 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.
Using event listener should we use useCapture as false to support old browser or it will be used as default for every browser
As mentioned in the docs:
Note:
useCapture
has not always been optional. Ideally, you should include it for the widest possible browser compatibility.
So yes, you should set it to false
to support a vast diversity of clients.
Also, you need to know when you might want to set it to true
. Let's say you are listening for blur
event on a single input textbox, then you can keep it as false
like:
const blog = document.querySelector('#blog');
blog.addEventListener('blur', function (event) {
// Your logic here...
}, false);
But, if you want to listen to all blur
events in the document
, then you should set it to true
like:
document.addEventListener('blur', function (event) {
// Your logic here...
}, true);
As, setting it to true
help us to take advantage of event bubbling for events that otherwise don't support it like focus
, blur
, etc. Basically it is false
for most used events, thus this param is optional
in modern browsers and its defaults to false
.
Why is 'false' used after this simple addEventListener function?
I checked MDN too, but I still didn't understand what the useCapture
was for, so this answer is for those who still don't get it after having checked the official documentation.
So first of all, the following happens in almost all browers:
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.
which means no matter what you set the useCapture
to, these two event phases always exist.
This picture shows how it works.
According to this model, the event:
Captures down - through 1 -> 2 -> 3.
Bubbles up - through 3 -> 2 -> 1.
Then comes your question. The 3rd param called useCapture
indicates on which of the two phases you want your handler to handle the event.
useCapture = true
The handler is set on the capturing phase. Events will get to it before getting to its children.
useCapture = false
.The handler is set on the bubbling phase. Events will get to it after getting to its children.
which means that if you write code like this:
child.addEventListener("click", second);
parent.addEventListener("click", first, true);
when clicking child element, first
method will be called before second
.
By default, the useCapture
flag is set to false which means you handler will only be called during event bubbling phase.
For detailed info, click this reference link and this.
Passing parameters in addEventListener
When the browser calls the event handler, this
will refer to the element, not your instance.
You need to save a copy of the desired this
in a separate variable:
var self = this;
var func = function(e) { self.onTitleChange (e); };
var target = content.document.getElementsByTagName('TITLE')[0];
target.addEventListener('DOMSubtreeModified', func, false);
Related Topics
What Does Arrow Function '() => {}' Mean in JavaScript
Firebase -> Date Order Reverse
How to Check If the React Component Is Unmounted
Sorting Objects by Property Values
Create an Instance of a Class in Es6 with a Dynamic Name
Why the Function Called by Settimeout Has No Callstack Limit
Three.Js:2Xmeshes Using Same Vector as Position
How to Check If an Object Has a Key in JavaScript
Function to Convert Timestamp to Human Date in JavaScript
How to Shuffle the Characters in a String in JavaScript
Node.Js: Read a Text File into an Array. (Each Line an Item in the Array.)
Normalizing Mousewheel Speed Across Browsers
Calling a JSON API with Node.Js
How to Check If an Element Is Overlapping Other Elements
How to Check If the Url Contains a Given String
JavaScript Runtime Complexity of Array Functions
Using Chrome, How to Find to Which Events Are Bound to an Element