JS

DOM Manipulation

JavaScript · 9 entries

Selecting Elements

syntax
document.querySelector(selector)
document.querySelectorAll(selector)
document.getElementById(id)
example
const header = document.querySelector("h1");
const buttons = document.querySelectorAll(".btn");
const main = document.getElementById("main-content");

// querySelectorAll returns a static NodeList
buttons.forEach(btn => {
  console.log(btn.textContent);
});

Note querySelector returns the first match or null. querySelectorAll returns a static NodeList (does not auto-update). Use Array.from() if you need full array methods.

Creating and Inserting Elements

syntax
document.createElement(tag)
parent.appendChild(child)
parent.append(...nodes)
element.insertAdjacentHTML(position, html)
example
const card = document.createElement("div");
card.className = "card";

const title = document.createElement("h2");
title.textContent = "New Item";

const desc = document.createElement("p");
desc.textContent = "Description goes here.";

card.append(title, desc);
document.getElementById("container").appendChild(card);

Note append() accepts multiple nodes and strings. appendChild() only accepts one node. Prefer textContent over innerHTML to prevent XSS when inserting user-provided text.

Event Listeners

syntax
element.addEventListener(event, handler, options)
element.removeEventListener(event, handler)
example
const button = document.querySelector("#submit-btn");

function handleClick(event) {
  event.preventDefault();
  console.log("Button clicked!", event.target);
}

button.addEventListener("click", handleClick);

// One-time listener
button.addEventListener("click", () => {
  console.log("This fires only once");
}, { once: true });

Note The third argument can be a boolean (useCapture) or an options object { capture, once, passive, signal }. Use { once: true } for one-shot handlers.

Event Delegation

syntax
parent.addEventListener(event, (e) => {
  if (e.target.matches(selector)) { ... }
});
example
const todoList = document.querySelector("#todo-list");

todoList.addEventListener("click", (event) => {
  const deleteBtn = event.target.closest(".delete-btn");
  if (deleteBtn) {
    const item = deleteBtn.closest(".todo-item");
    item.remove();
  }
});

Note Attach one listener to a parent instead of many on children. Works for dynamically added elements too. Use closest() to find the nearest matching ancestor.

classList Operations

syntax
el.classList.add(cls)
el.classList.remove(cls)
el.classList.toggle(cls)
el.classList.contains(cls)
el.classList.replace(old, new)
example
const panel = document.querySelector(".panel");

panel.classList.add("visible", "animated");
panel.classList.remove("hidden");
panel.classList.toggle("expanded");

if (panel.classList.contains("visible")) {
  console.log("Panel is visible");
}

panel.classList.replace("animated", "static");

Note classList methods are cleaner and safer than manipulating className directly. toggle() returns true if the class was added, false if removed.

Data Attributes (dataset)

syntax
element.dataset.key
// reads data-key="value" from HTML
example
// HTML: <button data-action="save" data-item-id="42">Save</button>
const btn = document.querySelector("button");

console.log(btn.dataset.action);  // "save"
console.log(btn.dataset.itemId);  // "42" (camelCase conversion)

btn.dataset.status = "pending"; // sets data-status="pending"

Note data-kebab-case becomes camelCase in JavaScript: data-item-id -> dataset.itemId. All dataset values are strings; parse numbers manually.

innerHTML vs textContent

syntax
element.innerHTML = htmlString;
element.textContent = plainText;
example
const output = document.querySelector("#output");

// textContent: safe, treats everything as text
output.textContent = "<b>Hello</b>"; // shows literal "<b>Hello</b>"

// innerHTML: parses HTML (XSS risk with user input!)
output.innerHTML = "<b>Hello</b>";   // shows bold Hello

// Safe alternative for HTML
const tmpl = document.createElement("template");
tmpl.innerHTML = "<b>Hello</b>";
output.append(tmpl.content.cloneNode(true));

Note NEVER use innerHTML with unsanitized user input -- it is the #1 source of XSS vulnerabilities. Use textContent for plain text and createElement for dynamic HTML.

DOM Traversal

syntax
el.parentElement
el.children
el.firstElementChild
el.nextElementSibling
el.closest(selector)
example
const item = document.querySelector(".active-item");

console.log(item.parentElement);        // parent
console.log(item.children);             // HTMLCollection of children
console.log(item.nextElementSibling);   // next sibling element
console.log(item.closest(".container")); // nearest ancestor matching selector

Note Use element-based properties (parentElement, children) over node-based ones (parentNode, childNodes) to skip text/comment nodes.

Removing Elements

syntax
element.remove()
parent.removeChild(child)
example
// Modern: element removes itself
const notification = document.querySelector(".notification");
notification.remove();

// Remove all children
const container = document.querySelector("#list");
while (container.firstChild) {
  container.removeChild(container.firstChild);
}

// Faster: clear all children
container.replaceChildren();

Note el.remove() is cleaner than parentNode.removeChild(el). Use replaceChildren() with no arguments to efficiently clear all children.