JavaScript Tutorial
JS - Introduction JS - Basic JS - Placement JS - Output JS - Statements JS - Syntax JS - Variables JS - Comments JS - Data Types JS - Operators JS - Operator Precedence JS - Condition JS - Switch JS - Functions JS - Objects JS - Loops For JS - Loops While JS - Break JS - Strings JS - String Methods JS - Numbers JS - Number Methods JS - Arrays JS - Array Methods JS - Array Iteration JS - Events JS - Event Listener JS - Event Propagation JS - Date JS - Math JS - Random JS - Boolean JS - Type Conversion JS - RegExp JS - Exception JS - Scope JS - Debugging JS - Hoisting JS - Strict Mode JS - this Keyword JS - Mistakes JS - Best Practices JS - Performance JS - Form Validation JS - ES6 Features
JS Objects
Object Definitions Object Properties Object Methods Object Constructors Object Prototypes
JS Functions
Function Definitions Function Parameters Function Call Function Apply Function Closures
JS HTML DOM
DOM Introduction DOM Methods DOM Selectors DOM HTML DOM CSS DOM Attributes DOM Navigation
JS Browser BOM
JS - Window JS - Screen JS - Location JS - History JS - Navigator JS - Popup Alert JS - Timing JS - Cookies
JS AJAX
AJAX - Introduction AJAX - XMLHttp AJAX - Request AJAX - Response AJAX - PHP
JS JSON
JSON - Introduction JSON - Syntax JSON - Data Types JSON - Parse JSON - Stringify JSON - Objects JSON - Arrays JSON - PHP JSON - JSONP
JS References
JavaScript Reference JavaScript Methods HTML DOM Reference

JavaScript Event Propagation

Event propagation is a way to describe the “stack” of events that are fired in a web browser.

Event bubbling and capture are two mechanisms of event propagation that describe what happens when two handlers of the same event type are activated on one element.

Suppose you have a <p> element inside a <div> element, and the user clicks on the <p> element, which element's "click" event should be handled first?

Run code

With capturing, the event is first captured by the outermost element and propagated to the inner elements.

With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.

With the addEventListener() method you can specify the propagation type by using the "useCapture" parameter.

Syntax:

element.addEventListener(event, listener, useCapture)

The default value is false, which will use the bubbling propagation, when the value is set to true, the event uses the capturing propagation.


Bubbling and Capturing explained

The concept of event propagation was introduced to deal with the situations in which multiple elements in the DOM hierarchy with a parent-child relationship have event handlers for the same event, such as a mouse click. Now, the question is which element's click event will be handled first when the user clicks on the inner element—the click event of the outer element, or the inner element.

When an event is fired on an element that has parent elements (e.g. the <p> in our case), modern browsers run two different phases — the capturing phase and the bubbling phase.

In the capturing phase:

  • The browser checks to see if the element's outer-most ancestor (<html>) has an onclick event handler registered on it in the capturing phase, and runs it if so.
  • Then it moves on to the next element inside <html> and does the same thing, then the next one, and so on until it reaches the element that was actually clicked on.

In the bubbling phase, the exact opposite occurs:

  • The browser checks to see if the element that was actually clicked on has an onclick event handler registered on it in the bubbling phase, and runs it if so.
  • Then it moves on to the next immediate ancestor element and does the same thing, then the next one, and so on until it reaches the <html> element.
JavaScript Event Propagation

In modern browsers, by default, all event handlers are registered in the bubbling phase.


The Capturing Phase

In the capturing phase, events propagate from the Window down through the DOM tree to the target node.

Run code

Event capturing only works with event handlers registered with the addEventListener() when the third argument is set to true.


The Bubbling Phase

In the bubbling phase, the exact opposite occurs. In this phase event propagates or bubbles back up the DOM tree, from the target element up to the Window.

Run code

Event bubbling is supported in all browsers, and it works for all handlers, regardless of how they are registered e.g. using onclick or addEventListener().


Stopping Event Propagation

You can also stop event propagation in the middle if you want to prevent any ancestor element's event handlers from being notified about the event using the event.stopPropagation() method.

In the following example click event listener on the parent elements will not execute if you click on the child elements:

Run code

Accessing the Target Element

The target element is the DOM node that has generated the event.

For example, if the user clicks a hyperlink, the target element is the hyperlink.

The target element is accessible as event.target, it doesn't change through the event propagation phases.

Run code

Preventing Default Action

Some events have a default action associated with them. For example, if you click on a link browser takes you to the link's target, when you click on a form submit button browser submit the form, etc. You can prevent such default actions with the event.preventDefault() method of the event object.

Run code

However, preventing the default actions does not stop event propagation; the event continues to propagate to the DOM tree as usual.


Event delegation

Bubbling also allows us to take advantage of event delegation.

Event delegation allows you to avoid adding event listeners to specific nodes; instead, the event listener is added to one parent.

This concept relies on the fact that if you want some code to run when you click on any one of a large number of child elements, you can set the event listener on their parent and have events that happen on them bubble up to their parent, rather than having to set the event listener on every child individually.

In this example, if you want each one of them to pop up a message when clicked, you can set the click event listener on the parent <ul>, and it will bubble to the list items:

Run code