I assume your question is about the Event Delegation version of .on
.
In JavaScript, most events bubble up in the DOM hierarchy. That means, when an event that can bubble fires for an element, it will bubble up to the DOM until document
level.
Consider this basic markup:
<div>
<span>1</span>
<span>2</span>
</div>
Now we apply event delegation:
$('div').on('click', 'span', fn);
The event handler is attached solely to the div
element. As the span
are inside of the div
, any click in the spans will bubble up to the div
, firing the div
's click handler. At that moment, all that is left is checking whether the event.target
(or any of the elements between the target and the delegateTarget
) matches the delegation target selector.
Let's make the a bit more complex:
<div id="parent">
<span>1</span>
<span>2 <b>another nested element inside span</b></span>
<p>paragraph won't fire delegated handler</p>
</div>
The basic logic is as follows:
//attach handler to an ancestor
document.getElementById('parent').addEventListener('click', function(e) {
//filter out the event target
if (e.target.tagName.toLowerCase() === 'span') {
console.log('span inside parent clicked');
}
});
Though the above will not match when event.target
is nested inside your filter. We need some iteration logic:
document.getElementById('parent').addEventListener('click', function(e) {
var failsFilter = true,
el = e.target;
while (el !== this && (failsFilter = el.tagName.toLowerCase() !== 'span') && (el = el.parentNode));
if (!failsFilter) {
console.log('span inside parent clicked');
}
});
Fiddle
edit: Updated code to match only descendant elements as jQuery's .on
does.
Note: These snippets are for explanatory purposes, not be used in real world. Unless you don't plan to support old IE, of course. For old IE you would need to feature test against addEventListener
/attachEvent
as well as event.target || event.srcElement
, and possibly some other quirks such as checking whether the event object is passed to handler function or available in the global scope. Thankfully jQuery does all that seamlessly behind the scenes for us. =]