When I first heard about event bubbling, I had understood the gist of it but not enough to use it in practice. Event bubbling is the order in which event handlers are called when one element is nested inside a second element, and both of these elements have a registered listener for the same event(e.g. a click event).
Event propagation is a blanket term for both event bubbling and event capturing. Consider an example of clickable images:
By clicking on the <img> element, it will generate a click event for not only the <img> element, but also for its parent element <a>, as well as its grandparent element <li> and so on. It will go all the way up until it terminates at the window object. The <img> element is the event target or the innermost element on which the click had originated from. Thus, the flow of the event goes from:
img → a → li → ul → div → body → html → document → window.
This branch is important because it is the path in which the event propagates or flows. This propagation is bidirectional, from the window to the event target and then back. It can be divided into three phases.
- Capture phase: From the window to the event target parent
- Target phase: The event target itself
- Bubble phase: From the event target parent back up to the window
What differentiates these phases are the types of event listeners that are called.
During the Event Capture Phase, only the capturer event listeners are called. These are the event listeners that were registered with a value of true for the third parameter of .addEventListener().
If the third parameter is omitted, the default value is false and the event listener is not considered a capturer.
During the Event Target Phase, all the event listeners registered on the event target are invoked. They are all invoked regardless of the value of their capture flag.
Lastly, during the Event Bubbling Phase, all other event listeners are called that do not have the third parameter of true in the addEventListener function. At the end of propagation, each event listener will called only once.
Two methods that are used frequently with propagation are event.stopPropagation() and event.preventDefault(). With event.stopPropagation(), all event listeners registered on the nodes on the propagation path that follow the event target will not be called. All other remaining listeners attached to the event target will still receive the event.
With event.preventDefault(), it stops the default action the browser executes at the end of the propagation. For example, when a form submits, the browser usually causes a re-render or navigates to a new page. By calling event.preventDefault, it stops the re-render.