Categories Javascript

JavaScript and the DOM

Welcome to the second part of our comprehensive JavaScript guide (Read the first part here). Now that you understand the core language features from part one, we’re ready to explore how JavaScript interacts with HTML and CSS through the Document Object Model (DOM).

The DOM is where JavaScript truly shines in web development—it’s the bridge that connects your scripts to the web page content, allowing you to create dynamic, interactive experiences for your users. With DOM manipulation, you can respond to user actions, update content without page reloads, and create web applications that feel responsive and alive.

As with the previous section, we’ve included interactive examples throughout this guide. We encourage you to experiment with these examples to gain hands-on experience with DOM manipulation techniques.

Let’s dive into the world of dynamic web content with JavaScript and the DOM!

Introduction to the DOM

The Document Object Model (DOM) is where JavaScript and HTML come together, allowing your scripts to interact with and manipulate webpage content.

What is the Document Object Model?

The DOM is a programming interface for HTML documents. It represents the page as a tree-like structure where each node is an object representing part of the document. Through the DOM, JavaScript can:

  • Access and change all HTML elements
  • Modify their attributes
  • Create new elements
  • Remove existing elements
  • React to user events

The DOM is not part of JavaScript but a Web API that browsers implement to give JavaScript access to HTML documents.

Try It Yourself: DOM Tree Visualizer

Create a file called dom-tree.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM Tree Visualizer</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .sample-page { border: 1px solid #ddd; padding: 15px; margin: 20px 0; }
        .dom-tree { font-family: monospace; background-color: #f8f8f8; padding: 15px; border-radius: 4px; }
        .node { padding-left: 20px; position: relative; }
        .node-name { font-weight: bold; color: #333; }
        .element { color: #0066cc; }
        .text { color: #666; font-style: italic; }
        .attr { color: #cc6600; }
        .highlight { background-color: #ffff99; }
        button { padding: 8px 16px; margin: 5px 0; }
    </style>
</head>
<body>
    <h1>DOM Tree Visualizer</h1>
    <p>This tool shows you how the Document Object Model (DOM) represents HTML as a tree structure.</p>
    
    <h2>Sample HTML Page:</h2>
    <div class="sample-page" id="sample">
        <h3>Hello, DOM!</h3>
        <p>This is a <strong>sample</strong> paragraph with some <em>emphasized</em> text.</p>
        <ul id="list">
            <li class="item">First item</li>
            <li class="item">Second item</li>
        </ul>
        <button id="sampleBtn">Click Me</button>
    </div>
    
    <button onclick="visualizeDom()">Show DOM Tree</button>
    <button onclick="highlightElements()">Highlight Elements in Tree</button>
    
    <h2>DOM Tree:</h2>
    <div class="dom-tree" id="domTree"></div>
    
    <script>
        function visualizeDom() {
            const sample = document.getElementById('sample');
            const domTree = document.getElementById('domTree');
            
            // Clear previous visualization
            domTree.innerHTML = '';
            
            // Recursive function to build DOM tree visualization
            function visualizeNode(node, container) {
                const nodeDiv = document.createElement('div');
                nodeDiv.className = 'node';
                
                let nodeType;
                let nodeInfo = '';
                
                // Determine node type
                if (node.nodeType === Node.ELEMENT_NODE) {
                    nodeType = 'element';
                    nodeInfo += `<span class="node-name element">&lt;${node.nodeName.toLowerCase()}</span>`;
                    
                    // Add attributes if any
                    if (node.attributes && node.attributes.length > 0) {
                        for (let i = 0; i < node.attributes.length; i++) {
                            const attr = node.attributes[i];
                            nodeInfo += ` <span class="attr">${attr.name}="${attr.value}"</span>`;
                        }
                    }
                    
                    nodeInfo += `<span class="element">&gt;</span>`;
                    
                    // Add id for highlighting later
                    nodeDiv.id = `tree-${node.nodeName.toLowerCase()}-${Math.random().toString(36).substr(2, 5)}`;
                    nodeDiv.dataset.elementId = node.id || '';
                    nodeDiv.dataset.elementClass = node.className || '';
                    nodeDiv.dataset.elementTag = node.nodeName.toLowerCase();
                    
                } else if (node.nodeType === Node.TEXT_NODE) {
                    const text = node.nodeValue.trim();
                    if (text) {
                        nodeType = 'text';
                        nodeInfo = `<span class="text">"${text}"</span>`;
                    } else {
                        return; // Skip empty text nodes
                    }
                } else {
                    return; // Skip other node types
                }
                
                nodeDiv.innerHTML = nodeInfo;
                container.appendChild(nodeDiv);
                
                // Process child nodes recursively
                if (node.childNodes && node.childNodes.length > 0) {
                    const childContainer = document.createElement('div');
                    childContainer.className = 'children';
                    nodeDiv.appendChild(childContainer);
                    
                    for (let i = 0; i < node.childNodes.length; i++) {
                        visualizeNode(node.childNodes[i], childContainer);
                    }
                }
                
                // Add closing tag for element nodes
                if (nodeType === 'element') {
                    const closeTag = document.createElement('div');
                    closeTag.innerHTML = `<span class="element">&lt;/${node.nodeName.toLowerCase()}&gt;</span>`;
                    nodeDiv.appendChild(closeTag);
                }
            }
            
            visualizeNode(sample, domTree);
        }
        
        function highlightElements() {
            // Reset previous highlights
            const highlighted = document.querySelectorAll('.highlight');
            highlighted.forEach(el => el.classList.remove('highlight'));
            
            // Highlight by tag name
            const liNodes = document.querySelectorAll('[data-element-tag="li"]');
            liNodes.forEach(node => node.classList.add('highlight'));
            
            // Optionally highlight by id or class
            // const btnNode = document.querySelector('[data-element-id="sampleBtn"]');
            // if (btnNode) btnNode.classList.add('highlight');
        }
        
        // Initialize the visualization
        visualizeDom();
    </script>
</body>
</html>

Open this file in your browser to see a visual representation of the DOM tree. This example:

  • Shows how HTML elements are represented as a nested tree structure
  • Demonstrates the parent-child relationships between elements
  • Highlights different node types (elements, text nodes, attributes)
  • Lets you interactively explore the DOM hierarchy

This visualization helps you understand how JavaScript “sees” your HTML document and how the DOM API provides access to this structure.

Selecting DOM Elements

Before you can manipulate elements, you need to select them:

// Single element selectors
const element = document.getElementById('myId');             // Selects by ID (fastest)
const element = document.querySelector('.myClass');         // Selects first matching CSS selector

// Multiple element selectors
const elements = document.getElementsByClassName('myClass'); // Returns HTMLCollection
const elements = document.getElementsByTagName('div');       // Returns HTMLCollection
const elements = document.querySelectorAll('.myClass');     // Returns NodeList

getElementById() and querySelector() return a single element, while getElementsByClassName()getElementsByTagName(), and querySelectorAll() return collections of elements that you can iterate through.

The querySelector() and querySelectorAll() methods accept any valid CSS selector, making them powerful but potentially slower than more specific methods.

Try It Yourself: Element Selector Playground

Create a file called dom-selectors.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM Element Selectors</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .sandbox { border: 1px solid #ddd; padding: 15px; margin: 20px 0; position: relative; }
        .box { display: inline-block; width: 80px; height: 80px; margin: 10px; text-align: center; 
               line-height: 80px; background-color: #f0f0f0; border-radius: 4px; }
        .red { background-color: #ffcccc; }
        .green { background-color: #ccffcc; }
        .blue { background-color: #ccccff; }
        .selected { border: 2px solid #ff6600; box-shadow: 0 0 10px rgba(255, 102, 0, 0.5); }
        .control-panel { background-color: #f8f8f8; padding: 15px; border-radius: 4px; margin-bottom: 20px; }
        .selector-input { width: 70%; padding: 8px; font-family: monospace; }
        .result { font-family: monospace; background-color: #eee; padding: 10px; border-radius: 4px; 
                 margin-top: 10px; min-height: 40px; white-space: pre-wrap; }
        button { padding: 8px 16px; margin: 0 5px; }
    </style>
</head>
<body>
    <h1>DOM Element Selectors Playground</h1>
    <p>This playground helps you practice different methods of selecting elements in the DOM.</p>
    
    <div class="control-panel">
        <div style="margin-bottom: 10px;">
            <label for="selectorMethod">Selection Method:</label>
            <select id="selectorMethod">
                <option value="getElementById">getElementById</option>
                <option value="getElementsByClassName">getElementsByClassName</option>
                <option value="getElementsByTagName">getElementsByTagName</option>
                <option value="querySelector">querySelector</option>
                <option value="querySelectorAll">querySelectorAll</option>
            </select>
        </div>
        
        <div style="margin-bottom: 10px;">
            <label for="selectorInput">Selector:</label>
            <input type="text" id="selectorInput" class="selector-input" placeholder="Enter selector (e.g., 'box-1' for ID, 'red' for class)">
        </div>
        
        <button onclick="selectElements()">Select Elements</button>
        <button onclick="resetSelection()">Reset Selection</button>
        
        <div class="result" id="selectorResult">// Selection results will appear here</div>
    </div>
    
    <div class="sandbox" id="elementSandbox">
        <div id="box-1" class="box red">Box 1</div>
        <div id="box-2" class="box green">Box 2</div>
        <div id="box-3" class="box blue">Box 3</div>
        <div id="box-4" class="box red">Box 4</div>
        <div id="box-5" class="box green">Box 5</div>
        <div id="box-6" class="box blue">Box 6</div>
        <div id="box-7" class="box red">Box 7</div>
        <div id="box-8" class="box green">Box 8</div>
        <div id="box-9" class="box blue">Box 9</div>
    </div>
    
    <div id="codePreview" class="result">// Generated code will appear here</div>
    
    <script>
        function selectElements() {
            // Reset previous selection
            resetSelection();
            
            const method = document.getElementById('selectorMethod').value;
            const selector = document.getElementById('selectorInput').value;
            
            if (!selector) {
                document.getElementById('selectorResult').textContent = "Please enter a selector";
                return;
            }
            
            let selectedElements;
            let code = "";
            let result = "";
            
            try {
                switch(method) {
                    case 'getElementById':
                        code = `const element = document.getElementById('${selector}');`;
                        selectedElements = [document.getElementById(selector)];
                        break;
                        
                    case 'getElementsByClassName':
                        code = `const elements = document.getElementsByClassName('${selector}');`;
                        selectedElements = document.getElementsByClassName(selector);
                        break;
                        
                    case 'getElementsByTagName':
                        code = `const elements = document.getElementsByTagName('${selector}');`;
                        selectedElements = document.getElementsByTagName(selector);
                        break;
                        
                    case 'querySelector':
                        code = `const element = document.querySelector('${selector}');`;
                        selectedElements = [document.querySelector(selector)];
                        break;
                        
                    case 'querySelectorAll':
                        code = `const elements = document.querySelectorAll('${selector}');`;
                        selectedElements = document.querySelectorAll(selector);
                        break;
                }
                
                // Convert collection to array for easier handling
                selectedElements = Array.from(selectedElements).filter(el => el);
                
                // Add selected class to matched elements
                selectedElements.forEach(el => {
                    el.classList.add('selected');
                });
                
                // Generate result message
                if (selectedElements.length === 0) {
                    result = "No elements matched your selector";
                } else {
                    result = `Selected ${selectedElements.length} element(s):\n`;
                    
                    selectedElements.forEach((el, index) => {
                        result += `Element ${index + 1}: <${el.tagName.toLowerCase()}`;
                        
                        if (el.id) result += ` id="${el.id}"`;
                        if (el.className) result += ` class="${el.className.replace('selected', '').trim()}"`;
                        
                        result += ">\n";
                    });
                }
                
                document.getElementById('selectorResult').textContent = result;
                document.getElementById('codePreview').textContent = code;
                
            } catch (error) {
                document.getElementById('selectorResult').textContent = `Error: ${error.message}`;
            }
        }
        
        function resetSelection() {
            const selected = document.querySelectorAll('.selected');
            selected.forEach(el => el.classList.remove('selected'));
            document.getElementById('codePreview').textContent = "// Generated code will appear here";
        }
    </script>
</body>
</html>

Open this file in your browser to experiment with different ways of selecting DOM elements. The playground allows you to:

  • Select elements using different methods (getElementById, querySelector, etc.)
  • See which elements match your selectors
  • View the JavaScript code you would write to perform the selection
  • Visualize the selected elements with highlighting
  • Understand how different selectors and methods behave

This interactive tool helps you practice and understand various DOM selection techniques, which are the foundation of DOM manipulation.

Manipulating DOM Elements

Once you’ve selected elements, you can manipulate them in various ways:

// Changing content
element.textContent = "New text";                       // Safe way to set text
element.innerHTML = "<span>HTML content</span>";        // Parses and renders HTML

// Modifying attributes
element.setAttribute('class', 'newClass');              // Sets attribute value
element.getAttribute('href');                           // Gets attribute value
element.removeAttribute('disabled');                    // Removes attribute
element.style.backgroundColor = 'blue';                 // Sets CSS property

// Adding/removing classes
element.classList.add('active');                        // Adds class
element.classList.remove('inactive');                   // Removes class
element.classList.toggle('highlighted');                // Toggles class on/off
element.classList.contains('selected');                 // Checks if class exists

Be cautious when using innerHTML as it can pose security risks if you’re inserting user-provided content. For text-only changes, textContent is safer and faster.

Try It Yourself: DOM Manipulation Lab

Create a file called dom-manipulation.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM Manipulation Lab</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .playground { border: 1px solid #ddd; padding: 20px; margin: 20px 0; border-radius: 4px; }
        .control-panel { background-color: #f0f0f0; padding: 15px; margin-bottom: 20px; border-radius: 4px; }
        #targetElement { width: 200px; height: 200px; background-color: #f0f0f0; 
                         border: 1px solid #ccc; margin: 20px auto; display: flex; 
                         align-items: center; justify-content: center; text-align: center;
                         transition: all 0.3s ease; }
        .action-buttons button { margin: 5px; padding: 8px 12px; }
        .code-preview { font-family: monospace; background-color: #eee; padding: 10px; 
                       border-radius: 4px; margin-top: 10px; white-space: pre-wrap; }
        .input-row { margin-bottom: 10px; }
        label { display: inline-block; width: 100px; }
        input, select { padding: 5px; width: 200px; }
        .success { color: #4CAF50; }
        .error { color: #F44336; }
    </style>
</head>
<body>
    <h1>DOM Manipulation Lab</h1>
    <p>Experiment with different ways to manipulate DOM elements in this interactive lab.</p>
    
    <div class="playground">
        <div class="control-panel">
            <h3>Content Manipulation</h3>
            <div class="input-row">
                <label for="contentType">Type:</label>
                <select id="contentType">
                    <option value="text">Text (textContent)</option>
                    <option value="html">HTML (innerHTML)</option>
                </select>
            </div>
            <div class="input-row">
                <label for="contentValue">Content:</label>
                <input type="text" id="contentValue" value="Hello, DOM!">
            </div>
            <button type="button" onclick="changeContent()">Update Content</button>
            <div id="contentCodePreview" class="code-preview">// Code will appear here</div>
        </div>
        
        <div class="control-panel">
            <h3>Style Manipulation</h3>
            <div class="input-row">
                <label for="styleProperty">Property:</label>
                <select id="styleProperty">
                    <option value="backgroundColor">Background Color</option>
                    <option value="color">Text Color</option>
                    <option value="fontSize">Font Size</option>
                    <option value="borderRadius">Border Radius</option>
                    <option value="transform">Transform (Rotate)</option>
                </select>
            </div>
            <div class="input-row">
                <label for="styleValue">Value:</label>
                <input type="text" id="styleValue" value="#3498db">
            </div>
            <button type="button" onclick="changeStyle()">Apply Style</button>
            <div id="styleCodePreview" class="code-preview">// Code will appear here</div>
        </div>
        
        <div class="control-panel">
            <h3>Class Manipulation</h3>
            <div class="input-row">
                <label for="className">Class Name:</label>
                <input type="text" id="className" value="highlight">
            </div>
            <div class="action-buttons">
                <button type="button" onclick="addClass()">Add Class</button>
                <button type="button" onclick="removeClass()">Remove Class</button>
                <button type="button" onclick="toggleClass()">Toggle Class</button>
                <button type="button" onclick="checkClass()">Check Class</button>
            </div>
            <div id="classResult" class="success"></div>
            <div id="classCodePreview" class="code-preview">// Code will appear here</div>
        </div>
        
        <div class="control-panel">
            <h3>Attribute Manipulation</h3>
            <div class="input-row">
                <label for="attrName">Attribute:</label>
                <input type="text" id="attrName" value="data-status">
            </div>
            <div class="input-row">
                <label for="attrValue">Value:</label>
                <input type="text" id="attrValue" value="active">
            </div>
            <div class="action-buttons">
                <button type="button" id="setAttributeBtn">Set Attribute</button>
                <button type="button" id="getAttributeBtn">Get Attribute</button>
                <button type="button" id="removeAttributeBtn">Remove Attribute</button>
            </div>
            <div id="attrResult" class="success"></div>
            <div id="attrCodePreview" class="code-preview">// Code will appear here</div>
        </div>
        
        <div id="targetElement">
            Target Element
        </div>
        
        <button type="button" onclick="resetElement()">Reset Element</button>
    </div>
    
    <script>
        // Content manipulation
        function changeContent() {
            const element = document.getElementById('targetElement');
            const type = document.getElementById('contentType').value;
            const content = document.getElementById('contentValue').value;
            let code = '';
            
            if (type === 'text') {
                element.textContent = content;
                code = `element.textContent = "${content}";`;
            } else {
                element.innerHTML = content;
                code = `element.innerHTML = "${content.replace(/"/g, '\\"')}";`;
            }
            
            document.getElementById('contentCodePreview').textContent = code;
        }
        
        // Style manipulation
        function changeStyle() {
            const element = document.getElementById('targetElement');
            const property = document.getElementById('styleProperty').value;
            const value = document.getElementById('styleValue').value;
            
            // Special case for transform to demonstrate rotation
            if (property === 'transform') {
                element.style[property] = `rotate(${value}deg)`;
            } else {
                element.style[property] = value;
            }
            
            const code = `element.style.${property} = "${element.style[property]}";`;
            document.getElementById('styleCodePreview').textContent = code;
        }
        
        // Class manipulation
        function addClass() {
            const element = document.getElementById('targetElement');
            const className = document.getElementById('className').value;
            
            if (!className) {
                document.getElementById('classResult').textContent = 'Error: Class name is required';
                document.getElementById('classResult').className = 'error';
                return;
            }
            
            element.classList.add(className);
            
            const code = `element.classList.add("${className}");`;
            document.getElementById('classCodePreview').textContent = code;
            document.getElementById('classResult').textContent = `Class "${className}" added`;
            document.getElementById('classResult').className = 'success';
        }
        
        function removeClass() {
            const element = document.getElementById('targetElement');
            const className = document.getElementById('className').value;
            
            if (!className) {
                document.getElementById('classResult').textContent = 'Error: Class name is required';
                document.getElementById('classResult').className = 'error';
                return;
            }
            
            element.classList.remove(className);
            
            const code = `element.classList.remove("${className}");`;
            document.getElementById('classCodePreview').textContent = code;
            document.getElementById('classResult').textContent = `Class "${className}" removed`;
            document.getElementById('classResult').className = 'success';
        }
        
        function toggleClass() {
            const element = document.getElementById('targetElement');
            const className = document.getElementById('className').value;
            
            if (!className) {
                document.getElementById('classResult').textContent = 'Error: Class name is required';
                document.getElementById('classResult').className = 'error';
                return;
            }
            
            const wasPresent = element.classList.contains(className);
            element.classList.toggle(className);
            
            const code = `element.classList.toggle("${className}");`;
            document.getElementById('classCodePreview').textContent = code;
            document.getElementById('classResult').textContent = 
                wasPresent ? `Class "${className}" removed` : `Class "${className}" added`;
            document.getElementById('classResult').className = 'success';
        }
        
        function checkClass() {
            const element = document.getElementById('targetElement');
            const className = document.getElementById('className').value;
            
            if (!className) {
                document.getElementById('classResult').textContent = 'Error: Class name is required';
                document.getElementById('classResult').className = 'error';
                return;
            }
            
            const hasClass = element.classList.contains(className);
            
            const code = `const hasClass = element.classList.contains("${className}");
// Returns: ${hasClass}`;
            document.getElementById('classCodePreview').textContent = code;
            document.getElementById('classResult').textContent = 
                hasClass ? `Element has class "${className}"` : `Element does not have class "${className}"`;
            document.getElementById('classResult').className = 'success';
        }
        
        // Attribute manipulation functions
        function setAttribute() {
            const element = document.getElementById('targetElement');
            const attrName = document.getElementById('attrName').value;
            const attrValue = document.getElementById('attrValue').value;
            
            if (!attrName) {
                document.getElementById('attrResult').textContent = 'Error: Attribute name is required';
                document.getElementById('attrResult').className = 'error';
                return;
            }
            
            element.setAttribute(attrName, attrValue);
            
            const code = `element.setAttribute("${attrName}", "${attrValue}");`;
            document.getElementById('attrCodePreview').textContent = code;
            document.getElementById('attrResult').textContent = 
                `Attribute "${attrName}" set to "${attrValue}"`;
            document.getElementById('attrResult').className = 'success';
        }
        
        function getAttribute() {
            const element = document.getElementById('targetElement');
            const attrName = document.getElementById('attrName').value;
            
            if (!attrName) {
                document.getElementById('attrResult').textContent = 'Error: Attribute name is required';
                document.getElementById('attrResult').className = 'error';
                return;
            }
            
            const value = element.getAttribute(attrName);
            
            const code = `const value = element.getAttribute("${attrName}");
// Returns: ${value !== null ? `"${value}"` : 'null'}`;
            document.getElementById('attrCodePreview').textContent = code;
            document.getElementById('attrResult').textContent = 
                value !== null ? `Attribute "${attrName}" value is "${value}"` : `Attribute "${attrName}" is not set`;
            document.getElementById('attrResult').className = 'success';
        }
        
        function removeAttribute() {
            const element = document.getElementById('targetElement');
            const attrName = document.getElementById('attrName').value;
            
            if (!attrName) {
                document.getElementById('attrResult').textContent = 'Error: Attribute name is required';
                document.getElementById('attrResult').className = 'error';
                return;
            }
            
            element.removeAttribute(attrName);
            
            const code = `element.removeAttribute("${attrName}");`;
            document.getElementById('attrCodePreview').textContent = code;
            document.getElementById('attrResult').textContent = 
                `Attribute "${attrName}" removed`;
            document.getElementById('attrResult').className = 'success';
        }
        
        // Reset the target element to its initial state
        function resetElement() {
            const element = document.getElementById('targetElement');
            element.textContent = 'Target Element';
            element.className = '';
            element.style = '';
            
            // Remove all attributes except ID
            const attributes = Array.from(element.attributes);
            for (let attr of attributes) {
                if (attr.name !== 'id') {
                    element.removeAttribute(attr.name);
                }
            }
            
            document.getElementById('contentCodePreview').textContent = '// Code will appear here';
            document.getElementById('styleCodePreview').textContent = '// Code will appear here';
            document.getElementById('classCodePreview').textContent = '// Code will appear here';
            document.getElementById('attrCodePreview').textContent = '// Code will appear here';
            document.getElementById('classResult').textContent = '';
            document.getElementById('attrResult').textContent = '';
        }
        
        // Add proper event listeners instead of inline onclick for attribute functions
        document.addEventListener('DOMContentLoaded', function() {
            document.getElementById('setAttributeBtn').addEventListener('click', setAttribute);
            document.getElementById('getAttributeBtn').addEventListener('click', getAttribute);
            document.getElementById('removeAttributeBtn').addEventListener('click', removeAttribute);
        });
    </script>
</body>
</html>

Open this file in your browser to experiment with different DOM manipulation techniques. This interactive lab allows you to:

  • Modify element content using both textContent and innerHTML
  • Apply CSS styles directly through the style property
  • Add, remove, toggle, and check for CSS classes
  • Set, get, and remove element attributes
  • See the JavaScript code for each manipulation
  • Reset the element to its original state

This hands-on practice helps you understand how to change elements’ appearance and behavior using JavaScript’s DOM manipulation capabilities.

Creating and Removing Elements

You can dynamically create and remove DOM elements:

// Creating elements
const newDiv = document.createElement('div');           // Create element
newDiv.textContent = 'New element';                     // Add content
document.body.appendChild(newDiv);                      // Add to DOM

// Removing elements
element.remove();                                       // Remove element
parentElement.removeChild(childElement);                // Remove child from parent

Try It Yourself: Dynamic Element Creator

Create a file called element-creator.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Element Creator</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .control-panel { background-color: #f0f0f0; padding: 15px; margin-bottom: 20px; border-radius: 4px; }
        .input-row { margin-bottom: 10px; }
        label { display: inline-block; width: 120px; }
        input, select { padding: 5px; width: 200px; }
        button { padding: 8px 16px; margin: 5px; }
        .element-container { border: 1px dashed #ccc; min-height: 200px; padding: 20px; margin-top: 20px; }
        .code-preview { font-family: monospace; background-color: #eee; padding: 10px; 
                       border-radius: 4px; margin-top: 10px; white-space: pre-wrap; }
        .created-element { margin: 10px; padding: 10px; background-color: #f9f9f9; 
                          border: 1px solid #ddd; border-radius: 4px; position: relative; }
        .remove-btn { position: absolute; right: 5px; top: 5px; background: #ff6666; 
                     color: white; border: none; border-radius: 50%; width: 20px; height: 20px; 
                     line-height: 20px; text-align: center; cursor: pointer; }
    </style>
</head>
<body>
    <h1>Dynamic Element Creator</h1>
    <p>Create, customize, and remove DOM elements dynamically with JavaScript.</p>
    
    <div class="control-panel">
        <h2>Create New Element</h2>
        
        <div class="input-row">
            <label for="elementType">Element Type:</label>
            <select id="elementType">
                <option value="div">div</option>
                <option value="p">p</option>
                <option value="button">button</option>
                <option value="h3">h3</option>
                <option value="span">span</option>
                <option value="input">input</option>
                <option value="img">img</option>
            </select>
        </div>
        
        <div class="input-row">
            <label for="elementContent">Content:</label>
            <input type="text" id="elementContent" value="New Element">
        </div>
        
        <div class="input-row">
            <label for="elementClass">CSS Class:</label>
            <input type="text" id="elementClass" placeholder="Optional class name">
        </div>
        
        <div class="input-row">
            <label for="elementStyle">Inline Style:</label>
            <input type="text" id="elementStyle" placeholder="color: blue; font-weight: bold;">
        </div>
        
        <div class="input-row" id="attributesContainer">
            <label>Attributes:</label>
            <button onclick="addAttributeField()">+ Add Attribute</button>
        </div>
        
        <button onclick="createNewElement()">Create Element</button>
        <button onclick="clearContainer()">Clear All Elements</button>
        
        <div id="codePreview" class="code-preview">// Code will appear here</div>
    </div>
    
    <h2>Created Elements:</h2>
    <div id="elementsContainer" class="element-container">
        <!-- Dynamically created elements will appear here -->
    </div>
    
    <script>
        let attributeCount = 0;
        
        function addAttributeField() {
            const container = document.getElementById('attributesContainer');
            const fieldGroup = document.createElement('div');
            fieldGroup.className = 'input-row attribute-field';
            fieldGroup.style.marginLeft = '120px';
            fieldGroup.style.marginTop = '5px';
            
            const nameInput = document.createElement('input');
            nameInput.type = 'text';
            nameInput.placeholder = 'Attribute name';
            nameInput.style.width = '120px';
            nameInput.style.marginRight = '10px';
            nameInput.id = `attrName${attributeCount}`;
            
            const valueInput = document.createElement('input');
            valueInput.type = 'text';
            valueInput.placeholder = 'Attribute value';
            valueInput.style.width = '120px';
            valueInput.id = `attrValue${attributeCount}`;
            
            const removeBtn = document.createElement('button');
            removeBtn.textContent = 'X';
            removeBtn.style.marginLeft = '5px';
            removeBtn.onclick = function() {
                container.removeChild(fieldGroup);
            };
            
            fieldGroup.appendChild(nameInput);
            fieldGroup.appendChild(valueInput);
            fieldGroup.appendChild(removeBtn);
            container.appendChild(fieldGroup);
            
            attributeCount++;
        }
        
        function createNewElement() {
            const container = document.getElementById('elementsContainer');
            const type = document.getElementById('elementType').value;
            const content = document.getElementById('elementContent').value;
            const className = document.getElementById('elementClass').value;
            const style = document.getElementById('elementStyle').value;
            
            // Generate code
            let code = `// Create new element\nconst newElement = document.createElement("${type}");\n`;
            
            // Create the element
            const newElement = document.createElement(type);
            
            // Handle different element types specially
            if (type === 'input') {
                newElement.value = content;
                code += `newElement.value = "${content}";\n`;
            } else if (type === 'img') {
                newElement.src = content || 'https://via.placeholder.com/150';
                newElement.alt = "Image";
                code += `newElement.src = "${newElement.src}";\n`;
                code += `newElement.alt = "Image";\n`;
            } else {
                newElement.textContent = content;
                code += `newElement.textContent = "${content}";\n`;
            }
            
            // Add class if specified
            if (className) {
                newElement.className = className;
                code += `newElement.className = "${className}";\n`;
            }
            
            // Add style if specified
            if (style) {
                newElement.style.cssText = style;
                code += `newElement.style.cssText = "${style}";\n`;
            }
            
            // Add custom attributes
            const attributeFields = document.querySelectorAll('.attribute-field');
            attributeFields.forEach((field, index) => {
                const nameInput = document.getElementById(`attrName${index}`);
                const valueInput = document.getElementById(`attrValue${index}`);
                
                if (nameInput && valueInput && nameInput.value) {
                    newElement.setAttribute(nameInput.value, valueInput.value);
                    code += `newElement.setAttribute("${nameInput.value}", "${valueInput.value}");\n`;
                }
            });
            
            // Wrap the created element in a container for better handling
            const elementWrapper = document.createElement('div');
            elementWrapper.className = 'created-element';
            
            // Add remove button
            const removeBtn = document.createElement('button');
            removeBtn.className = 'remove-btn';
            removeBtn.textContent = 'x';
            removeBtn.title = 'Remove this element';
            removeBtn.onclick = function() {
                container.removeChild(elementWrapper);
            };
            
            elementWrapper.appendChild(removeBtn);
            elementWrapper.appendChild(newElement);
            
            // Add to DOM
            container.appendChild(elementWrapper);
            
            // Complete the code preview
            code += `\n// Add to DOM\ndocument.body.appendChild(newElement);\n\n`;
            code += `// To remove the element\n// newElement.remove();\n`;
            code += `// or\n// parentElement.removeChild(newElement);`;
            
            document.getElementById('codePreview').textContent = code;
        }
        
        function clearContainer() {
            const container = document.getElementById('elementsContainer');
            container.innerHTML = '';
            document.getElementById('codePreview').textContent = '// All elements removed\ncontainer.innerHTML = "";';
        }
    </script>
</body>
</html>

Open this file in your browser to practice creating and removing DOM elements. This interactive tool allows you to:

  • Create different types of HTML elements dynamically
  • Set element content, styles, classes, and attributes
  • See the JavaScript code that performs these operations
  • Remove individual elements or clear all created elements
  • Understand how element creation and removal work in the DOM

This hands-on exercise demonstrates how JavaScript can be used to modify the page structure on the fly, enabling dynamic web applications.

Event Handling

Event handling allows your code to respond to user interactions:

const button = document.querySelector('button');

button.addEventListener('click', function(event) {
    console.log('Button clicked!');
    console.log(event);        // Event object contains details about the event
});

// Alternative with arrow function
button.addEventListener('mouseover', (event) => {
    console.log('Mouse over button');
});

// Removing event listeners
function handleClick(event) {
    console.log('Clicked');
}
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick);       // Same function reference needed

Common events include:

  • Mouse events: clickdblclickmouseovermouseout
  • Keyboard events: keydownkeyupkeypress
  • Form events: submitchangeinput
  • Document/Window events: loadresizescroll

The event object provides information about the event, such as which element triggered it, mouse coordinates, key pressed, etc.

Try It Yourself: Event Handler Playground

Create a file called event-handlers.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Event Handlers</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .playground { border: 1px solid #ddd; padding: 20px; margin: 20px 0; border-radius: 4px; }
        .event-box { width: 300px; height: 200px; background-color: #f0f0f0; 
                    border: 1px solid #ccc; margin: 20px auto; display: flex; 
                    align-items: center; justify-content: center; position: relative; }
        .control-panel { background-color: #f8f8f8; padding: 15px; margin-bottom: 20px; border-radius: 4px; }
        .event-log { height: 200px; overflow-y: auto; background-color: #222; color: #0f0; 
                    font-family: monospace; padding: 10px; border-radius: 4px; }
        .event-log-entry { margin: 2px 0; }
        .timestamp { color: #999; }
        .code-preview { font-family: monospace; background-color: #eee; padding: 10px; 
                      border-radius: 4px; margin-top: 10px; white-space: pre-wrap; }
        input, button, select { margin: 5px; padding: 5px; }
        .coordinates { position: absolute; bottom: 5px; right: 5px; font-size: 12px; color: #666; }
    </style>
</head>
<body>
    <h1>JavaScript Event Handlers Playground</h1>
    <p>Experiment with different event types and handlers in this interactive playground.</p>
    
    <div class="control-panel">
        <h2>Event Configuration</h2>
        
        <div>
            <label for="eventType">Event Type:</label>
            <select id="eventType">
                <optgroup label="Mouse Events">
                    <option value="click">click</option>
                    <option value="dblclick">dblclick</option>
                    <option value="mousedown">mousedown</option>
                    <option value="mouseup">mouseup</option>
                    <option value="mousemove">mousemove</option>
                    <option value="mouseover">mouseover</option>
                    <option value="mouseout">mouseout</option>
                </optgroup>
                <optgroup label="Keyboard Events">
                    <option value="keydown">keydown</option>
                    <option value="keyup">keyup</option>
                    <option value="keypress">keypress</option>
                </optgroup>
                <optgroup label="Form Events">
                    <option value="focus">focus</option>
                    <option value="blur">blur</option>
                    <option value="change">change</option>
                    <option value="input">input</option>
                </optgroup>
            </select>
        </div>
        
        <div>
            <button onclick="addEventHandler()">Add Event Handler</button>
            <button onclick="removeEventHandler()">Remove Event Handler</button>
            <button onclick="clearLog()">Clear Log</button>
        </div>
        
        <div id="codePreview" class="code-preview">// Select event type and click "Add Event Handler"</div>
    </div>
    
    <div class="playground">
        <div id="eventBox" class="event-box" tabindex="0">
            <p>Interact with this box</p>
            <div id="coordinates" class="coordinates"></div>
        </div>
        
        <input type="text" id="textInput" placeholder="Type here for keyboard events" style="width: 300px; display: block; margin: 0 auto;">
        
        <h3>Event Log:</h3>
        <div id="eventLog" class="event-log">
            <div class="event-log-entry">
                <span class="timestamp">[System] </span>Select an event type and click "Add Event Handler"
            </div>
        </div>
    </div>
    
    <script>
        // Event handler storage to enable removal
        const eventHandlers = {};
        
        function logEvent(event) {
            const eventLog = document.getElementById('eventLog');
            const entry = document.createElement('div');
            entry.className = 'event-log-entry';
            
            const now = new Date();
            const timestamp = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}.${now.getMilliseconds()}`;
            
            // Basic event info
            let eventInfo = `${event.type} on <${event.target.tagName.toLowerCase()}>`;
            
            // Event-specific details
            if (event.type.startsWith('mouse')) {
                // Update coordinates display
                document.getElementById('coordinates').textContent = `X: ${event.clientX}, Y: ${event.clientY}`;
                
                // Add to log
                eventInfo += ` at position (${event.offsetX}, ${event.offsetY})`;
                if (event.buttons > 0) eventInfo += ` with button ${event.button}`;
            } else if (event.type.startsWith('key')) {
                eventInfo += ` - key: ${event.key} (code: ${event.code})`;
            } else if (event.type === 'input' || event.type === 'change') {
                eventInfo += ` - value: "${event.target.value}"`;
            }
            
            entry.innerHTML = `<span class="timestamp">[${timestamp}] </span>${eventInfo}`;
            eventLog.appendChild(entry);
            eventLog.scrollTop = eventLog.scrollHeight; // Auto-scroll to bottom
        }
        
        function addEventHandler() {
            const eventType = document.getElementById('eventType').value;
            
            // Determine the appropriate target element
            let targetElement;
            if (eventType.startsWith('key') || ['focus', 'blur', 'change', 'input'].includes(eventType)) {
                targetElement = document.getElementById('textInput');
            } else {
                targetElement = document.getElementById('eventBox');
            }
            
            // Remove any existing handler for this event type
            if (eventHandlers[eventType]) {
                targetElement.removeEventListener(eventType, eventHandlers[eventType]);
            }
            
            // Create and add the new handler
            eventHandlers[eventType] = function(event) {
                logEvent(event);
            };
            
            targetElement.addEventListener(eventType, eventHandlers[eventType]);
            
            // Log the addition
            const eventLog = document.getElementById('eventLog');
            const entry = document.createElement('div');
            entry.className = 'event-log-entry';
            entry.innerHTML = `<span class="timestamp">[System] </span>Added "${eventType}" event handler`;
            eventLog.appendChild(entry);
            
            // Generate code preview
            const elementName = targetElement.id === 'textInput' ? 'inputElement' : 'boxElement';
            const code = `// Select the element
const ${elementName} = document.getElementById('${targetElement.id}');

// Add event listener
${elementName}.addEventListener('${eventType}', function(event) {
    console.log('${eventType} event detected!', event);
    
    // Access event properties
    console.log('Event type:', event.type);
    console.log('Target element:', event.target);
    ${eventType.startsWith('mouse') ? `\n    // Mouse event specific properties
    console.log('Mouse position:', event.clientX, event.clientY);
    console.log('Relative to target:', event.offsetX, event.offsetY);` : ''}
    ${eventType.startsWith('key') ? `\n    // Keyboard event specific properties
    console.log('Key pressed:', event.key);
    console.log('Key code:', event.code);` : ''}
    ${['input', 'change'].includes(eventType) ? `\n    // Form event specific properties
    console.log('New value:', event.target.value);` : ''}
});`;
            
            document.getElementById('codePreview').textContent = code;
            
            // Focus the appropriate element for keyboard/form events
            if (eventType.startsWith('key') || ['focus', 'blur', 'change', 'input'].includes(eventType)) {
                targetElement.focus();
            }
        }
        
        function removeEventHandler() {
            const eventType = document.getElementById('eventType').value;
            
            // Determine the appropriate target element
            let targetElement;
            if (eventType.startsWith('key') || ['focus', 'blur', 'change', 'input'].includes(eventType)) {
                targetElement = document.getElementById('textInput');
            } else {
                targetElement = document.getElementById('eventBox');
            }
            
            // Remove the handler if it exists
            if (eventHandlers[eventType]) {
                targetElement.removeEventListener(eventType, eventHandlers[eventType]);
                delete eventHandlers[eventType];
                
                // Log the removal
                const eventLog = document.getElementById('eventLog');
                const entry = document.createElement('div');
                entry.className = 'event-log-entry';
                entry.innerHTML = `<span class="timestamp">[System] </span>Removed "${eventType}" event handler`;
                eventLog.appendChild(entry);
                
                // Update code preview
                const elementName = targetElement.id === 'textInput' ? 'inputElement' : 'boxElement';
                const code = `// To remove an event listener, you need the original function reference
${elementName}.removeEventListener('${eventType}', handlerFunction);

// This is why it's often better to use named functions rather than anonymous ones
function handlerFunction(event) {
    // Event handling code
}

// Then you can add and remove it easily
${elementName}.addEventListener('${eventType}', handlerFunction);
${elementName}.removeEventListener('${eventType}', handlerFunction);`;
                
                document.getElementById('codePreview').textContent = code;
            } else {
                // No handler exists to remove
                const eventLog = document.getElementById('eventLog');
                const entry = document.createElement('div');
                entry.className = 'event-log-entry';
                entry.innerHTML = `<span class="timestamp">[System] </span>No "${eventType}" handler to remove`;
                eventLog.appendChild(entry);
            }
        }
        
        function clearLog() {
            const eventLog = document.getElementById('eventLog');
            eventLog.innerHTML = '<div class="event-log-entry"><span class="timestamp">[System] </span>Log cleared</div>';
        }
        
        // Add a mousemove handler by default
        document.addEventListener('DOMContentLoaded', function() {
            document.getElementById('eventType').value = 'mousemove';
            addEventHandler();
        });
    </script>
</body>
</html>

Open this file in your browser to experiment with different JavaScript event handlers. This interactive playground allows you to:

  • Add and remove event listeners for various event types
  • Interact with elements and see real-time event logging
  • View event details like mouse coordinates or key codes
  • See the JavaScript code that handles different events
  • Understand how event propagation works

This hands-on experience helps you learn how to make your web pages interactive by responding to user actions.

What’s Next?

Well done! You now have the skills to select, manipulate, create, and remove DOM elements, as well as respond to user interactions through event handling. These capabilities form the foundation of dynamic web development with JavaScript.

In the final document of this series, “JavaScript Best Practices and Practical Applications,” we’ll focus on writing high-quality JavaScript code, avoiding common pitfalls, and applying your knowledge to real-world scenarios. You’ll learn debugging techniques, common mistakes to avoid, and see practical examples that bring together all the concepts covered in the series.

Ready to elevate your JavaScript code to professional standards? Continue to the next section to learn about best practices and practical applications.

You May Also Like