Let's start with example. Here is a very simple example HTML.
<html>
<head>
</head>
<body>
<ul>
<li>
<a href="some_url/">Link 1</a>
</li>
<li>
<a href="some_url/">Link 2</a>
</li>
<li>
<a href="some_url/">Link 3</a>
</li>
</ul>
</body>
</html>
Now in this example, we want to add an event listener to all <a>
elements.
The problem is that the list in this example is dynamic.
<li>
elements are added and removed as time passes by.
However, the page does not refresh between changes, which would allow us to use simple click event listeners to the link objects (i.e. $('a').click()
).
The problem we have is how to add events to the <a>
elements that come and go.
Delegated events are only possible because of event propagation (often called event bubbling). Any time an event is fired, it will bubble all the way up (to the document root). They delegate the handling of an event to a non-changing ancestor element, hence the name "delegated" events.
So in example above, clicking <a>
element link will trigger 'click' event in these elements in this order:
Knowing what event bubbling does, we can catch one of the wanted events which are propagating up through our HTML.
A good place for catching it in this example is the <ul>
element, as that element does is not dynamic:
$('ul').on('click', 'a', function () {
console.log(this.href); // jQuery binds the event function to the targeted DOM element
// this way `this` refers to the anchor and not to the list
// Whatever you want to do when link is clicked
});
In above:
<a>
element<a>
element.<li>
element and then to the <ul>
element.<ul>
element has the event listener attached.this
. If the function does not include a call to stopPropagation()
, the event will continue propagating upwards towards the root (document
).Note: If a suitable non-changing ancestor is not available/convenient, you should use document
. As a habit do not use 'body'
for the following reasons:
body
has a bug, to do with styling, that can mean mouse events do not bubble to it. This is browser dependant and can happen when the calculated body height is 0 (e.g. when all child elements have absolute positions). Mouse events always bubble to document
.document
always exists to your script, so you can attach delegated handlers to document
outside of a DOM-ready handler and be certain they will still work.