Theory
Events, bubbling, delegation
Lesson 2's card looks good but is dead — clicking does nothing. The DOM runs on events: the browser announces clicks, keys, form submits, and we react to them.
The basics is addEventListener:
button.addEventListener('click', (e) => { /* e — the event object */ });
But the key thing is understanding how events travel. When you click a button inside a card, the event bubbles: it fires on the button first, then the card, then body, then document. One click, several levels up.
From that come two powerful techniques and two traps:
- Delegation. Instead of a listener on every button, put one on a shared parent. Because events bubble, that single listener sees them all. This is exactly how keyboard shortcuts work (one listener on
document). e.stopPropagation()— stops the bubbling. Needed when a button lives inside another clickable element (our ♡ inside the card).e.preventDefault()— stops the browser's default action (a form submit → page reload; a link click → navigation).
stopPropagation and preventDefault are often confused, but they're different: the first stops the event's journey through the DOM, the second stops the browser's built-in reaction. In this lesson we'll see both — and both as real bugs that make the app misbehave.