DOM Event Delegation


Example

Event delegation is a process which allow us to avoid adding event listeners to specific nodes; instead, the event listener is added to parent node. This mechanism utilizes the event propagation/bubbling to handle an event at a higher level element/node in the DOM instead of using the element on which the event was originated. For example, think we need to add events for the following list elements:

<ul id="container">
    <li id="item-1" class="new">Item 1</li>
    <li id="item-2">Item 2</li>
    <li id="item-3">Item 3</li>
</ul>

We need to add click handlers and basically, we can add listeners to each element using a loop but imagine that, we want to add elements dynamically. So, we register all the event handlers when the DOM is loaded and after the DOM initializes and registers all the event handlers for each element, the newly inserted element into the above UL will not respond on click because that element was not present in the DOM when we've registered the click event listeners.

So, to overcome this problem, we may leverage the event delegation. Which means, instead of registering the listeners to each li elements themselves, we can bind the event listener to it's parent UL element for example:

document.getElementById("container").addEventListener("click", function(e) {
    console.log("List item " e.target.id, " was clicked!");
});

Since, the event propagates (bubbles upwards) by default, then clicking on any LI element will make the UL element to fire the same event as well. In this case, we can use the e parameter in the function, which is actually the event object and it carries helpful information about the event including the original element, which initiated the event. So, for example, we can use something like the following:

document.getElementById("container").addEventListener("click", function(e) {

    // If UL itself then no action is require
    if(e.target.nodeName == 'UL') return false;

    if(e.target.classList.contains('new')) {
        console.log("List item " e.target.id, " was clicked and it's new!");
    }
});

So, it's obvious that, e (Event Object) allow us to examine the source element (e.target) and we can easily inject new elements to the UL after DOM is loaded and the only one delegated event handler will handle all the click events within the parent UL which is also less memory consuming because we declared only one function for all the elements.