Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript JavaScript and the DOM (Retiring) Responding to User Interaction Event Bubbling and Delegation

Event Bubbling vs. Event Capturing

This video describes the effect of using the addEventListener() method on a div that contains a number of li elements. The idea is to affect all the li elements with just one application of the event listener to their ancestor.

The video calls this "bubbling" — the effect of which is that the "event moves to other elements like the parent and other ancestors of the element." Yet isn't the li element not the parent or ancestor of the div but rather its descendant?

If so, then isn't this an example of "capturing" (also called "trickling") and not "bubbling"?

trickle down, bubble up

—old JavaScript proverb

5 Answers

Steven Parker
Steven Parker
231,236 Points

In the DOM tree model, the root is at the top.

This is similar to a "family tree" in genealogy where parents are shown above their children.

So the parents and other ancestors of an element are above it. And yes, the li is a descendant, and so the event bubbles up to it's ancestors.

Thanks, and as you write "the li is a descendant, and so the event bubbles up to it's ancestors." However, the method addEventListener() is affixed to the div. So any activity on the div element triggers the event. Then the event would bubble up to the body element and then ultimately to the document. Meanwhile, the descendants remain unaffected.

Or is it the case that activity on elements lower on the tree (p, button, ul and li) are, in a sense, always producing event data? And the effects of that activity, or events, get sent up the tree eventually running into the addEventListener() as if it were a net ready to capture user actions? I had suspected adding the addEventListener() to an element meant that element would be generating the data (or more precisely, the event object). But it sounds like all the elements are generating events all the time and you have to add that method in a spot where you can actually capture all that data that is bubbling up.

I think I know the answer, but I've had to spell it out here to be clear.

Steven Parker
Steven Parker
231,236 Points

The event bubbles up to where the listener is attached.

Yes you could generate an event on the parent itself, but the bubbling occurs when you generate the event on the child and the listener on the parent/ancestor receives it.

So when you click on the li, you generate an event, but if it has no listener it bubbles up to the ul, and then to the div where it finally triggers the listener attached there.

Does that clear it up?

What's interesting to me — because I'd never realized this when I've used the addEventListener() method in the past — is that events are always being generated. I had mentally connected the method with events, so I incorrectly assumed no events were being generated if JavaScript wasn't set up to capture them.

In my original question I wrote —

The idea is to affect all the li elements with just one application of the event listener to their ancestor.

The above assertion is incorrect because it assumes the event listener on the div is affecting the li elements. The li elements will continue to generate event objects whether or not the addEventListener() is there. The addEventListener() affects nothing. It only makes note of what is already occurring.

What I'm picturing is a number of lowly elements stacked close to the ground. As a mouse moves among them, they release helium balloons. These balloons rise and contain event objects. Now, if there is nothing to capture them then they will continue to rise and disappear into the sky. However, if we set up a net — in the form of the addEventListener() method — to capture these balloons, then we can get at the event data that's contained inside those balloons.

We may not even care to access the event objects — so we don't have to bother setting a net. But if we do care then that's when we set the net.

Thanks for the clarification.

Steven Parker
Steven Parker
231,236 Points

A very colorful analogy! I've pictured bubbles rising through plumbing myself, where the plumbing is the DOM tree.

But without looking into the internals of the JavaScript engine, we don't know for sure if the events occur when there's nothing listening. It could be that they are only generated if there's a listener attached somewhere up the tree. But as you say, we don't really care if they are generated or not unless we listen. And then we know that they are generated.

But without looking into the internals of the JavaScript engine, we don't know for sure if the events occur when there's nothing listening.

"If a tree falls in a forest and no one is around to hear it, does it make a sound?"

I don't know who would readily have the answer to the JS engine question. It would be nice to know. Rarely do I find resources that discuss such things (especially for the uninitiated). For better or worse, I understand concepts better when familiar with their functioning on the most minute level — easier then to make colorful analogies. Thanks again.

Steven Parker
Steven Parker
231,236 Points

I almost used that "tree falls" quote in my last comment! And whether or not event generation is triggered by the presence of a listener is such a specific implementation issue that it might not even be done the same way in all browsers. We may never know, but we don't need to since it won't affect the function of our program either way. We can still mentally picture bubbles and balloons as we wish.

Hi Lee,

With your net analogy and "capturing the balloons" are you thinking that the event listener is capturing the events and stopping further propagation?

If so, attaching an event listener to an element only means that the element is able to process that event if that particular event happens to reach that element. It does not keep it from further propagating. In this lesson, the div, ul, and li's could all have listeners attached to them and they all would run.

You would have to use event.stopPropagation() or event.stopImmediatePropagation() if you wanted to actually capture the event and stop it from further propagating. These methods would be closer to your analogy of having a net.

Also, in regards to capturing vs. bubbling, both of these things are occurring in modern browsers. It goes capturing phase > target phase > bubbling phase

listeners in the capturing phase will execute top to bottom and it's bottom to top in the bubbling phase.

event listeners are registered by default with the bubbling phase so that's why the video only mentions the bubbling phase. Nothing is happening with the capturing and target phases.

Thanks for the additional info, Jason.

"If a tree falls in a forest and no one is around to hear it, does it make a sound?"

It's gonna keep ringing in my head for a few days...

Thanks all for the nice discussion.

Samuel Cleophas
Samuel Cleophas
12,348 Points

This is a phenomenal thread. Thanks guys! It's helped me a lot!

Aakash Srivastav
seal-mask
.a{fill-rule:evenodd;}techdegree
Aakash Srivastav
Full Stack JavaScript Techdegree Student 11,638 Points

I think in order to check whether it's an example of event bubbling or event capturing , you should add an event handler to any of the <li> item too.
Now when you perform the "mouseclick" event , If it's bubbling , then event handler attached to <li> will be invoked first . But if it's event capturing then event handler attached to <div> gets invoked first then event capturing happens. Here you cant clearly say what going on as there is only one event handler .
When you perform the "mouseclick" event on the <li> items , even if <li> get the event first , if there is no event handler attached to <li> , you can't say whether it get the event first or the <div> get.
This article will help you Event Bubbling vs Event Capturing in understanding it more.
Thanks