Handbooks / JavaScript / Chapter 9
DOM and Events
7 pages · ~5 min✓ Reviewed
Builds on Modules and Tooling. Next up: Browser APIs: fetch and Storage.
DOM Events Mental Model
1. Select and Update
| Call | Returns |
|---|---|
querySelector(sel) | first match or null |
querySelectorAll(sel) | static NodeList |
getElementById(id) | one element, fastest |
textContentsets plain text: safeinnerHTMLparses HTML: XSS risk with user inputclassList.add / remove / togglechange classessetAttribute(name, v);dataset.keyreadsdata-key
2. The Event Object
- Event = object passed to the handler
event.target: element that fired itevent.currentTarget: element the listener is attached to
3. Three Phases
- Capturewindow down to target
- Targetelement fires
- Bubbletarget up to window
focus, blur, mouseenter, mouseleave and element scroll do not bubble. Most other events do.
Listeners and the Core Workflow
1. Attach and Remove
el.addEventListener(type, handler, options)attaches a listener- Many listeners per event allowed;
onclickkeeps only one removeEventListenerneeds the same function reference and same capture flag- Anonymous or inline arrow functions cannot be removed
const onClick = () => save(); btn.addEventListener('click', onClick); btn.removeEventListener('click', onClick);
named reference, so removal works
2. Options Object
| Option | Effect |
|---|---|
{ once: true } |
Bubbling, Capturing and Delegation
1. Phases and Order
| Listener | Fires | Order |
|---|---|---|
| Default | bubble phase | inner → outer |
capture: true | capture phase | outer → inner, before the target |
- windowcapture starts
- targetfires here
- windowbubble ends
2. Event Delegation
preventDefault, stopPropagation and Passive Listeners
1. Cancel vs Stop
| Cancels default | Stops other elements | Stops same-element listeners | |
|---|---|---|---|
preventDefault() | yes | no | no |
stopPropagation() | no | yes | no |
stopImmediatePropagation() | no | yes | yes |
Forms and Input Events
1. input vs change vs submit
| Event | Fires when | Target |
|---|---|---|
input | every value change: typing, paste, drag | field |
change | commit: blur for text; at once for checkbox, radio, select | field |
submit | form is submitted; not a button click | form element |
- Listen on the form, then call
e.preventDefault()to handle it with JS
2. Reading and validating
DOM Events Cheat Sheet
1. Select, Update, Listen
- Select: querySelector (first or null), querySelectorAll (static list),
getElementById - Update:
textContent(safe),classList,dataset.key,setAttribute - Remove with the same fn reference or
ac.abort(); inline arrows can't be removed passivematters only fortouchstart,touchmove,wheel
const ac = new AbortController() box.addEventListener('wheel', onWheel, { once: true, capture: false, passive: true, signal: ac.signal })
all four options on a wheel listener
2. Phases and Delegation
- Capturewindow down
- Targetfires here
- Bubbleback up
Check yourself
A parent has a capture listener logging P and its child has a normal listener logging C. You click the child. What logs?
- P, then C
- Capture runs outer to inner, before the bubble phase
parent.addEventListener('click', () => log('P'), true) child.addEventListener('click', () => log('C'))
Spot the bug: the remove call below never removes the listener. Why?
- Each arrow function is a new object, so the references differ
- Store the handler in a variable and pass that to both calls
btn.addEventListener('click', () => go()) btn.removeEventListener('click', () => go())
A link inside a div calls e.stopPropagation() on click. Does the browser still navigate, and does the div's listener run?
- It still navigates, because only preventDefault cancels that