Week 08: JavaScript DOM & Events
Unit III - Making Pages Interactive
Connecting JavaScript to HTML!
What You'll Learn
- What is the DOM?
- Selecting elements
- Modifying content and styles
- Handling user events
- Creating and removing elements
The DOM Analogy
Think of your HTML as a family tree. The DOM lets JavaScript navigate this tree, find any family member (element), and change their properties!
Press → or click Next to continue
What is the DOM?
Document Object Model - A tree representation of HTML that JavaScript can manipulate.
HTML
<html>
<head>
<title>Page</title>
</head>
<body>
<h1>Hello</h1>
<p>World</p>
</body>
</html>
DOM Tree
document
└── html
├── head
│ └── title
│ └── "Page"
└── body
├── h1
│ └── "Hello"
└── p
└── "World"
Key Concepts
- document: The root - entry point to the DOM
- Element: HTML tags (h1, p, div)
- Node: Everything including text, comments
- Parent/Child: Tree relationships
Selecting Elements
Modern Methods
// By ID - returns one element
document.getElementById('header')
// By CSS selector - returns first match
document.querySelector('.intro')
document.querySelector('#main')
document.querySelector('div.card')
// By CSS selector - returns ALL matches
document.querySelectorAll('.card')
document.querySelectorAll('p')
Older Methods
// By class name
document.getElementsByClassName('card')
// By tag name
document.getElementsByTagName('p')
// By name attribute
document.getElementsByName('email')
Prefer querySelector/querySelectorAll! They use CSS selectors and are more flexible.
querySelector vs querySelectorAll
const first = document.querySelector('.card'); // First .card element
const all = document.querySelectorAll('.card'); // NodeList of ALL .card elements
// Loop through NodeList
all.forEach(card => console.log(card));
Modifying Content
Text Content
const el = document.querySelector('h1');
// Get text content
console.log(el.textContent);
// Set text content (safe from XSS)
el.textContent = 'New Title';
// innerHTML - includes HTML tags
el.innerHTML = '<span>Bold</span> Title';
// innerText - visible text only
el.innerText = 'Visible text';
Attributes
const link = document.querySelector('a');
const img = document.querySelector('img');
// Get attribute
link.getAttribute('href')
img.src // shortcut for common attrs
// Set attribute
link.setAttribute('href', 'https://...')
img.src = 'new-image.jpg'
// Remove attribute
link.removeAttribute('target')
// Check if exists
link.hasAttribute('target')
innerHTML Security Warning
innerHTML can execute scripts! Never use with user input.
// DANGEROUS - XSS vulnerability!
el.innerHTML = userInput;
// SAFE - text only
el.textContent = userInput;
Modifying Styles
Inline Styles
const box = document.querySelector('.box');
// Set individual styles
box.style.backgroundColor = 'red';
box.style.fontSize = '20px';
box.style.marginTop = '10px';
// Note: CSS properties use camelCase!
// background-color → backgroundColor
// font-size → fontSize
// Get computed style
getComputedStyle(box).color
CSS Classes (Preferred!)
const box = document.querySelector('.box');
// Add class
box.classList.add('active');
box.classList.add('highlight', 'big');
// Remove class
box.classList.remove('active');
// Toggle class
box.classList.toggle('hidden');
// Check if has class
box.classList.contains('active');
// Replace class
box.classList.replace('old', 'new');
Best Practice
Use CSS classes instead of inline styles! Define styles in CSS, toggle classes in JS.
// CSS
.hidden { display: none; }
.active { background: #e91e63; color: white; }
// JS
element.classList.toggle('hidden');
Event Handling
Events are actions that happen in the browser (clicks, keypresses, form submissions...)
addEventListener (Best!)
const btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log('Clicked!');
});
// With arrow function
btn.addEventListener('click', () => {
console.log('Clicked!');
});
// Named function (for removal)
function handleClick() {
console.log('Clicked!');
}
btn.addEventListener('click', handleClick);
// Remove listener
btn.removeEventListener('click', handleClick);
Common Events
| Event | Trigger |
|---|---|
| click | Mouse click |
| dblclick | Double click |
| mouseover | Mouse enters |
| mouseout | Mouse leaves |
| keydown | Key pressed |
| keyup | Key released |
| submit | Form submitted |
| input | Input value changes |
The Event Object
Event handlers receive an event object with details about the event.
Basic Usage
btn.addEventListener('click', function(event) {
console.log(event.type); // "click"
console.log(event.target); // clicked element
console.log(event.currentTarget); // listener element
});
// Arrow function
btn.addEventListener('click', (e) => {
e.target.textContent = 'Clicked!';
});
Common Properties
event.target- Element that triggered eventevent.currentTarget- Element with listenerevent.type- Event nameevent.timeStamp- When it happened
Prevent Default
// Stop form submission
form.addEventListener('submit', (e) => {
e.preventDefault();
// Handle form with JS instead
});
// Stop link navigation
link.addEventListener('click', (e) => {
e.preventDefault();
console.log('Link clicked, not navigating');
});
Stop Propagation
// Stop event bubbling
inner.addEventListener('click', (e) => {
e.stopPropagation();
// Parent won't receive this click
});
Event Delegation
Instead of adding listeners to many elements, add one to their parent!
Without Delegation (Bad)
// Adding listener to EACH button
const buttons = document.querySelectorAll('.btn');
buttons.forEach(btn => {
btn.addEventListener('click', handleClick);
});
// Problem: What about dynamically added buttons?
// They won't have listeners!
With Delegation (Good)
// Single listener on parent
document.querySelector('.container')
.addEventListener('click', (e) => {
if (e.target.classList.contains('btn')) {
handleClick(e);
}
});
// Works for dynamically added elements too!
Event Bubbling
Events "bubble up" from child to parent. Click on a button inside a div? Both receive the event!
// child click → parent click → grandparent click → ... → document
Creating & Removing Elements
Creating Elements
// Create element
const div = document.createElement('div');
div.textContent = 'Hello!';
div.classList.add('card');
// Add to DOM
document.body.appendChild(div);
// or
parent.insertBefore(div, referenceElement);
// or
parent.append(div); // at end
parent.prepend(div); // at start
// Insert adjacent
el.insertAdjacentHTML('beforeend',
'<p>New paragraph</p>');
Removing Elements
// Modern way
element.remove();
// Old way
parent.removeChild(element);
// Replace element
parent.replaceChild(newEl, oldEl);
// Clone element
const clone = element.cloneNode(true);
// true = deep clone (with children)
DocumentFragment
// For adding many elements efficiently
const fragment = document.createDocumentFragment();
items.forEach(item => {
const li = document.createElement('li');
li.textContent = item;
fragment.appendChild(li);
});
ul.appendChild(fragment); // One DOM update!
DOM Traversal
Navigate between elements in the DOM tree.
Parent/Child/Sibling
const el = document.querySelector('.item');
// Parent
el.parentElement
el.parentNode
// Children
el.children // HTMLCollection
el.childNodes // includes text nodes
el.firstElementChild
el.lastElementChild
// Siblings
el.nextElementSibling
el.previousElementSibling
// Closest ancestor matching selector
el.closest('.container')
Example
<ul class="list">
<li>Item 1</li>
<li class="active">Item 2</li>
<li>Item 3</li>
</ul>
const active = document.querySelector('.active');
active.parentElement
// → ul.list
active.nextElementSibling
// → li (Item 3)
active.closest('ul')
// → ul.list
CampusKart Milestone: Interactive UI
Deliverable: Dynamic product cards, add-to-cart, search/filter, dark mode
What to Build
- Dynamically create product cards from a JS array
- "Add to Cart" button (updates cart count in nav)
- Quantity +/- controls in cart
- Remove from cart functionality
- Real-time search: filter cards as user types
- Category filter buttons
- Dark mode toggle
The Magic Moment
"Before this week, your page was a poster. Now it's an application."
Push to GitHub when done.
Video Resources
Practice Exercises
Exercise 1: Todo List
- Add items with form
- Mark as complete
- Delete items
Exercise 2: Image Gallery
- Click thumbnails
- Show in main view
- Next/Previous buttons
Exercise 3: Form Validation
- Validate on submit
- Show error messages
- Real-time feedback
Exercise 4: Accordion
- Collapsible sections
- Only one open at a time
- Smooth animation
Week 08 Summary
Key Concepts
- DOM is the tree representation of HTML
- querySelector/querySelectorAll for selecting
- textContent (safe) vs innerHTML
- classList for managing CSS classes
- addEventListener for events
- Event delegation for efficiency
- createElement, remove for DOM manipulation
Best Practices
- Use querySelector over getElementById
- Use classList over inline styles
- Use event delegation
- Use textContent for user input (XSS)
- Cache DOM selections in variables
Next Week
Week 09: Objects, JSON & AJAX!