JS: Event Delegation

By Xah Lee. Date: . Last updated: .

What is Event Delegation

How Does Event Delegation Work

Event Delegation Example

Suppose we want to color all paragraph “p” items red when user clicks it.

for (let xx of document.querySelectorAll("p")) {
  xx.addEventListener("click", (xevent) => {
    xevent.target.style.color = "red";
  }, false);
}

〔see for-of Loop

instead of attaching a event handler to “p”, we can attach it a parent element, such as “body”. Because when mouse hovers over any “p”, it is also hovering over “body”.

for (let xx of document.querySelectorAll("body")) {
  xx.addEventListener("click", (xevent) => {
    if (xevent.target.nodeName === "P") xevent.target.style.color = "red";
  }, false);
}

Try it. Copy and paste the above code into your browser's JavaScript console. Then, click on any paragraph.

Why use Event Delegation?

If you use event delegation, you can add child elements without needing to attach event to them. This makes your implementation simpler. (in complex web app, you may be constantly adding and removing elements dynamically.)

Also, relegation may save you memory, since you have just one listener instead of potentially hundreds.

Tech Detail of Event Delegation

Delegation works fundamentally because elements are nested.

When element p is inside a div, and when user clicks on p, the click is also on div because div encloses p.

When a event (such as mouse click) applies to all nested elements, the order of event firing is from outer element to inner elements then back to outer element.

Suppose you attach a mouseover event handler to ul.

When user mouse hovers over li, your event handler will run because mouse is also hovering over ul. The browser will go thru a event propagation path, which will start at ul then go to its nested elements until it hits the element that the mouse is on, then travel back to the ul element.

For each element in the event propagation path, it'll set eventObject.target to that element. So, your event handler can check if element's tag is li.

Event Dispatch Specification

dom eventflow
DOM event flow http://www.w3.org/TR/DOM-Level-3-Events/#dom-event-architecture

DOM defines 3 phase for event dispatch. Quote:

  • capture phase: The event object MUST propagate through the target's ancestors from the defaultView to the target's parent. This phase is also known as the capturing phase. Event listeners registered for this phase MUST handle the event before it reaches its target.
  • target phase: The event object MUST arrive at the event object's event target. This phase is also known as the at-target phase. Event listeners registered for this phase MUST handle the event once it has reached its target. If the event type indicates that the event MUST NOT bubble, the event object MUST halt after completion of this phase.
  • bubble phase: The event object propagates through the target's ancestors in reverse order, starting with the target's parent and ending with the defaultView. This phase is also known as the bubbling phase. Event listeners registered for this phase MUST handle the event after it has reached its target.