Keyboard, Pointer & Beyond
Advanced · 20 min read · ▶ live playground · ✦ checkpoint
Click, submit, and input events cover a lot of UI, but real interfaces often need more specific signals. Keyboard events tell you which key was pressed, pointer events unify mouse, touch, and pen input, and custom events let your own components announce what happened.
This is the closing loop for events: listen to the right signal, read the event object, update the DOM, and avoid taking over browser behavior unless your UI has a clear reason.
Keyboard events name the key
The everyday keyboard event is keydown. It fires when a key is pressed, and event.key tells you the meaning of that key: "Enter", "Escape", "a", "A", "ArrowDown", and so on.
Modifier fields tell you what else was held:
event.shiftKeyevent.ctrlKeyevent.altKeyevent.metaKey
Use event.key, not old numeric keyCode. Numbers make code harder to read and do not describe text, layout, or special keys as clearly.
Try the note box. Typing normal letters stays normal. Press Escape to clear the note, or press Ctrl/Command + Enter to mark it reviewed.
The important restraint is in what the code does not do. It does not call preventDefault() for every key. Normal letters, Backspace, selection shortcuts, and caret movement belong to the browser and the user. The handler only takes over Ctrl/Command + Enter because that shortcut has a specific app meaning.
For plain text changes, the form lesson's input event is still the better signal. Use keydown when the key itself matters: Escape, arrow keys, Enter shortcuts, or a deliberate command.
Pointer events unify mouse, touch, and pen
Old web code often split input into mouse events and touch events. Pointer events give you one family for mouse, touch, and pen:
pointerdownstarts a contact.pointermovefollows movement.pointerupends the contact.event.pointerTypetells you"mouse","touch", or"pen"when the browser knows.event.pointerIdidentifies one active pointer so you can ignore unrelated moves.
The playground below tracks one pointer at a time. Drag or press inside the pad. The status reports zones instead of exact coordinates, because exact pixels depend on your viewport and device.
touch-action: none in the CSS tells the browser this pad is handling the gesture, so touch dragging should not turn into page scrolling inside the pad. That is a real reason to take over default behavior. Outside a deliberate control like this, let the browser handle scrolling, zooming, text selection, and other expected gestures.
The pointerId check is small but important. Touch screens can have more than one contact at a time. Even if your first version tracks only one pointer, storing the active pointerId keeps unrelated pointer events from changing the wrong state.
Custom events let components announce facts
Browser events announce browser facts: a key went down, a pointer moved, a form submitted. Custom events let your own code announce app facts with names you choose.
The pattern is:
element.dispatchEvent(new CustomEvent("name", { detail: data }));
The detail object carries the useful payload. If you add bubbles: true, the custom event travels up the DOM like the events from 15.2, so a parent can listen without the child knowing who cares.
The stepper does not call a cart function directly. It announces "quantitychange" with the item and quantity. The parent listens for that event and decides what to do with it.
That separation matters as interfaces grow. A child component can announce "quantity changed", "tab selected", or "panel closed" without knowing whether the parent updates a total, logs an action, saves state, or ignores it. Custom event names are usually lowercase words or hyphenated names in real apps; pick names that describe the fact, not the button that caused it.
You now have the event toolkit for local browser interaction: listener basics, propagation, forms, keyboard commands, pointer input, and custom component signals. Section 16 moves from local events to the web outside the page: requests, responses, APIs, and live server data.
Checkpoint
Answer all three to mark this lesson complete