Events
The page reacts to actions
Everything interactive on websites — buttons, menus, search fields, games — works the same way: the code subscribes to an event ("when this button is clicked…") and says which function to call then. The code itself doesn't wait for anything: the program ends, and the handler function fires later, when the event happens.
addEventListener
const btn = document.querySelector("#hello");
btn.addEventListener("click", () => {
console.log("The button was clicked!");
});
The first argument is the event name, the second is the handler function. You don't call it yourself (no ()):
the browser will call it on every click. You can subscribe as many times as you like — all handlers will fire
in order.
Common events:
| Event | When |
|---|---|
click |
a mouse click or a tap |
input |
the field's value changed (every letter) |
change |
the field was changed and left; a choice in select, a checkbox |
submit |
a form is submitted (Enter or a button) |
keydown / keyup |
a key is pressed / released |
mouseenter / mouseleave |
the mouse enters / leaves an element |
focus / blur |
a field gets / loses focus |
You'll also see an older way — btn.onclick = () => {...}. An element can have only one such
function, a new one overwrites the old one, so addEventListener is better.
State between events
A handler is called many times, and data between calls is stored in a variable outside the handler:
let likes = 0;
const likeBtn = document.querySelector("#like");
likeBtn.addEventListener("click", () => {
likes++;
likeBtn.textContent = `♥ ${likes}`;
});
If you declared let likes = 0 inside the arrow function, the count would start over on every click.
The event object
The browser passes an event object with details to the handler — it's usually called e or event:
document.querySelector("#box").addEventListener("click", (e) => {
console.log(e.type); // "click"
console.log(e.target); // the element that was clicked
console.log(e.clientX, e.clientY); // mouse coordinates in the window
});
e.target is the element where the event happened. This will come in handy in the next topic, when one
handler serves many buttons.
Text input
const search = document.querySelector("#search");
search.addEventListener("input", () => {
console.log("Searching:", search.value);
});
input fires on every character — that's how "live" search and character counters are made. change fires when
the user has finished and left the field; for <select> and checkboxes it fires right when a choice is made.
Keyboard
Key presses are listened for on document (or on an input field). Which key it was is in e.key:
document.addEventListener("keydown", (e) => {
if (e.key === "Enter") console.log("Enter");
if (e.key === "ArrowUp") console.log("Arrow up");
if (e.key === " ") console.log("Space");
if (e.ctrlKey && e.key === "s") console.log("Ctrl+S");
});
Names: letters — "a", "B"; arrows — "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown";
"Enter", "Escape", "Shift", " " (space).
Cancelling the browser's action
Some events have a default action: a link takes you to another page, a form
reloads the page, the space bar scrolls it. e.preventDefault() cancels it:
document.querySelector("a.no-go").addEventListener("click", (e) => {
e.preventDefault();
console.log("Not going anywhere");
});
Unsubscribing
To make a handler stop firing, remove it with removeEventListener — with the very same
function, so you need to keep it in a variable:
const onClick = () => console.log("click");
btn.addEventListener("click", onClick);
btn.removeEventListener("click", onClick);
// Or right away: fire only once
btn.addEventListener("click", () => console.log("first click"), { once: true });
Summary
el.addEventListener("event", function)— subscribing; we pass the function, we don't call it.- Data between events lives in variables outside the handler.
e.target— where it happened,e.key— which key,e.preventDefault()— cancel the browser's action.input— every change of a field,change— a finished change,keydown— a key press.