documentliul#todobuttonlitodo.htmlMilkBreadDoneDonebutton1const list = document.querySelector("#todo");2list.addEventListener("click", (event) => {3 const item = event.target.closest("li");4 if (!item) return;5 item.classList.toggle("done");6 console.log(event.target.tagName);7});typetargetcurrentTargetConsoleBUTTONtodo.js:6BUTTONtodo.js:6BUTTONBUTTON
Back: the page's DOM tree and the browser window showing itFront: the script todo.js, the event object and the developer consoleMovers: the click event (an envelope), the listener and the values it passesAt the back, the page's DOM tree and the browser window showing a two-row to-do list. In front, the script, the event object and the developer console. The script adds one click listener, to the list. A click on a Done button travels down the tree to the button (capture) and bubbles back up to the list, where the listener runs. event.target stays the button; event.currentTarget is the list. The same listener handles every row: event delegation. The real path is longer: window, document, html, body, ul, li, button. The figure leaves out window, html and body; they have no listeners here, so nothing changes.

What an event is

  1. An event is a signal that something happened on the page: a click, a key press, a form being sent. The browser describes it in an event object and delivers it through the DOM tree, the objects built from the HTML.

Adding a listener

The event's trip

The listener runs

Event delegation

What happens

// step 1/10 · event
event      a signal: something happened
examples   click, keydown, submit, input
object     the browser describes it in an Event
listener   a function that waits for one type
page       todo.html: a list with two rows,
           each with a Done button

The real path is longer: window, document, html, body, ul, li, button. The figure leaves out window, html and body; they have no listeners here, so nothing changes. event.stopPropagation() stops the trip at the current element, so parents further up never hear the event. event.preventDefault() is different: it cancels the browser's own action, such as following a link or sending a form.