DOM & Events
Making web pages interactive — selecting elements, changing content, responding to clicks and keyboard input.
getElementsByClassName returns a live collection that updates itself as the page changes. Loop over it while removing that class, and each element drops out of the collection the moment you change it, so the indexes shift and the loop skips every other element. Half the items stay untouched, with no error.
const pending = document.getElementsByClassName("pending"); // a LIVE collection
for (let i = 0; i < pending.length; i++) {
pending[i].classList.remove("pending"); // the element leaves the collection
}
console.log(document.querySelectorAll(".pending").length);
// 2 -- with four <li class="pending">, items 2 and 4 are still pending (Chromium 141)Making pages respond to users
document, no window, and no DOM.
The DOM — JavaScript's view of your HTML
When a browser loads an HTML page, it builds a tree of objects called the
DOM (Document Object Model). Every element — every <h1>,
<button>, <p> — becomes a node in this tree.
JavaScript can read and modify any of these nodes to change what the user sees.
Selecting elements
// querySelector — the modern, flexible selector (like CSS selectors)
const title = document.querySelector("h1"); // first h1
const btn = document.querySelector("#submit-btn"); // element with id="submit-btn"
const warning = document.querySelector(".warning"); // first with class="warning"
const input = document.querySelector("form input[type='email']"); // specific input
// querySelectorAll — returns ALL matching elements (a NodeList)
const allButtons = document.querySelectorAll("button");
const listItems = document.querySelectorAll(".menu li");
// Loop over them:
allButtons.forEach(btn => {
console.log(btn.textContent);
});querySelectorAll, used above, returns a static NodeList: a snapshot taken once, which doesn't change while you modify the page. Loop over that (or copy a live collection first with [...pending]), and every element gets visited:
const pending = document.querySelectorAll(".pending"); // a STATIC snapshot
for (const el of pending) {
el.classList.remove("pending");
}
console.log(document.querySelectorAll(".pending").length); // 0Reading and changing content
const heading = document.querySelector("h1");
// textContent — plain text (safe, recommended):
console.log(heading.textContent); // current text
heading.textContent = "New Heading"; // change the text
// innerHTML — can include HTML tags (use carefully — XSS risk with user data):
const div = document.querySelector(".message");
div.innerHTML = "<strong>Bold message</strong> and normal text";
// NEVER do this with user input — it's an XSS vulnerability:
// div.innerHTML = userInput; // ✗ dangerous if userInput contains <script>
// Safe way to insert user content:
div.textContent = userInput; // ✓ always treated as plain textChanging styles and classes
const box = document.querySelector(".box");
// classList — the right way to manage CSS classes:
box.classList.add("active"); // add a class
box.classList.remove("hidden"); // remove a class
box.classList.toggle("selected"); // add if absent, remove if present
box.classList.contains("active"); // true/false check
box.classList.replace("old", "new"); // replace one class with another
// Inline styles (use classes when possible — CSS is more maintainable):
box.style.color = "red";
box.style.fontSize = "18px";
box.style.display = "none"; // hide the element
box.style.display = ""; // restore (remove inline override)Responding to events
An event is something that happens — a click, a keystroke, the page loading. You listen for events and run a function (the event handler) when they occur.
const button = document.querySelector("#my-button");
// addEventListener — the correct, modern way:
button.addEventListener("click", function(event) {
console.log("Button clicked!");
console.log("Clicked element:", event.target);
console.log("Mouse position:", event.clientX, event.clientY);
});
// Arrow function works too:
button.addEventListener("click", (e) => {
e.target.textContent = "Clicked!"; // change the button text
e.target.disabled = true; // disable after clicking
});
// Common events:
document.addEventListener("DOMContentLoaded", () => {
// Runs when HTML is fully parsed — safe to access elements here
console.log("Page ready");
});
const input = document.querySelector("input");
input.addEventListener("input", (e) => {
console.log("Current value:", e.target.value);
});
input.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
console.log("Enter pressed!");
}
});
window.addEventListener("scroll", () => {
console.log("Scrolled to:", window.scrollY);
});Creating and inserting elements
// Create a new element:
const li = document.createElement("li");
li.textContent = "New list item";
li.classList.add("item");
// Insert into the page:
const list = document.querySelector("ul");
list.appendChild(li); // add at end
list.prepend(li); // add at start
list.insertBefore(li, list.children[2]); // add at specific position
// Modern insertion methods:
list.append(li); // like appendChild, also accepts strings
list.insertAdjacentHTML("beforeend", "<li>Another item</li>");
// Remove an element:
li.remove(); // remove from DOMOfficial Sources
- MDN Web Docs — Introduction to the DOM
- MDN Web Docs — EventTarget.addEventListener()
- WHATWG DOM Standard
- MDN Web Docs — Event bubbling
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.