Skip to main content
  1. Javascripts/

JavaScript DOM Manipulation: A Comprehensive Guide

·1871 words·9 mins·
JavaScript DOM Web Development Frontend Manipulation
Ifarra
Author
Ifarra
Disturbing the peace!!
Table of Contents

JavaScript DOM Manipulation: A Comprehensive Guide
#

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the page so that programs can change the document structure, style, and content. JavaScript uses the DOM to dynamically update and modify web pages, creating interactive and engaging user experiences. This article provides a comprehensive guide to DOM manipulation with JavaScript, covering essential techniques and best practices.

What is the DOM?
#

The DOM is a tree-like structure representing the HTML elements of a webpage. Each HTML element becomes a node in the tree, allowing JavaScript to access and modify these elements. The browser builds the DOM when a webpage is loaded.

Selecting DOM Elements
#

The first step in DOM manipulation is selecting the elements you want to modify. JavaScript provides several methods for selecting DOM elements:

  • document.getElementById(id): Selects an element by its id attribute. This is the fastest and most specific way to select a single element.

    const myElement = document.getElementById("my-element");
    console.log(myElement); // Outputs the element with the id "my-element"
    
  • document.getElementsByClassName(className): Selects all elements with the specified class name. Returns an HTMLCollection, a live collection of elements.

    const elements = document.getElementsByClassName("my-class");
    console.log(elements); // Outputs an HTMLCollection of elements with the class "my-class"
    // Iterate through the collection:
    for (let i = 0; i < elements.length; i++) {
        console.log(elements[i]);
    }
    
  • document.getElementsByTagName(tagName): Selects all elements with the specified tag name. Returns an HTMLCollection.

    const paragraphs = document.getElementsByTagName("p");
    console.log(paragraphs); // Outputs an HTMLCollection of all paragraph elements
    
  • document.querySelector(selector): Selects the first element that matches the specified CSS selector. More versatile than getElementById, getElementsByClassName and getElementsByTagName for complex selectors, but potentially slower.

    const firstParagraph = document.querySelector("p"); // Selects the first paragraph
    const elementWithClass = document.querySelector(".my-class"); // Selects the first element with class "my-class"
    const elementInsideDiv = document.querySelector("div > p"); // Selects the first paragraph that's a direct child of a div
    
  • document.querySelectorAll(selector): Selects all elements that match the specified CSS selector. Returns a NodeList, a non-live collection of elements.

    const allParagraphs = document.querySelectorAll("p");
    console.log(allParagraphs); // Outputs a NodeList of all paragraph elements
    // Iterate through the NodeList:
    allParagraphs.forEach(paragraph => {
        console.log(paragraph);
    });
    

Important Considerations:

  • HTMLCollection is a live collection. Changes to the DOM are reflected immediately in the collection.
  • NodeList returned by querySelectorAll is typically static. Changes to the DOM are not reflected in the collection after it’s created. (Though some browsers/specific uses can result in a live NodeList.)
  • querySelector and querySelectorAll use CSS selectors, offering powerful and flexible ways to target elements. Remember CSS selector specificity rules apply.
  • querySelector only returns the first matching element, while querySelectorAll returns all matching elements.

Modifying Element Attributes
#

After selecting an element, you can modify its attributes:

  • element.getAttribute(attributeName): Retrieves the value of an attribute.

    const link = document.getElementById("my-link");
    const href = link.getAttribute("href");
    console.log(href); // Outputs the URL in the href attribute
    
  • element.setAttribute(attributeName, attributeValue): Sets the value of an attribute.

    link.setAttribute("href", "https://www.example.com");
    link.setAttribute("target", "_blank");
    
  • element.removeAttribute(attributeName): Removes an attribute.

    link.removeAttribute("target");
    
  • Shortcut for commonly used attributes: You can directly access and modify some attributes like id, className, src, href, etc., as properties of the element object.

    const image = document.getElementById("my-image");
    image.src = "new-image.jpg";
    image.alt = "New Image Description";
    console.log(image.src);
    console.log(image.alt);
    
  • element.classList: Provides methods to manipulate an element’s classes:

    • element.classList.add(className): Adds a class to the element.
    • element.classList.remove(className): Removes a class from the element.
    • element.classList.toggle(className): Adds the class if it’s not present, removes it if it is.
    • element.classList.contains(className): Returns true if the element has the class, false otherwise.
    const button = document.getElementById("my-button");
    button.classList.add("highlight");
    button.classList.remove("disabled");
    button.classList.toggle("active");
    if (button.classList.contains("active")) {
        console.log("Button is active!");
    }
    

Modifying Element Content
#

You can change the content within an element using these properties:

  • element.textContent: Gets or sets the text content of an element (and all its descendants). This is generally preferred over innerText for setting text, as it’s more performant and predictable.

    const heading = document.getElementById("my-heading");
    heading.textContent = "New Heading Text";
    console.log(heading.textContent); // Outputs "New Heading Text"
    
  • element.innerHTML: Gets or sets the HTML content of an element. Use with caution as it can introduce security vulnerabilities (XSS) if you’re inserting user-provided content without proper sanitization.

    const paragraph = document.getElementById("my-paragraph");
    paragraph.innerHTML = "<p>This is a <strong>bold</strong> paragraph.</p>";
    console.log(paragraph.innerHTML); // Outputs the HTML content
    
  • element.outerHTML: Gets or sets the HTML representation of the element itself, including the opening and closing tags.

    const div = document.getElementById("my-div");
    div.outerHTML = "<section>This is a new section.</section>";
    

Creating and Appending DOM Nodes
#

To dynamically add new elements to the page, you can create and append DOM nodes:

  • document.createElement(tagName): Creates a new element with the specified tag name.

    const newParagraph = document.createElement("p");
    
  • document.createTextNode(text): Creates a new text node.

    const paragraphText = document.createTextNode("This is a new paragraph.");
    
  • element.appendChild(node): Appends a node as the last child of an element.

    newParagraph.appendChild(paragraphText);
    document.body.appendChild(newParagraph); // Appends to the end of the body
    
  • element.insertBefore(newNode, existingNode): Inserts a node before an existing child node.

    const existingHeading = document.getElementById("my-heading");
    document.body.insertBefore(newParagraph, existingHeading); // Inserts before the heading
    
  • element.removeChild(node): Removes a child node from an element.

    document.body.removeChild(newParagraph);
    
  • element.replaceChild(newNode, oldNode): Replaces a child node with a new node.

    const newHeading = document.createElement("h2");
    newHeading.textContent = "Replaced Heading";
    document.body.replaceChild(newHeading, existingHeading);
    

Example: Creating and Appending a List Item

const myList = document.getElementById("my-list");
const newListItem = document.createElement("li");
newListItem.textContent = "New List Item";
myList.appendChild(newListItem);

DOM Traversal
#

DOM traversal involves navigating the DOM tree to find related elements.

  • element.parentNode: Returns the parent node of an element.

    const listItem = document.querySelector("li");
    const list = listItem.parentNode; // Returns the <ul> or <ol> element
    
  • element.childNodes: Returns a NodeList of all child nodes of an element.

    const listChildren = list.childNodes;
    console.log(listChildren);
    
  • element.firstChild: Returns the first child node of an element.

    const firstChild = list.firstChild;
    
  • element.lastChild: Returns the last child node of an element.

    const lastChild = list.lastChild;
    
  • element.nextSibling: Returns the next sibling node of an element.

    const nextItem = listItem.nextSibling;
    
  • element.previousSibling: Returns the previous sibling node of an element.

    const previousItem = listItem.previousSibling;
    
  • element.children: Returns an HTMLCollection of only the element children (ignores text nodes).

    const listElementChildren = list.children; //only contains other list items (<li>)
    

Important Considerations:

  • childNodes includes text nodes (e.g., whitespace between elements), while children only includes element nodes. This can affect your iteration logic.

Styling Elements
#

You can modify the style of elements using the element.style property:

  • element.style.propertyName = value: Sets the CSS property of an element. Property names are camelCased (e.g., backgroundColor, fontSize).

    const heading = document.getElementById("my-heading");
    heading.style.color = "blue";
    heading.style.backgroundColor = "lightgray";
    heading.style.fontSize = "24px";
    

This directly manipulates the inline styles of the element. While convenient for simple changes, it’s generally better to control styling using CSS classes for maintainability and separation of concerns. Use element.classList as shown earlier to toggle or add/remove classes.

Handling Events
#

Event handling allows you to respond to user interactions and other events on the page.

  • element.addEventListener(event, function, useCapture): Attaches an event listener to an element.

    • event: The name of the event (e.g., “click”, “mouseover”, “keydown”).
    • function: The function to be executed when the event occurs. Also known as the event handler.
    • useCapture: Optional. A boolean value that specifies whether the event should be captured or bubbled. (Advanced; default is false, meaning bubbling.)
    const button = document.getElementById("my-button");
    button.addEventListener("click", function(event) {
        console.log("Button clicked!");
        console.log(event.target); // The element that triggered the event (the button)
    });
    
  • Common Events:

    • click: When an element is clicked.
    • mouseover: When the mouse pointer is moved onto an element.
    • mouseout: When the mouse pointer is moved away from an element.
    • keydown: When a key is pressed down.
    • keyup: When a key is released.
    • submit: When a form is submitted.
    • load: When the page or an element has finished loading.
    • DOMContentLoaded: When the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. (Use this when your javascript requires DOM to be ready).
  • Event Object: The event handler function receives an event object as an argument. This object contains information about the event, such as the target element (event.target), the type of event (event.type), and the coordinates of the mouse pointer (event.clientX, event.clientY).

  • event.preventDefault(): Prevents the default action of an event (e.g., preventing a link from navigating or a form from submitting).

    const link = document.getElementById("my-link");
    link.addEventListener("click", function(event) {
        event.preventDefault(); // Prevents the link from navigating
        console.log("Link clicked, but navigation prevented!");
    });
    
  • event.stopPropagation(): Prevents the event from bubbling up to parent elements.

    document.getElementById("inner").addEventListener("click", function(event) {
      console.log("Inner div clicked");
      event.stopPropagation(); // Stops event from reaching the outer div
    });
    
    document.getElementById("outer").addEventListener("click", function(event) {
      console.log("Outer div clicked"); // Won't be triggered if the inner div is clicked
    });
    
  • element.removeEventListener(event, function): Removes an event listener from an element. Note: you need to provide the exact same function reference that was originally added. This is easiest to achieve if you define the function and store it in a variable, and then use that variable when adding and removing the listener.

    function handleClick(event) {
        console.log("Button clicked!");
    }
    
    button.addEventListener("click", handleClick);
    
    // Later, to remove the listener:
    button.removeEventListener("click", handleClick);
    

Best Practices for DOM Manipulation
#

  • Minimize DOM Access: DOM operations can be expensive. Minimize the number of times you access the DOM.
  • Batch Updates: Group multiple DOM updates together to avoid unnecessary reflows and repaints. Consider using a DocumentFragment when creating several nodes at once before appending them.
  • Use Event Delegation: Delegate event handling to a parent element to reduce the number of event listeners. Instead of attaching a click handler to each list item, attach a click handler to the list itself and check the event.target to determine which list item was clicked.
  • Avoid innerHTML for complex or user-provided content: Prefer creating and appending elements using createElement, createTextNode, and appendChild to avoid potential security risks (XSS attacks). Sanitize user-provided data before inserting it into the DOM if innerHTML is unavoidable.
  • Cache DOM Elements: Store references to frequently used DOM elements in variables to avoid repeatedly querying the DOM.

Example: Dynamic List Filtering
#

This example demonstrates how to dynamically filter a list of items based on user input.

<!DOCTYPE html>
<html>
<head>
    <title>Dynamic List Filtering</title>
</head>
<body>
    <input type="text" id="filterInput" placeholder="Filter items...">
    <ul id="itemList">
        <li>Apple</li>
        <li>Banana</li>
        <li>Orange</li>
        <li>Grapes</li>
        <li>Mango</li>
    </ul>

    <script>
        const filterInput = document.getElementById("filterInput");
        const itemList = document.getElementById("itemList");
        const listItems = itemList.getElementsByTagName("li");

        filterInput.addEventListener("keyup", function() {
            const filterValue = filterInput.value.toUpperCase();

            for (let i = 0; i < listItems.length; i++) {
                const listItem = listItems[i];
                const itemText = listItem.textContent.toUpperCase();

                if (itemText.indexOf(filterValue) > -1) {
                    listItem.style.display = ""; // Show the item
                } else {
                    listItem.style.display = "none"; // Hide the item
                }
            }
        });
    </script>
</body>
</html>

In this example:

  1. We select the input field and the list using their IDs.
  2. We get all list items using getElementsByTagName.
  3. We add a keyup event listener to the input field.
  4. Inside the event listener, we get the filter value, convert it to uppercase, and iterate through the list items.
  5. For each list item, we get its text content, convert it to uppercase, and check if it contains the filter value.
  6. If the item text contains the filter value, we show the item; otherwise, we hide it.

Conclusion
#

DOM manipulation is a fundamental skill for web developers. By understanding how to select, modify, create, and append DOM elements, you can create dynamic and interactive web applications. Remember to follow best practices to optimize performance and maintainability. By applying the concepts and techniques covered in this guide, you’ll be well-equipped to tackle a wide range of DOM manipulation tasks.

Related

JavaScript Performance Optimization Techniques
·1666 words·8 mins
JavaScript Performance Optimization Web Development Front-End
This article explores practical JavaScript performance optimization strategies, focusing on efficient code writing, memory management, browser rendering, and modern tools for performance profiling.
Understanding the JavaScript Event Loop: A Deep Dive
·1165 words·6 mins
JavaScript Event Loop Asynchronous Single-Threaded Concurrency
This article provides a comprehensive explanation of the JavaScript event loop, detailing how it enables non-blocking behavior and manages asynchronous tasks in a single-threaded environment. We&rsquo;ll cover the call stack, heap, callback queue, and microtask queue, along with practical examples.
Two Sum - Leetcode
·794 words·4 mins
Python Leetcode Leetcode-Easy Notes
How to sove Two Sum problem from Leetcode and its explaination