When a user types in a new task and clicks the add button, a new
<li> and corresponding <button> are created, and a fifth click
subscription is added, one for the new button. The callback for the remove
buttons could be unique for each button, or a generic function that determined
which item to remove based on some other info from the event or button.

When a user clicks on one of the remove buttons, the item is removed. The
associated click event subscription is left in the system, taking up memory.
So to solve this, maybe the event subscription is detached before the item is
removed. Now there are four initial subscriptions and additional logic to
properly detach subscriptions before items are removed.

Over time, the number of items on the todo list grows, and so the number of
subscriptions in the system, and thus memory consumed, grows with it.
Additionally, if at some point, the entire list needs to be cleared, that's a
lot of subscriptions to detach before it's ok to flush the list's
innerHTML.

What is event delegation?

Event delegation is a way to reduce the number of subscriptions used to
support this system. In the example case, only two click subscriptions are
needed: one for the add button, and one for every remove button click. The
second one is the delegated subscription. Here's how to think about
it:

The key to event delegation is understanding that a click on a remove button
is also a click on

Instead of subscribing to the button's "click" event, you can subscribe
to the list's "click" event[2].

You clicked somewhere, but where?

When you click anywhere on the document, the browser dispatches a click
event that is assigned an e.target property corresponding to the element
that triggered the event. For example, if you click on "Profit!", the
event originated from the <li> with "Profit!" in it, so e.target will
be that <li> element[3].

With these two bits of information, we can create a single click
subscription to respond to every button click in the Todo list.

Now since there are no subscriptions tied directly to the individual
buttons, we can add new items to the list without needing to add more
subscriptions. Similarly, we can remove items or even clear the list's
innerHTML without needing to detach subscriptions because there aren't any
subscriptions inside the list to clear.

More work in the event subscriber

Since any click inside the list is now triggering the event subscriber, it
will be executed for button clicks, but also for clicks on the task item's text
(e.g. "Profit!"). To make sure this click happened on a button, we need to
inspect e.target to make sure it is a button.

This can start to get tricky when you're triggering on an element that can
contain children. For example, if there were no buttons, but instead you
wanted to remove items just by clicking on the <li>, you'd need to check
if e.target was an <li>. But if it's not, you have to look at
e.target's parentNode and potentially that node's parentNode and so on,
because e.target will always refer to the most specific element that received
the click. This can amount to a lot of filtering code wrapping the item
removal logic, which hinders the readability of your app.

Let node.delegate(...) do the work for you

This is where node.delegate(...)
comes in. node.delegate(...) boils down the filtering logic to a css
selector, passed as the third argument. The subscribed callback will only
execute if the event originated from an element that matches (or is contained
in an element that matches) this css selector. This allows the code to power
our Todo widget to look like this:

Footnotes

If there are click subscriptions at multiple points in
the DOM heirarchy, they will be executed in order from most specific (the
button) to least specific (document) unless e.stopPropagation() is
called along the line. This will prevent subscriptions from elements higher
up the parent axis from executing.

We're using the "click" event here, but this all applies
to other events as well.

Actually the event originated from the text node inside
the <li>, but IE reports the origin (the srcElement in IE) as the
<li>, which is probably what developers want, anyway. YUI fixes
e.target to bet the element for browsers that report it as the text
node.