Event Capturing vs Event Bubbling [duplicate] - javascript

This question already has answers here:
What is event bubbling and capturing?
(9 answers)
Closed 2 years ago.
I just wanted to get the general consensus on which is a better mode of event delegation in JS between bubbling and capturing.
Now I understand that depending on a particular use-case, one might want to use capturing phase over bubbling or vice versa but I want to understand what delegation mode is preferred for most general cases and why (to me it seems bubbling mode).
Or to put it in other words, is there a reason behind W3C addEventListener implementation to favor the bubbling mode. [capturing is initiated only when you specify the 3rd parameter and its true. However, you can forget that 3rd param and bubbling mode is kicked in]
I looked up the JQuery's bind function to get an answer to my question and it seems it doesn't even support events in capture phase (it seems to me because of IE not support capturing mode).
So looks like bubbling mode is the default choice but why?

In the past it was a platform issue, Internet Explorer had a bubbling model, and Netscape was more about capturing (yet supported both).
The W3C model calls for you be able to choose which one you want.
I think bubbling is more popular because, as stated there are some platforms that only support bubbling...and it sort of makes sense as a "default" mode.
Which one you choose is largely a product of what you are doing and what makes sense to you.

While reading JavaScript: The Definitive Guide, 5th Edition, I came across Example 17-4 on page 422 that defines a function for dragging absolutely positioned elements. In the example, the function drag() is called in the onmousedown attribute of a document element. The function repositions the element based on the change in location of the mouse which is queried by handlers added to the root document element for captured mousemove and mouseup events. They capture these events on the document for the following reason:
It is important to note that the mousemove and mouseup handlers are registered as capturing event handlers because the user may move the mouse faster than the document element can follow it, and some of these events occur outside the original target element.
This suggests an advantage in quicker response when capturing events.

This test suggests there is a slight performance advantage to using capture over bubble. Even without killing the event as soon as it is handled, however when left it was marginal. I suppose a complex DOM would exaggerate the performance difference between the two.

This link gives the clear explanation- https://www.quirksmode.org/js/events_order.html
You, the web developer, can choose whether to register an event handler in the capturing or in the bubbling phase. This is done through the addEventListener() method explained on the Advanced models page. If its last argument is true the event handler is set for the capturing phase, if it is false the event handler is set for the bubbling phase.
Suppose you do
element1.addEventListener('click',doSomething2,true)
element2.addEventListener('click',doSomething,false)
If the user clicks on element2 the following happens:
The click event starts in the capturing phase. The event looks if any ancestor element of element2 has a onclick event handler for the capturing phase.
The event finds one on element1. doSomething2() is executed.
The event travels down to the target itself, no more event handlers for the capturing phase are found. The event moves to its bubbling phase and executes doSomething(), which is registered to element2 for the bubbling phase.
The event travels upwards again and checks if any ancestor element of the target has an event handler for the bubbling phase. This is not the case, so nothing happens.
The reverse would be
element1.addEventListener('click',doSomething2,false)
element2.addEventListener('click',doSomething,false)
Now if the user clicks on element2 the following happens:
The click event starts in the capturing phase. The event looks if any ancestor element of element2 has a onclick event handler for the capturing phase and doesn’t find any.
The event travels down to the target itself. The event moves to its bubbling phase and executes doSomething(), which is registered to element2 for the bubbling phase.
The event travels upwards again and checks if any ancestor element of the target has an event handler for the bubbling phase.
The event finds one on element1. Now doSomething2() is executed.
Compatibility with traditional model
In the browsers that support the W3C DOM, a traditional event registration
element1.onclick = doSomething2;
is seen as a registration in the bubbling phase.
Use of event bubbling
Few web developers consciously use event capturing or bubbling. In Web pages as they are made today, it is simply not necessary to let a bubbling event be handled by several different event handlers. Users might get confused by several things happening after one mouse click, and usually you want to keep your event handling scripts separated. When the user clicks on an element, something happens, when he clicks on another element, something else happens.
Of course this might change in the future, and it’s good to have models available that are forward compatible. But the main practical use of event capturing and bubbling today is the registration of default functions.

I'm not certain but I'm pretty sure that anything you can do with bubbling you can do with capturing and vice versa.
The idea that you'd have some events bubbling and some capturing in the same app sounds like a good way to make things very confusing. What I'm saying is, I don't think bubbling versus capturing really matters. What matters is that you pick one and stick with it.
W3C's APIs often contain this sort of thing where they have a lot of features that nobody really cares about. Perhaps this is another example of how good defaults can remove the need for configuration or even whole features.

Related

Event Listener Capture and Bubbling Phase Events

I have had this question in my mind for a while after reading many tutorials and posts on SO, none have been able to give me the mental model needed to get past this block.
Here is an excerpt from a terrific blog post about the Browser Events:
When we click the anchor tag, the DOM calculates the Capture Phase path, firing all the Capture Phase event handlers of the root document, body, div and anchor tags (in that order), and then it turns around and fires all of the Bubble Phase event handlers in the reverse order of the Capture Phase.
Here is the snippet of code described in the quote:
<html>
<head>
</head>
<body>
<div id="myDiv">
<a id="myAnchor"
href="http://bitovi.com/">bitovi!
</a>
</div>
</body>
</html>
Here is what I don't understand. Many explanations talk about the Capture and Bubble phases as walking down and up the DOM, which I understand. I don't understand how "all" the events are fired while walking down the tree in the capture phase and then all the bubble events are fired going up the tree. What is "all" a reference to? Is it all the events on the page? Are they fired "silently" and since they aren't where the actual click event occurred they don't execute, the only event actually fired is the element that was clicked, the rest of the events are just stored for some reason?
Later in the blog post, this other explanation also confuses me and is related to my misunderstanding about the reference to "all the events":
This is describing what happens during the Execution of the Capture Phase Events:
Now, we loop through all of the elements that we just collected (and
flipped around). A few things we need to do here:
We need to check if event.stopPropagation() was called by one of the event handlers fired (see the last step of this bulleted list). If it
was, just break out of this loop – we don’t need to iterate through
the rest of the list.
Next, we check to see if there were any Capture Phase event handlers set for the DOM node currently being evaluated.
Finally, loop through all of the handlers we collected and execute them in the context of the node currently being evaluated.
I'm confused by the last two bullet points. "Check if any Capture Phase event handlers set for the DOM node currently being evaluated". I generally understand how the event handlers are set with the addEventListener method. Here is where the confusion is:
"Loop through all of the handlers that were collected and execute them in the context of the node currently being evaluated".
Are all the handlers on the page collected and executed? If the event had the stop.prop event or did was not set on the dom node the event was triggered on, will the event not fire?
Sorry if this question is confusing, I will try to clarify anything that does not make sense. Thanks!
Not all the events, all the event handlers¹. There's only one event fired in the description, a single click event. That event is passed to each event listener attached to the elements identified in the capture/bubble chain, unless it is stopped from doing so by stopPropagation() (or stopImmediatePropagation()).
¹ Pedantically, they are event listeners. Event handlers "act as non-capture event listeners for the object on which they are specified."

Bubbling and Capturing in context of addEventListener() method in javascript

in addEventListner(event,function,useCapture) method, useCapture parameter is two type bubbling and capturing.
My question is what is the function/operation of this useCapture parameter in context of js addEventListener() method?
This diagram from the DOM events specification may help shed some light:
As you can see from that, there are three phases to an event: The capturing phase, which originates at the very top level view and works its way down to the descendant element the event is aimed at, then the target phase which occurs just on the target element, and finally the bubbling phase where it goes back up the hierarchy back to the root view.
The vast majority of the time, you only need or want to work with the bubbling phase (and IE didn't even support the capturing phase until IE9). Whether this is necessarily because it's more useful is a question; we're all just really used to it, and it's been the focus of continued innovation (cancelling bubbling and such), because (again) for years and years it was the only game in town if you wanted to support IE. And it does make good sense, but then, so does capturing.
The reason this exists is primarily a quirk of history. Very early on, of course, there were not specifications for this, and the dominant browsers at the time (Netscape Navigator and Microsoft Internet Explorer) both made up what they did with events. Netscape went with the "starts at the root and makes its way to the final target" (capturing) approach, Microsoft went with the "starts at the target and works its way to the root" (bubbling) approach. So when it came time to standardize this, the DOM committee decided to go with...both.
The third parameter(useCapture) of the addEventListener() method is decided in which way
the event is propagated in the html DOM.
this parameter has an boolean value,false indicates bubbling and true indicates capturing.
It is optional parameter and its default value is false.
Event propagation is a way of defining the element order when an event occurs.
Suppose you have a h1 element inside a div element.Now if user clicks the h1 element,
then which element's "click" event will be handled first?
In bubbling the inner most element's event will be handle first then the outer.
i.e.h1 element's "click" event will be handled first, then the div element's event will be handled.
In capturing the outer most element's event will be handle first then the inner.
i.e.div element's "click" event will be handled first, then the h1 element's event will be handled.

What does the third parameter (false) indicate in document.addEventListener("deviceready",OnDeviceReady,false); [duplicate]

This question already has answers here:
Why is 'false' used after this simple addEventListener function?
(3 answers)
Closed 9 years ago.
What does the third parameter (false) indicate in
document.addEventListener("deviceready",OnDeviceReady,false);
Can any one show an example script to show the difference
This is for historical reasons. When the browser event system was first designed, there were two conflicting ways of modelling how it worked. They were called event capture and event bubbling.
Take for instance, this HTML:
<html>
<body>
Content
</body>
</html>
If an event (e.g. a click) happens on the a element, should the ancestor elements know? It was widely accepted that they should. But the question was in what order they should be notified. The Microsoft and Netscape developers (this should give you an idea of quite how historical we're talking!) had differing opinions.
One model was event capture (advocated by the Netscape developers). This notified the html element first and worked its way down the tree:
html
body
a
The other model was event bubbling (advocated by the Microsoft developers). This notified the target element first, and worked its way up the tree:
a
body
html
The eventual compromise was that it should do both.
html (capture phase)
body (capture phase)
a (capture phase)
a (bubbling phase)
body (bubbing phase)
html (bubbling phase)
So the event works its way down the tree and then back up again.
This is a long-winded way of getting to addEventListener. addEventListener listens for both capture phase and bubbling phase events. The third parameter (called useCapture in the specification) allows the programmer to specify which phase they want to use.
In modern browsers, this defaults to false. You will probably never come across a circumstance where you want to use the capturing phase, especially as Internet Explorer still doesn't support it. But old browsers need the false to be explicit, so it is generally provided for backwards-compatibility.
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
registered listener before being
dispatched to any EventTargets 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.

Should I attach my .on('click') event to the document or element

Yesterday I was reading the jQuery docs for .on() where was stated:
Avoid excessive use of document or document.body for delegated events on large documents
But today, I was looking at this JSPERF and I notice a better performance when the click event is attached to the document.
So right now, I'm confused. The performance tests speak against the docs?
Your JSPerf here is testing the speed to attach events, not the effect that they have on cumulative page performance. This is the wrong thing to test!
Javascript events propagate up the DOM all the way to the document root. This means that if you have an on("click", ...) handler on document, then every click on every element in the document will end up running an event handler, so jQuery can test if its origin matches the delegate target, to see if it should be passed to that event handler.
Imagine that your page has 10 different delegated event handlers on document, all handling various clicks. Every time you click any element in the page, the event will bubble up to the document root, and all 10 of those handlers have to be tested to figure out which (if any) should be run.
In general, you want your delegated events to be as deep in the tree as possible while still enabling your functionality, since this limits the number of elements that may invoke this event, and you can handle the event earlier to prevent it from propagating up the DOM tree.
It depends.
You can attach handler to any element you want, of course, and in some cases you will have to attach it to document or body (if you, for example, want to target all the links on the page). But, if you are sure that certain elements will always appear only inside given element (which is already created) - then for performance sake, you can attach event handler to that common parent.
The point is excessive.
IMHO excessive delegates on any DOM is terrible

Event propagation in Javascript

If I have an element (html) nested in another element and both of them have a click handler attached, clicking the inner element executes its click handler and then bubbles up to the parent and executes its click handler. That's how I understand it.
Do events bubble up the DOM tree if there are no events attached that are the same and if so, is it worth putting a event.stopPropagation() at the end of every handler to stop this and speed things up?
events almost always bubble up unless event.cancelBubble=true is set or event.stopPropagation() is used. You are only aware of it, though, when one of your event
handlers gets tripped.
See http://en.wikipedia.org/wiki/DOM_events for a list of events which bubble. (Note: in the table of HTML events, cancelable refers to the effectiveness of event.preventDefault() or return false to cancel the default action, not bubbling)
Also see http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow, in particular 1.2.1 Basic Flow to understand the capture phase and bubbling phase of event propagation.
EDIT
http://mark-story.com/posts/view/speed-up-javascript-event-handling-with-event-delegation-and-bubbling suggests there is a performance gain by stopping propagation but provides no data.
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/a9af0aa4216a8046 suggests that browsers should be optimized for bubbling behaviour and says there should be no significant performance difference. Again no data.
http://developer.yahoo.com/performance/rules.html#events provides a good technique for improving event-handling performance, but doesn't directly talk about stopPropagation performance.
Ultimately, you'd have to profile the difference to get a good idea of the benefits on your site.
I suppose this behavior is already well optimized by browsers, so you won't be able to catch significant performance boost when stopping propagations (except, perhaps, for really-really complex nested DOM structures). If you are worried by performance and deal with lots of events, you may be interested in event delegation instead.
Also, you should remember your code should stay readable and self-explainable. stopPropagation() is a method used for certain purpose, so using it in every method could be really confusing.

Categories

Resources