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

EventTrigger
clickMouse click
dblclickDouble click
mouseoverMouse enters
mouseoutMouse leaves
keydownKey pressed
keyupKey released
submitForm submitted
inputInput 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 event
  • event.currentTarget - Element with listener
  • event.type - Event name
  • event.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

Frontend Masters

JS Hard Parts

JavaScript.info

DOM Tutorial

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!