JavaScript DOM

Selecting Elements

querySelector and querySelectorAll
// Single element
const header = document.querySelector("h1");
const nav = document.querySelector("#main-nav");
const active = document.querySelector(".active");
const link = document.querySelector('a[href="/about"]');

// Multiple elements — returns NodeList
const items = document.querySelectorAll(".item");
items.forEach(item => console.log(item.textContent));

// Convert NodeList to Array for full array methods
const arr = [...document.querySelectorAll("li")];
const filtered = arr.filter(li => li.classList.contains("active"));

querySelector returns the first match or null. querySelectorAll returns a static NodeList.

Modifying Elements

Content, attributes, styles
const el = document.querySelector("#status");

// Content
el.textContent = "Online";        // text only (safe from XSS)
el.innerHTML = "<strong>OK</strong>";  // parses HTML (XSS risk with user input)

// Attributes
el.setAttribute("data-host", "sw01");
el.getAttribute("data-host");     // "sw01"
el.dataset.host;                  // "sw01" (data-* shorthand)
el.removeAttribute("data-host");

// Classes
el.classList.add("active", "highlight");
el.classList.remove("inactive");
el.classList.toggle("visible");
el.classList.contains("active");  // true

// Styles
el.style.color = "green";
el.style.display = "none";

Prefer textContent over innerHTML when inserting user-provided text — innerHTML creates XSS vulnerabilities.

Creating Elements

Build DOM nodes programmatically
const li = document.createElement("li");
li.textContent = "New item";
li.classList.add("item");

// Append to parent
document.querySelector("ul").appendChild(li);

// Insert at specific position
const list = document.querySelector("ul");
list.insertBefore(li, list.firstChild);  // prepend

// Modern: append, prepend, before, after
list.prepend(li);
list.append(li);
el.before(newEl);
el.after(newEl);

// Remove
li.remove();

Event Handling

addEventListener — the modern approach
const button = document.querySelector("#submit");

button.addEventListener("click", (event) => {
    event.preventDefault();  // stop default behavior
    console.log("clicked:", event.target);
});

// Event delegation — handle events on parent
document.querySelector("ul").addEventListener("click", (e) => {
    if (e.target.matches("li")) {
        console.log("Clicked:", e.target.textContent);
    }
});

// Remove listener
const handler = () => console.log("clicked");
button.addEventListener("click", handler);
button.removeEventListener("click", handler);

// Once — auto-remove after first call
button.addEventListener("click", handler, { once: true });

Event delegation attaches one listener to a parent instead of one per child. This handles dynamically added elements and uses less memory.

Common Events

Events you will use most
// Page lifecycle
window.addEventListener("DOMContentLoaded", init);  // DOM ready
window.addEventListener("load", onLoad);              // everything loaded

// Form
form.addEventListener("submit", handleSubmit);
input.addEventListener("input", onInput);    // every keystroke
input.addEventListener("change", onChange);  // on blur

// Keyboard
document.addEventListener("keydown", (e) => {
    if (e.key === "Escape") closeModal();
    if (e.ctrlKey && e.key === "s") { e.preventDefault(); save(); }
});