The practical difference is that delegate
(and three-argument on
) can cause listeners to apply to elements that don't exist yet.
$( "table td" ).on( "click", ...)
attaches a listener to every element that matches the table td
selector that exists at the time the call is made. If a td
is added to the page after this call, it won't have a listener attached to it.
$( "table" ).delegate( "td", "click", ...)
attaches a listener to every table
that exists at the time the call is made, and that listener only fires when a td
sub-element of that table
element is clicked.
$("button").click(function() {
$("tr").append("<td>I am added after page-load time and am not targeted by load-time scripts. The listener that fires an alert does not apply to me, because I didn't exist when the <code>$('table td').click</code> code ran. However, the delegated listener still aplies, so I will turn red when you click me.</td>");
})
$("table td").on("click", function() { alert("hi"); });
$("table").delegate("td", "click", function() { $(this).css("color", "red"); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table style="width:70%";>
<tr>
<td>I am targeted by non-delegated event listeners set at page-load time. Click this text to trun this text red and see an alert.</td>
</tr>
</table>
<button>Add another td</button>
Delegation works because when you click a child element (like a td
) you've actually clicked all of its parents (like a table
and the body
) as well. (To compare to human person: you can't poke a person's arm without also poking that person as a whole.) When a click listener fires for a parent, the event has a target
property that indicates what element was the original target of the event.
document.getElementById("theDiv").addEventListener("click", function(e) {
if(e.target != this) {
e.target.style.color = "red";
}
});
<div id="theDiv">
<span>I'm a span, inside of a div</span><br/>
<span>I'm another span, inside of a div</span><br/>
<span>I'm a third span, inside of a div</span>
</div>
Note in this example, we add only one listener on the <div>
. When we click a <span>
, the click
event also applies to the parent <div>
. We use event.target
to allow the <div>
listener to find out which of its children was clicked.