JS: Event Delegation
What is Event Delegation
- Event Delegation is a programing technique to lets you set one single event handler instead of hundreds. For example, you want a hover tip of definition of each word.
- Also, Event Delegation make it possible to set up event handler of new elements that are dynamic added.
How Does Event Delegation Work
- Event Delegation works by adding event to the parent element, instead of each children, then in your event handler, use event target to detect if current element is the one you want.
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 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.