DOM & Browser APIs
The Document Object Model (DOM) is a tree-like representation of your HTML. JavaScript can read, modify, and react to changes in the DOM. This is what makes web pages interactive.
1. Selecting Elements
Modern Methods
// Single element (first match)
const header = document.querySelector('h1');
const button = document.querySelector('#submit-btn');
const card = document.querySelector('.card');
// Multiple elements (NodeList)
const items = document.querySelectorAll('.item');
const links = document.querySelectorAll('a[href^="https"]');
// Iterate NodeList
items.forEach(item => console.log(item.textContent));
// Convert to array for more methods
const itemsArray = [...items];
const filtered = itemsArray.filter(item => item.classList.contains('active'));
Legacy Methods (Still Useful)
document.getElementById('myId'); // Single element
document.getElementsByClassName('myClass'); // HTMLCollection
document.getElementsByTagName('div'); // HTMLCollection
Best Practice: Use querySelector and querySelectorAll for flexibility. They accept any CSS selector.
2. Traversing the DOM
Navigate relative to an element.
const item = document.querySelector('.item');
// Parents
item.parentElement; // Direct parent
item.closest('.container'); // Closest ancestor matching selector
// Children
item.children; // HTMLCollection of child elements
item.firstElementChild; // First child element
item.lastElementChild; // Last child element
// Siblings
item.nextElementSibling; // Next sibling element
item.previousElementSibling; // Previous sibling element
3. Modifying Elements
Text & HTML Content
const heading = document.querySelector('h1');
// Text content (safe, no HTML parsing)
heading.textContent = 'New Heading';
// HTML content (parses HTML, use with caution)
heading.innerHTML = '<span>New</span> Heading';
// Outer HTML (includes the element itself)
heading.outerHTML = '<h2>Replaced!</h2>';
Security: Never use innerHTML with user input. It can lead to XSS attacks. Use textContent or sanitize the input.
Attributes
const link = document.querySelector('a');
// Get/Set attributes
link.getAttribute('href');
link.setAttribute('href', 'https://example.com');
link.removeAttribute('target');
link.hasAttribute('rel');
// Direct property access (for standard attributes)
link.href = 'https://example.com';
link.id = 'main-link';
// Data attributes
// <div data-user-id="123" data-role="admin">
const div = document.querySelector('div');
div.dataset.userId; // '123'
div.dataset.role; // 'admin'
div.dataset.newProp = 'value'; // Adds data-new-prop="value"
Classes
const element = document.querySelector('.card');
// Modern classList API
element.classList.add('active', 'highlighted');
element.classList.remove('hidden');
element.classList.toggle('collapsed');
element.classList.contains('active'); // true/false
element.classList.replace('old', 'new');
// Multiple operations
element.className = 'card active'; // Overwrites all classes
Styles
const box = document.querySelector('.box');
// Inline styles (not recommended for many changes)
box.style.backgroundColor = 'blue';
box.style.marginTop = '20px';
box.style.cssText = 'color: red; font-size: 16px;';
// Get computed styles
const styles = getComputedStyle(box);
styles.width; // '200px'
4. Creating & Removing Elements
Creating Elements
// Create element
const div = document.createElement('div');
div.className = 'card';
div.textContent = 'Hello World';
// Create from HTML string
const template = `
<div class="card">
<h2>Title</h2>
<p>Content</p>
</div>
`;
// Use insertAdjacentHTML (see below)
Inserting Elements
const container = document.querySelector('.container');
const newElement = document.createElement('div');
// Append/Prepend (multiple nodes allowed)
container.append(newElement); // Add to end
container.prepend(newElement); // Add to start
container.append('Text', anotherEl); // Multiple items
// Insert at specific position
container.insertAdjacentElement('beforebegin', newElement); // Before container
container.insertAdjacentElement('afterbegin', newElement); // First child
container.insertAdjacentElement('beforeend', newElement); // Last child
container.insertAdjacentElement('afterend', newElement); // After container
// Insert HTML string
container.insertAdjacentHTML('beforeend', '<div class="new">New</div>');
Removing & Replacing
const element = document.querySelector('.to-remove');
// Remove
element.remove();
// Replace
const newEl = document.createElement('span');
element.replaceWith(newEl);
// Clone
const clone = element.cloneNode(true); // true = deep clone
container.append(clone);
5. Event Handling
Adding Event Listeners
const button = document.querySelector('button');
// Standard way
button.addEventListener('click', (event) => {
console.log('Clicked!', event);
});
// With options
button.addEventListener('click', handler, {
once: true, // Remove after first trigger
passive: true, // Never calls preventDefault (scroll perf)
capture: true // Trigger during capture phase
});
// Remove listener
button.removeEventListener('click', handler);
The Event Object
document.addEventListener('click', (event) => {
event.target; // Element that triggered the event
event.currentTarget; // Element the listener is attached to
event.type; // 'click'
event.timeStamp; // When it happened
event.preventDefault(); // Stop default behavior (e.g., form submit)
event.stopPropagation(); // Stop bubbling to parent elements
});
Event Delegation
Instead of adding listeners to many elements, add one to a parent.
// ❌ Bad: Listener on each item
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
// ✅ Good: Delegate to parent
document.querySelector('.list').addEventListener('click', (event) => {
if (event.target.matches('.item')) {
handleClick(event.target);
}
// Or for nested elements:
const item = event.target.closest('.item');
if (item) handleClick(item);
});
Common Events
// Mouse
element.addEventListener('click', fn);
element.addEventListener('dblclick', fn);
element.addEventListener('mouseenter', fn); // No bubble
element.addEventListener('mouseleave', fn); // No bubble
element.addEventListener('mouseover', fn); // Bubbles
// Keyboard
document.addEventListener('keydown', (e) => {
console.log(e.key); // 'Enter', 'a', 'ArrowUp'
console.log(e.code); // 'Enter', 'KeyA', 'ArrowUp'
console.log(e.ctrlKey); // true if Ctrl held
});
// Form
form.addEventListener('submit', (e) => {
e.preventDefault();
const data = new FormData(form);
});
input.addEventListener('input', fn); // Every change
input.addEventListener('change', fn); // On blur/enter
// Window
window.addEventListener('load', fn); // All resources loaded
window.addEventListener('DOMContentLoaded', fn); // DOM ready
window.addEventListener('resize', fn);
window.addEventListener('scroll', fn);
6. Browser APIs
Local Storage
Persist data in the browser (survives page refresh).
// Store
localStorage.setItem('user', JSON.stringify({ name: 'Alice' }));
// Retrieve
const user = JSON.parse(localStorage.getItem('user'));
// Remove
localStorage.removeItem('user');
// Clear all
localStorage.clear();
// Session storage (cleared when tab closes)
sessionStorage.setItem('temp', 'data');
Fetch API
Make HTTP requests (covered in Async chapter).
const response = await fetch('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'value' })
});
const data = await response.json();
Geolocation
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position.coords.latitude);
console.log(position.coords.longitude);
},
(error) => {
console.error(error.message);
}
);
Intersection Observer
Efficiently detect when elements enter/exit the viewport.
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target); // Stop observing
}
});
}, {
threshold: 0.5 // 50% visible
});
document.querySelectorAll('.animate-on-scroll').forEach(el => {
observer.observe(el);
});
Clipboard API
// Copy to clipboard
await navigator.clipboard.writeText('Copied text!');
// Read from clipboard
const text = await navigator.clipboard.readText();
History API
Manipulate browser history for SPAs.
// Add to history (without page reload)
history.pushState({ page: 1 }, 'Title', '/new-url');
// Replace current entry
history.replaceState({ page: 2 }, 'Title', '/updated-url');
// Listen for back/forward
window.addEventListener('popstate', (event) => {
console.log(event.state); // { page: 1 }
});
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
// Get values
formData.get('username');
formData.get('email');
// Convert to object
const data = Object.fromEntries(formData);
// Send to server
fetch('/api/submit', {
method: 'POST',
body: formData // Automatically sets Content-Type
});
});
Validation
const input = document.querySelector('input[name="email"]');
// Built-in validation
input.required = true;
input.pattern = '[a-z]+@[a-z]+\\.[a-z]+';
// Check validity
input.checkValidity(); // true/false
input.validity.valid; // true/false
input.validity.valueMissing; // true if empty but required
input.validity.patternMismatch; // true if doesn't match pattern
// Custom validation
input.setCustomValidity('Please enter a valid email');
input.setCustomValidity(''); // Clear error
Summary
The DOM is your interface to the web page:
- Selection: Use
querySelector and querySelectorAll.
- Modification: Change text, attributes, classes, and styles.
- Creation:
createElement, append, insertAdjacentHTML.
- Events: Use delegation for better performance.
- Browser APIs: Storage, Geolocation, Intersection Observer, etc.
With these fundamentals, you can build dynamic, interactive web applications!
🎉 Course Complete!
Congratulations on completing the JavaScript Crash Course! You now have a solid foundation in:
- Fundamentals — Variables, types, and control flow
- Functions & Scope — Closures and higher-order functions
- Objects & Prototypes — The JavaScript object model
- Async JavaScript — Promises and async/await
- Modern JavaScript — ES6+ features
- DOM & Browser APIs — Building interactive web pages
What’s Next?
- Practice: Build projects! A todo app, weather app, or portfolio site.
- Frameworks: Learn React, Vue, or Angular.
- Backend: Explore Node.js for server-side JavaScript.
- TypeScript: Add static typing to your JavaScript.
Happy coding! 🚀