event bubbling

event bubbling

Event bubbling concept is a way of propagating the events from the element clicked all the way to the ancestor. This is a beginner article so if you are already aware of this you can skip this article.

What is event bubbling?

The principle of event bubbling is fairly simple. Here it goes.

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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>


If there is an event happening on any TD element in the above code, then the event handler for that TD element will be fired and executed, once the TD event handler completes its operation, then it’s parent event listener is fired (event bubbled here). 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.

To see this in action, let’s add event listeners for every HTML tag in the above HTML. Here’s is 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.

The requirement for this article is that for the above table whenever we click on any TD element we’ve to show the content in an alert (so, row x column y should be displayed).

To satisfy the requirement, we’d generally attach an event listener on the TD element and when the user clicks we’ll alert the text in that TD element.

1
2
3
4
5
$(function(){
$("td").on("click", function(e){
alert($(this).text());
});
});

Now, the above code looks pretty obvious but imagine we have 100 rows and every row is having 5 columns, 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

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

Well, the code works. But how does it work? Because of event bubbling. Yes, 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).

Event bubbling is the concept of bubbling the events up until the hierarchy so 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 as event delegation.

Javascript solution for event delegation

This is a javascript solution to event delegation. 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.

1
2
3
4
5
6
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
}

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 on 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.

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

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

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

This 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

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.

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.

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×