# JavaScript DOM Manipulation Guide - Complete Reference ## Table of Contents - [Introduction](#introduction) - [Understanding the DOM](#understanding-the-dom) - [Selecting Elements](#selecting-elements) - [By ID](#by-id) - [By Class or Tag](#by-class-or-tag) - [By CSS Selector](#by-css-selector) - [Other Selection Methods](#other-selection-methods) - [Working with Element Content](#working-with-element-content) - [Text Content](#text-content) - [HTML Content](#html-content) - [Working with Attributes](#working-with-attributes) - [Getting and Setting Attributes](#getting-and-setting-attributes) - [Working with Data Attributes](#working-with-data-attributes) - [Working with CSS Styles](#working-with-css-styles) - [Inline Styles](#inline-styles) - [Computed Styles](#computed-styles) - [Working with Classes](#working-with-classes) - [Creating and Removing Elements](#creating-and-removing-elements) - [Event Handling](#event-handling) - [Adding Event Listeners](#adding-event-listeners) - [Event Object](#event-object) - [Event Propagation](#event-propagation) - [Event Delegation](#event-delegation) - [Working with Forms](#working-with-forms) - [Practical Examples](#practical-examples) - [Todo List Application](#todo-list-application) - [Modal Dialog](#modal-dialog) - [Tabs Component](#tabs-component) --- ## Introduction The Document Object Model (DOM) is a programming interface for web documents. It represents the page so that programs can change the document structure, style, and content. JavaScript interacts with the DOM to create dynamic web pages. --- ## Understanding the DOM ```javascript // The DOM tree structure // document (root) // └── html // ├── head // │ ├── title // │ └── meta // └── body // ├── header // ├── main // │ ├── section // │ └── article // └── footer // Every part of the page is a "node" in this tree console.log(document); // The entire document console.log(document.body); // The body element console.log(document.head); // The head element console.log(document.documentElement); // The html element ``` --- ## Selecting Elements ### By ID ```javascript // Get element by ID - returns single element or null const header = document.getElementById('header'); const main = document.getElementById('main-content'); const nonExistent = document.getElementById('does-not-exist'); console.log(header); // console.log(nonExistent); // null ``` ### By Class or Tag ```javascript // Get elements by class name - returns HTMLCollection (live) const buttons = document.getElementsByClassName('btn'); console.log(buttons.length); // Number of elements with class "btn" // Get elements by tag name - returns HTMLCollection (live) const paragraphs = document.getElementsByTagName('p'); const divs = document.getElementsByTagName('div'); console.log(paragraphs.length); // Number of

elements ``` ### By CSS Selector ```javascript // querySelector - returns first match or null const firstButton = document.querySelector('.btn'); const firstInput = document.querySelector('input[type="email"]'); const navItem = document.querySelector('#nav li.active'); // querySelectorAll - returns NodeList of all matches const allButtons = document.querySelectorAll('.btn'); const allSections = document.querySelectorAll('section'); const allItems = document.querySelectorAll('#nav li'); // NodeList is NOT live - it's a snapshot console.log(allButtons.length); // Number of buttons // Loop through NodeList allButtons.forEach(btn => { console.log(btn.textContent); }); // Convert to array const buttonsArray = Array.from(allButtons); ``` ### Other Selection Methods ```javascript // Get first child element (skipping text nodes) const firstChild = element.firstElementChild; // Get last child element const lastChild = element.lastElementChild; // Get parent element const parent = element.parentElement; // Get siblings const nextSibling = element.nextElementSibling; const prevSibling = element.previousElementSibling; // Get children const children = element.children; // HTMLCollection // Closest ancestor matching selector const ancestor = element.closest('.container'); ``` --- ## Working with Element Content ### Text Content ```javascript // textContent - gets/sets ALL text content (including hidden) const element = document.getElementById('myElement'); console.log(element.textContent); // Get all text element.textContent = 'New text content'; // Set text (escapes HTML) // innerText - gets/sets VISIBLE text (respects CSS) console.log(element.innerText); // Get visible text element.innerText = 'Visible text'; // Set visible text // Difference: const hidden = document.createElement('div'); hidden.style.display = 'none'; hidden.textContent = 'Hidden text'; document.body.appendChild(hidden); console.log(hidden.textContent); // "Hidden text" console.log(hidden.innerText); // "" (empty - not visible) ``` ### HTML Content ```javascript // innerHTML - gets/sets HTML content (parses as HTML) const container = document.getElementById('container'); console.log(container.innerHTML); // Get HTML container.innerHTML = '

New paragraph

'; // Set HTML // Be careful with innerHTML - can overwrite event listeners // This removes all existing children and their handlers // insertAdjacentHTML - insert HTML at specific position element.insertAdjacentHTML('beforebegin', '

Before element

'); element.insertAdjacentHTML('afterbegin', '

First child

'); element.insertAdjacentHTML('beforeend', '

Last child

'); element.insertAdjacentHTML('afterend', '

After element

'); // outerHTML - gets/sets entire element including the element itself console.log(element.outerHTML); // Get element as HTML string element.outerHTML = '
New element
'; // Replace entire element ``` --- ## Working with Attributes ### Getting and Setting Attributes ```javascript const input = document.querySelector('input[type="text"]'); // getAttribute - get attribute value console.log(input.getAttribute('id')); console.log(input.getAttribute('placeholder')); // setAttribute - set attribute value input.setAttribute('placeholder', 'Enter your name'); input.setAttribute('disabled', true); // Add boolean attribute // hasAttribute - check if attribute exists if (input.hasAttribute('required')) { console.log('Input is required'); } // removeAttribute - remove attribute input.removeAttribute('disabled'); // Direct property access for common attributes input.value = 'Hello'; // Get/set value input.disabled = true; // Get/set disabled input.checked = true; // Get/set checked (checkboxes) input.id = 'myInput'; // Get/set id input.className = 'btn primary'; // Get/set class ``` ### Working with Data Attributes ```javascript const element = document.querySelector('.user'); // data-* attributes become dataset properties element.dataset.userId = '12345'; element.dataset.role = 'admin'; element.dataset['customField'] = 'value'; // Remove data attribute delete element.dataset.userId; // Access all data attributes console.log(element.dataset); // DOMStringMap object // HTML:
// JS: element.dataset.userId → "123" // JS: element.dataset.name → "Alice" ``` --- ## Working with CSS Styles ### Inline Styles ```javascript const element = document.getElementById('myElement'); // Set individual styles element.style.color = 'red'; element.style.backgroundColor = '#f0f0f0'; element.style.fontSize = '16px'; element.style.display = 'none'; element.style.border = '1px solid black'; // CSS properties with hyphens become camelCase element.style.borderRadius = '5px'; element.style.backgroundImage = 'url("image.jpg")'; // Get inline style console.log(element.style.color); // Only returns inline styles // Set multiple styles at once using CSSText element.style.cssText = 'color: red; background: blue; padding: 10px;'; // Or use setProperty element.style.setProperty('color', 'blue'); element.style.setProperty('--custom-color', 'green'); // CSS variables ``` ### Computed Styles ```javascript const element = document.getElementById('myElement'); // getComputedStyle - get computed styles (from all sources) const styles = getComputedStyle(element); console.log(styles.color); // RGB color console.log(styles.fontSize); // Computed font size console.log(styles.display); // Display property console.log(styles.backgroundColor); // Background color // Get specific property const width = getComputedStyle(element).width; const height = getComputedStyle(element).height; // Get CSS variable const customColor = getComputedStyle(element).getPropertyValue('--custom-color'); // Get pseudo-element style const beforeStyle = getComputedStyle(element, ':before'); console.log(beforeStyle.content); ``` --- ## Working with Classes ```javascript const element = document.getElementById('myElement'); // classList - provides methods for working with classes element.classList.add('active'); // Add class element.classList.remove('hidden'); // Remove class element.classList.toggle('selected'); // Toggle class const hasClass = element.classList.contains('active'); // Check class // Add multiple classes element.classList.add('btn', 'btn-primary', 'large'); // Remove multiple classes element.classList.remove('btn', 'btn-small'); // Replace class element.classList.replace('old-class', 'new-class'); // Get class count console.log(element.classList.length); // Access class by index console.log(element.classList[0]); // className - get/set entire class attribute console.log(element.className); // Get all classes element.className = 'new-classes'; // Replaces all classes ``` --- ## Creating and Removing Elements ```javascript // Create new element const newDiv = document.createElement('div'); newDiv.id = 'new-div'; newDiv.classList.add('container'); newDiv.textContent = 'Hello World'; // Add element to DOM document.body.appendChild(newDiv); // Add as last child // Or insert at specific position const container = document.getElementById('container'); container.appendChild(newDiv); // insertBefore - insert before a reference node container.insertBefore(newDiv, container.firstChild); // Modern insertion methods container.append(newDiv, 'Text node'); // Multiple items container.prepend(newDiv); // Insert as first child container.before(newDiv); // Insert before element container.after(newDiv); // Insert after element // Clone element const clone = originalElement.cloneNode(true); // Deep clone (with children) const shallowClone = originalElement.cloneNode(false); // Just the element // Remove element newDiv.remove(); // Modern method container.removeChild(newDiv); // Old method // Replace element container.replaceChild(newElement, oldElement); container.replaceWith(newElement); // Modern method // Creating document fragments (for performance) const fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { const item = document.createElement('div'); item.textContent = `Item ${i}`; fragment.appendChild(item); } container.appendChild(fragment); // Single reflow ``` --- ## Event Handling ### Adding Event Listeners ```javascript const button = document.getElementById('myButton'); // addEventListener - recommended way to add events function handleClick(event) { console.log('Button clicked!'); } button.addEventListener('click', handleClick); // Add multiple event listeners button.addEventListener('click', () => console.log('First handler')); button.addEventListener('click', () => console.log('Second handler')); // Remove event listener (needs named function) button.removeEventListener('click', handleClick); // Options for addEventListener button.addEventListener('click', handler, { capture: false, // Use capture phase once: true, // Remove after first trigger passive: true // Promise not to call preventDefault }); // One-time event listener button.addEventListener('click', () => console.log('Only once'), { once: true }); ``` ### Event Object ```javascript element.addEventListener('click', function(event) { // event.type - type of event console.log(event.type); // "click" // event.target - element that triggered event console.log(event.target); // The clicked element // event.currentTarget - element with listener console.log(event.currentTarget); // The element with addEventListener // event.preventDefault() - prevent default behavior event.preventDefault(); // event.stopPropagation() - stop event from bubbling event.stopPropagation(); // Mouse event properties console.log(event.clientX, event.clientY); // Mouse position console.log(event.pageX, event.pageY); // Position relative to document // Keyboard event properties console.log(event.key); // Key pressed console.log(event.code); // Physical key code console.log(event.shiftKey); // Was shift held? }); // Different events element.addEventListener('click', handler); // Mouse click element.addEventListener('dblclick', handler); // Double click element.addEventListener('mouseenter', handler); // Mouse enters element.addEventListener('mouseleave', handler); // Mouse leaves element.addEventListener('mouseover', handler); // Mouse enters (bubbles) element.addEventListener('mouseout', handler); // Mouse leaves (bubbles) input.addEventListener('input', handler); // Value changes input.addEventListener('change', handler); // Value changes (on blur) input.addEventListener('focus', handler); // Gets focus input.addEventListener('blur', handler); // Loses focus document.addEventListener('keydown', handler); // Key pressed document.addEventListener('keyup', handler); // Key released form.addEventListener('submit', handler); // Form submitted ``` ### Event Propagation ```javascript // Event phases: capture → target → bubble // By default, listeners are in bubble phase const parent = document.querySelector('.parent'); const child = document.querySelector('.child'); const grandchild = document.querySelector('.grandchild'); // Stop propagation - prevent event from reaching other elements grandchild.addEventListener('click', function(event) { event.stopPropagation(); // Parent won't hear the click console.log('Grandchild clicked'); }); parent.addEventListener('click', function(event) { console.log('Parent clicked'); }); // Stop immediate propagation - stop others on same element grandchild.addEventListener('click', function(event) { event.stopImmediatePropagation(); console.log('First handler'); }); grandchild.addEventListener('click', function(event) { console.log('Second handler - won\'t run'); }); // Capture phase - event goes from root down to target parent.addEventListener('click', function(event) { console.log('Capture phase'); }, { capture: true }); // Bubble phase - event goes from target up to root (default) parent.addEventListener('click', function(event) { console.log('Bubble phase'); }); ``` ### Event Delegation ```javascript // Instead of adding listeners to each item, add to parent const list = document.getElementById('todo-list'); // Add single listener to parent list.addEventListener('click', function(event) { // Check if clicked element is an item if (event.target.matches('.todo-item')) { // Handle the item event.target.classList.toggle('completed'); } // Handle delete button within item if (event.target.matches('.delete-btn')) { event.target.parentElement.remove(); } }); // Dynamically added items automatically work const newItem = document.createElement('li'); newItem.className = 'todo-item'; newItem.textContent = 'New task'; list.appendChild(newItem); // Works without adding new listener ``` --- ## Working with Forms ```javascript const form = document.getElementById('myForm'); // Get form data const formData = new FormData(form); const data = Object.fromEntries(formData); // Or manually const name = form.name.value; const email = form.email.value; const password = form.password.value; // Checkbox const subscribe = form.subscribe.checked; // Radio buttons const gender = form.gender.value; // Selected radio's value // Select dropdown const country = form.country.value; // Selected option value const selectedOption = form.country.options[form.country.selectedIndex]; // Validate form function validateForm(form) { const errors = []; if (!form.name.value.trim()) { errors.push('Name is required'); } if (!form.email.value.includes('@')) { errors.push('Valid email is required'); } if (form.password.value.length < 8) { errors.push('Password must be at least 8 characters'); } return errors; } // Handle form submission form.addEventListener('submit', function(event) { event.preventDefault(); // Prevent page reload const errors = validateForm(form); if (errors.length > 0) { console.log('Errors:', errors); return; } // Submit form data console.log('Form is valid!'); // form.submit(); // Actually submit (if not using fetch) }); // Reset form form.reset(); ``` --- ## Practical Examples ### Todo List Application ```javascript class TodoList { constructor(containerId) { this.container = document.getElementById(containerId); this.todos = JSON.parse(localStorage.getItem('todos')) || []; this.init(); } init() { this.render(); this.setupEventListeners(); } render() { this.container.innerHTML = this.todos.map((todo, index) => `
  • ${todo.text}
  • `).join(''); } add(text) { this.todos.push({ text, completed: false }); this.save(); this.render(); } toggle(index) { this.todos[index].completed = !this.todos[index].completed; this.save(); this.render(); } delete(index) { this.todos.splice(index, 1); this.save(); this.render(); } save() { localStorage.setItem('todos', JSON.stringify(this.todos)); } setupEventListeners() { // Event delegation for dynamic elements this.container.addEventListener('click', (event) => { if (event.target.matches('input[type="checkbox"]')) { this.toggle(parseInt(event.target.dataset.index)); } if (event.target.matches('.delete-btn')) { this.delete(parseInt(event.target.dataset.index)); } }); // Add todo form const form = document.getElementById('add-todo-form'); form.addEventListener('submit', (event) => { event.preventDefault(); const input = form.querySelector('input'); if (input.value.trim()) { this.add(input.value.trim()); input.value = ''; } }); } } // Usage const todoList = new TodoList('todo-container'); ``` ### Modal Dialog ```javascript class Modal { constructor(options = {}) { this.title = options.title || 'Modal'; this.content = options.content || ''; this.onClose = options.onClose || (() => {}); this.create(); } create() { // Create modal elements this.overlay = document.createElement('div'); this.overlay.className = 'modal-overlay'; this.modal = document.createElement('div'); this.modal.className = 'modal'; this.modal.innerHTML = ` `; this.overlay.appendChild(this.modal); document.body.appendChild(this.overlay); this.setupEventListeners(); } setupEventListeners() { // Close button this.modal.querySelector('.modal-close').addEventListener('click', () => { this.close(); }); // Click outside to close this.overlay.addEventListener('click', (event) => { if (event.target === this.overlay) { this.close(); } }); // Escape key document.addEventListener('keydown', (event) => { if (event.key === 'Escape' && this.overlay.style.display !== 'none') { this.close(); } }); } open() { this.overlay.style.display = 'flex'; } close() { this.overlay.style.display = 'none'; this.onClose(); } setContent(content) { this.modal.querySelector('.modal-content').innerHTML = content; } } // Usage const modal = new Modal({ title: 'Confirm Action', content: '

    Are you sure you want to proceed?

    ', onClose: () => console.log('Modal closed') }); document.getElementById('open-modal-btn').addEventListener('click', () => { modal.open(); }); ``` ### Tabs Component ```javascript class Tabs { constructor(containerId) { this.container = document.getElementById(containerId); this.tabs = this.container.querySelectorAll('.tab'); this.panels = this.container.querySelectorAll('.tab-panel'); this.activeTab = null; this.init(); } init() { this.tabs.forEach(tab => { tab.addEventListener('click', () => { this.activate(tab.dataset.tab); }); }); // Activate first tab by default if (this.tabs.length > 0) { this.activate(this.tabs[0].dataset.tab); } } activate(tabId) { // Update tabs this.tabs.forEach(tab => { tab.classList.toggle('active', tab.dataset.tab === tabId); }); // Update panels this.panels.forEach(panel => { panel.classList.toggle('active', panel.id === tabId); }); this.activeTab = tabId; } getActiveTab() { return this.activeTab; } } // HTML structure expected: //
    //
    // // //
    //
    Content 1
    //
    Content 2
    //
    ``` --- ## Quick Reference ```javascript // Selection document.getElementById('id'); document.querySelector('.class'); document.querySelectorAll('.class'); // Content element.textContent = 'text'; element.innerHTML = '

    HTML

    '; // Attributes element.getAttribute('attr'); element.setAttribute('attr', 'value'); element.dataset.name = 'value'; // Styles element.style.color = 'red'; getComputedStyle(element).color; // Classes element.classList.add('class'); element.classList.remove('class'); element.classList.toggle('class'); // Events element.addEventListener('click', handler); element.removeEventListener('click', handler); // DOM document.createElement('div'); parent.appendChild(child); element.remove(); ```