DOM Manipulation
## Learning Objectives
- Select and traverse DOM elements
- Modify elements and their content
- Handle events effectively
- Create and remove elements dynamically
## Selecting Elements
### Single Elements
```javascript
// By ID
const element = document.getElementById("myId");
// By CSS selector (first match)
const first = document.querySelector(".myClass");
const nested = document.querySelector("div.container > p");
// getElementById vs querySelector
// - getElementById: faster, directly by ID
// - querySelector: more flexible, CSS selectors
```
### Multiple Elements
```javascript
// By tag name
const paragraphs = document.getElementsByTagName("p");
// By class name
const items = document.getElementsByClassName("item");
// By CSS selector (all matches)
const allLinks = document.querySelectorAll("a.nav-link");
// querySelectorAll returns NodeList (forEach available)
// getElementsBy* returns HTMLCollection (array-like, no forEach)
```
## Traversing the DOM
```javascript
const element = document.querySelector(".item");
// Parent
element.parentElement;
element.parentNode;
// Children
element.children; // HTMLCollection
element.childNodes; // NodeList (includes text nodes)
element.firstChild; // First node
element.firstElementChild; // First element child
element.lastChild;
element.lastElementChild;
// Siblings
element.nextSibling;
element.nextElementSibling;
element.previousSibling;
element.previousElementSibling;
```
## Modifying Elements
### Changing Content
```javascript
const div = document.getElementById("content");
// textContent (plain text)
div.textContent = "Hello, World!";
// innerHTML (HTML parsing)
div.innerHTML = "
Paragraph
"; // innerText (visible text, respects CSS) div.innerText = "Visible text"; // Best for security: createElement + textContent const p = document.createElement("p"); p.textContent = "Safe content"; div.appendChild(p); ``` ### Changing Attributes ```javascript const link = document.querySelector("a"); link.getAttribute("href"); link.setAttribute("href", "https://example.com"); link.removeAttribute("href"); link.hasAttribute("href"); // Direct property access (for id, className, value, etc.) link.href = "https://example.com"; input.value = "text"; img.src = "image.jpg"; ``` ### Changing Styles ```javascript const element = document.querySelector(".box"); element.style.color = "blue"; element.style.backgroundColor = "#f0f0f0"; element.style.fontSize = "16px"; // CSS custom properties element.style.setProperty("--my-color", "red"); // Best approach: class toggling element.classList.add("active"); element.classList.remove("hidden"); element.classList.toggle("active"); element.classList.contains("active"); ``` ## Creating and Inserting Elements ```javascript // Create element const newDiv = document.createElement("div"); newDiv.textContent = "I'm new!"; // Insert const parent = document.querySelector(".container"); // Append as last child parent.appendChild(newDiv); // Insert before another element const reference = parent.querySelector(".special"); parent.insertBefore(newDiv, reference); // Modern insertion methods parent.append(newDiv); // Append multiple children parent.prepend(newDiv); // Insert as first child element.before(newDiv); // Insert before element element.after(newDiv); // Insert after element // With text parent.append("Just text"); // Insert text node parent.prepend(document.createTextNode("Text")); ``` ### Removing Elements ```javascript const element = document.querySelector(".to-remove"); element.remove(); // Modern element.parentNode.removeChild(element); // Legacy // Remove children const parent = document.querySelector(".container"); parent.innerHTML = ""; // Remove all children while (parent.firstChild) { parent.removeChild(parent.firstChild); // Remove one by one } ``` ## Working with Classes ```javascript const element = document.querySelector(".box"); // Add class element.classList.add("active"); // Remove class element.classList.remove("disabled"); // Toggle class element.classList.toggle("expanded"); // Check class if (element.classList.contains("active")) { // Do something } // Multiple classes element.classList.add("active", "highlighted"); element.classList.remove("old", "outdated"); ``` ## Event Handling ### Adding Event Listeners ```javascript const button = document.querySelector("#myButton"); // addEventListener button.addEventListener("click", function(event) { console.log("Clicked!", event.target); }); // Arrow function button.addEventListener("click", (event) => { console.log("Clicked!", event.target); }); // Reference to named function function handleClick(event) { console.log("Clicked!", event.target); } button.addEventListener("click", handleClick); // Remove listener button.removeEventListener("click", handleClick); ``` ### Event Types ```javascript // Mouse events element.addEventListener("click", handler); element.addEventListener("dblclick", handler); element.addEventListener("mouseenter", handler); element.addEventListener("mouseleave", handler); // Keyboard events document.addEventListener("keydown", (e) => { console.log("Key:", e.key); console.log("Code:", e.code); }); document.addEventListener("keyup", handler); // Form events form.addEventListener("submit", handler); input.addEventListener("focus", handler); input.addEventListener("blur", handler); input.addEventListener("change", handler); // On change input.addEventListener("input", handler); // On every input // Document events document.addEventListener("DOMContentLoaded", handler); window.addEventListener("load", handler); window.addEventListener("resize", handler); window.addEventListener("scroll", handler); ``` ### Event Object ```javascript element.addEventListener("click", (event) => { event.target; // Element that triggered event event.currentTarget; // Element with listener event.type; // Event type ("click") event.clientX; // Mouse X position event.eventY; // Mouse Y position event.preventDefault(); // Prevent default action event.stopPropagation(); // Stop bubbling }); ``` ### Event Delegation ```javascript // Instead of adding listeners to each item document.querySelector("ul").addEventListener("click", (e) => { if (e.target.matches("li")) { console.log("Clicked:", e.target.textContent); } }); ``` ### once Option ```javascript button.addEventListener("click", handler, { once: true }); // Fires only once ``` ### preventDefault ```javascript const form = document.querySelector("form"); form.addEventListener("submit", (e) => { e.preventDefault(); // Stop form submission // Handle manually }); const link = document.querySelector("a"); link.addEventListener("click", (e) => { e.preventDefault(); // Stop navigation }); ``` ## Working with Forms ```javascript const form = document.querySelector("form"); const input = form.querySelector("input[name='username']"); // Get form data const formData = new FormData(form); const data = Object.fromEntries(formData); // Input value input.value; // Get value input.value = "new value"; // Set value input.checked; // For checkboxes/radios input.disabled = true; // Disable input ``` ## Data Attributes ```javascript const element = document.querySelector(".item"); // Read data attribute element.dataset.userId; // "123" element.dataset["userId"]; // "123" // Write data attribute element.dataset.userId = "456"; element.dataset.loading = "true"; // data-user-id -> dataset.userId (camelCase) // data-user-id-string -> dataset.userIdString ``` ## Summary - Use `querySelector`/`querySelectorAll` for flexible element selection - `textContent` is safer than `innerHTML` for plain text - Always prefer `classList` over modifying `style` directly - Use `addEventListener` for attaching event handlers - Event delegation reduces the number of event listeners - `data-*` attributes store custom data on elements
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →