Skip to content

What is Event Bubbling in JavaScript

event-bubbling

What is Event Bubbling in JavaScript?

When an event happens on an element, the respective handler is run and is bubbled on to the parent element, the parent element handles the event and the event is bubbled on to its ancestors (except when bubbling is stopped).

Event Bubbling with an example

Let’s look at a sample HTML.

<table id="grid">
    <thead></thead>
    <tbody>
        <tr>
            <td>row 1 cell 1</td>
            <td>row 1 cell 2</td>
        </tr>
        <tr>
            <td>row 2 cell 1</td>
            <td>row 2 cell 2</td>
        </tr>
        <tr>
            <td>row 3 cell 1</td>
            <td>row 3 cell 2</td>
        </tr>
        <!-- some other tr rows -->
    </tbody>
</table>

When an event happens on any of the TD element in the above code, the event handler for that TD element will be fired and executed, once the TD event handler completes its operation, then its parent event listener is fired. This is called event bubbling.

So, the TR element handles the event and passes it to the tbody, the tbody handles its specific thing and passes it to the table and so on until the document object is reached.

Event Bubbling in Action

To see this in action, let’s add event listeners for every HTML tag in the above HTML. Here’s the demo in jsfiddle. Just try to click on any td cell and observe that all the listeners are fired all the way up to the document listener.

$(function(){
    $("td").on("click", function(e){
        alert($(this).text());
    });
});

Now, the above code looks pretty obvious but imagine we have 100 rows (TR) and every row is having 5 columns (TD), then the click event listener will bind to all the 500 (100 * 5) TD elements.

To solve this, we’ll just attach a listener on the grid and see if the click happened on the TD element and then take necessary action. This needs a little work, but it is just a single listener for the entire grid.

In our case, the logic should be pretty easy

$(function(){
    $("#grid").on("click", function(e){
        var cell= $(e.target); //Get the cell
        if(cell.is('TD'))
            alert('Cell data: ' + cell.text());
    });
});

Now, if we click on any of the TD element in the table we should get an alert with the cell text.

But how does it work? Because of the event bubbling.

The TD element receives a click and there is no handler attached to it so bubbled up to tr, tbody these don’t have any listeners it bubbles up to the table element which has a click event handler and is fired.

Note that once the event is handled in the table (grid) it doesn’t stop there it still bubbles up to the document object (because we didn’t stop the bubbling).

Well, this could be a problem because firing every click event until the body of the element will sometimes result in unexpected behavior in the application. We can stop this event from bubbling up the hierarchy.

To catch the bubbling we can have a listener on the parent element so that we can take appropriate action based on the target element. When this is implemented, we will call it an event delegation.

Javascript solution for event delegation

This is a javascript solution to event delegation.

var table = document.getElementById("grid");
table.onclick = function (evt) {
    var td = evt.target.closest("td"); //evt.target is the element that recieves the click
    if(!td) return; //if the click happens on any other element we can ignore the handling
    //do something with the event or take necessary action
}

If you are using plain javascript, then you should remember one thing here. The event.target is always the element that is clicked on and not the element it is bubbled up to.

jQuery event delegation

Instead of verifying if the clicked element is TD or not, jQuery has support for event delegation. So, you can specify what element to listen to when a click happens on a grid.

definition

Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.- jQuery

Here’s how we can achieve event delegation in jQuery.

$(function(){
    $("#grid").on("click", "td", function(evt) {
        alert(" the td content is : " + $(this).text())
    });
});

The advantage of creating click events with event delegation is that the elements added dynamically will also receive the click events in the future. So, you don’t have to worry about dynamically adding elements.

One might think that this is the same as having the selector combined with the grid

$("#grid td").on("click", function() {});

The above event is not a delegated listener because we are attaching click event listeners for all the td elements in the #grid. Whereas the delegated listener will listen on the grid and if the click happens on the td element then the listener will be fired.

Conclusion

I’d recommend stopping the bubbling(using e.stopPropogation()) if you have handled the specific event, otherwise, it will fire the parent listeners if you have any.

With event delegation, we can have some performance improvements on the page.

jQuery event delegation is good but if you have to stop/off the event delegation, then the answer is you can’t! Yes, you cannot stop the event delegation on a specific element inside a parent container.

1 thought on “What is Event Bubbling in JavaScript”

  1. Pingback: stopPropogation() vs preventDefault() in JavaScript - Code Rethinked

Leave a Reply

Your email address will not be published.