Lecture 28 - DOM Manipulation & Events

DOM Manipulation & Events ๐ŸŽช

Making Webpages Come Alive with JavaScript

CSCI 3403 - Web Programming

Week 15, Class 30

Today's Mission: Learn how to make your webpage interactive and responsive to user actions!

"The DOM is your playground - let's make it dance!"

Today's Learning Objectives

What is the DOM? ๐ŸŒณ

Document Object Model

The DOM is: A tree-like representation of your HTML that JavaScript can interact with

<div id="container">
  <div class="display"></div>
  <div class="controls"></div>
</div>

๐Ÿ“ฆ Nodes

Everything in the DOM (elements, text, comments)

๐Ÿท๏ธ Elements

HTML tags that become element nodes

DOM Family Tree ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ

Understanding Relationships

<div id="container"> โ† Parent
  <div class="display"></div> โ† Child & Sibling
  <div class="controls"></div> โ† Child & Sibling
</div>

Parent-Child

Elements directly inside another

Siblings

Elements at the same level

Ancestors

All parent elements up the tree

Descendants

All children down the tree

Selecting Elements ๐ŸŽฏ

Query Selectors are Your Best Friends

// Select ONE element
const header = document.querySelector("#header");
const button = document.querySelector(".btn-primary");

// Select ALL matching elements (returns NodeList)
const allDivs = document.querySelectorAll("div");
const buttons = document.querySelectorAll("button");

// Complex selectors work too!
const nested = document.querySelector(".container .item:first-child");
Pro Tip: querySelector returns the FIRST match. Use querySelectorAll for multiple elements!

Navigating the DOM ๐Ÿงญ

Moving Through Elements

Going Down:

element.firstElementChild
element.lastElementChild
element.children

Going Sideways:

element.nextElementSibling
element.previousElementSibling

Going Up:

element.parentElement
element.closest(".ancestor-class") // Finds nearest ancestor

Creating Elements ๐Ÿ—๏ธ

Building DOM Nodes in Memory

// Step 1: Create element in memory
const newDiv = document.createElement("div");

// Step 2: Add content and attributes
newDiv.textContent = "Hello World!";
newDiv.id = "my-div";
newDiv.classList.add("highlight");

// Step 3: Add it to the page
container.appendChild(newDiv);
Important: Elements exist in memory until you add them to the DOM with appendChild() or append()!

Modifying Elements โœจ

Changing Content and Properties

Text Content

element.textContent = "New text";
// Safe, doesn't parse HTML

HTML Content

element.innerHTML = "<p>HTML</p>";
// Powerful but risky

Attributes

element.id = "header";
element.setAttribute("data-id", "123");

Classes

element.classList.add("active");
element.classList.toggle("hidden");

Removing Elements ๐Ÿ—‘๏ธ

Clean Up Your DOM

// Modern way (ES6+)
element.remove();

// Classic way
parent.removeChild(element);

// Remove all children
while (parent.firstChild) {
  parent.removeChild(parent.firstChild);
}

// Or use innerHTML (be careful!)
parent.innerHTML = "";

Styling Elements ๐ŸŽญ

Multiple Approaches

โœ… Good: Toggle Classes

element.classList.toggle("dark-mode");

Clean, reusable, separates concerns

โš ๏ธ Use Sparingly: Inline Styles

element.style.backgroundColor = "blue";
element.style.fontSize = "20px";

OK for dynamic values, avoid for static styles

Note: CSS properties use camelCase in JS: background-color โ†’ backgroundColor

Exercise: Build a Container ๐Ÿ’ป

Let's Practice Together!

Create this structure using only JavaScript:

<div id="container">
  <p style="color: red">Hey I'm red!</p>
  <h3 style="color: blue">I'm a blue h3!</h3>
  <div>
    <h1>I'm in a div</h1>
    <p>ME TOO!</p>
  </div>
</div>

Events: Making It Interactive ๐ŸŽช

Responding to User Actions

Events are: Things that happen on your webpage (clicks, key presses, mouse movements, etc.)

Common Events:

click dblclick mouseover mouseout keydown keyup submit load scroll focus
๐ŸŽฎ

The First Computer Game

1952 - Cambridge University

  • In 1952, A.S. Douglas created OXO (tic-tac-toe) for the EDSAC computer at Cambridge University as part of his PhD dissertation on human-computer interaction.
  • It was one of the first games to use a visual display and allowed a human player to compete against the computer.
  • The game used a 35ร—16-pixel cathode ray tube display, and players interacted using a rotary telephone controller.
๐Ÿ–ฅ๏ธ [Imagine: A grainy black-and-white image of the EDSAC computer with OXO displayed]

Source: Computer History Museum

๐Ÿ’ก Connection to Events

This pioneering game demonstrates how event-driven programming enables interactive experiences. Just like OXO responded to player input via the rotary controller, modern web applications use event listeners to respond to user actions like clicks, hovers, and key presses!

Reflection: The First Computer Game ๐Ÿค”

๐Ÿง  Think About It:

How did OXO's need to respond to user input in 1952 lay the groundwork for the event-driven programming we use today in JavaScript?

Discussion Points:

  • What similarities exist between OXO's rotary controller input and modern click events?
  • How has event-driven programming evolved from 1952 to today?
  • What would A.S. Douglas think of modern web games and interactions?

Key Takeaway: Every click handler you write is part of a 70+ year legacy of making computers respond to human input!

Three Ways to Add Events 3๏ธโƒฃ

โŒ Method 1: HTML Attribute

<button onclick="alert('Hi!')">Click</button>

Mixes JS with HTML, only one handler

โš ๏ธ Method 2: DOM Property

btn.onclick = () => alert("Hi!");

Better, but still only one handler

โœ… Method 3: addEventListener

btn.addEventListener("click", () => {
  alert("Hi!");
});

Clean, multiple handlers possible, most flexible!

addEventListener() ๐ŸŽฏ

The Right Wayโ„ข

const button = document.querySelector("#myButton");

// Anonymous function
button.addEventListener("click", () => {
  console.log("Clicked!");
});

// Named function (reusable!)
function handleClick() {
  console.log("Button was clicked!");
}
button.addEventListener("click", handleClick);

// With event object
button.addEventListener("click", (e) => {
  console.log(e.target); // The clicked element
  e.target.style.background = "blue";
});

The Event Object ๐Ÿ“ฆ

Information About What Happened

button.addEventListener("click", function(e) {
  // e is the event object
  console.log(e.type); // "click"
  console.log(e.target); // Element that was clicked
  console.log(e.currentTarget); // Element with listener
  console.log(e.clientX); // Mouse X position
  console.log(e.clientY); // Mouse Y position
  console.log(e.timeStamp); // When it happened
});
๐Ÿ–ฑ๏ธ

The Computer Mouse Was Named for Its Tail

1964 - Stanford Research Institute

  • Douglas Engelbart invented the computer mouse in 1964 at Stanford Research Institute. The first prototype was a wooden shell with two metal wheels.
  • It was nicknamed "mouse" because the cord coming out the back looked like a tail. The cursor was originally called a "bug".
  • Engelbart chose this design after experimenting with various devices including knee-operated controls and head-mounted devices!
๐Ÿชต [Imagine: The original wooden mouse prototype with its "tail" cord]

Source: Computer History Museum

๐Ÿ’ก Connection to Mouse Events

Engelbart's invention revolutionized user interaction with computers. Today, mouse events (click, mouseover, mouseout, mousemove) are fundamental to web development. Every addEventListener for a mouse event traces back to that wooden box with a tail!

Reflection: The Computer Mouse ๐Ÿค”

๐Ÿง  Think About It:

Before the mouse, users interacted with computers primarily through keyboards and punch cards. How did the mouse fundamentally change the way we think about computer interfaces?

Consider:

  • What types of interactions does the mouse make possible that keyboards can't?
  • How do touchscreens (touch events) continue this evolution?
  • What's the next evolution beyond mouse and touch?

Fun Fact: Engelbart's mouse had the buttons on top and the cord on the back. Modern mice flipped both - but we still call the cord a "tail"!

Mouse Events in Action ๐Ÿ–ฑ๏ธ

Thanks to Douglas Engelbart!

click

button.addEventListener("click", (e) => {
  console.log("Clicked!");
});

dblclick

element.addEventListener("dblclick", (e) => {
  console.log("Double clicked!");
});

mouseover / mouseout

div.addEventListener("mouseover", (e) => {
  e.target.classList.add("hover");
});

mousemove

document.addEventListener("mousemove", (e) => {
  console.log(e.clientX, e.clientY);
});

Event Bubbling ๐Ÿซง

Events Travel Up the DOM Tree

<div class="outer">
  <div class="middle">
    <button class="inner">Click Me</button>
  </div>
</div>

When you click the button:

1๏ธโƒฃ Button's handler fires first

2๏ธโƒฃ Then middle div's handler

3๏ธโƒฃ Then outer div's handler

4๏ธโƒฃ All the way up to document!

Stop It: Use e.stopPropagation() to prevent bubbling!
๐ŸŽฌ

The Mother of All Demos

December 9, 1968 - San Francisco

  • On December 9, 1968, Douglas Engelbart (yes, the mouse inventor!) gave a 90-minute demonstration that changed computing forever.
  • In one demo, he introduced: the computer mouse, hypertext, video conferencing, collaborative editing, and windows.
  • This demo inspired the development of the graphical user interface and modern interactive computing as we know it today.
  • The demo was performed live in front of 1,000 computer professionals - none had seen anything like it!
๐ŸŽฅ [Imagine: Engelbart presenting with his headset mic and display screens showing collaborative editing]

Source: "The Mother of All Demos" - Stanford Research Institute

The Demo That Changed Everything ๐Ÿš€

๐Ÿ’ก Connection to Event-Driven Interfaces

Engelbart's demo showed that computers could be interactive, collaborative, and intuitive. The concepts he introduced - clicking on hyperlinks, moving windows, editing documents collaboratively - all depend on event-driven programming. Every event listener you write today is part of realizing Engelbart's vision!

๐Ÿง  Think About It:

Engelbart demonstrated technology in 1968 that wouldn't become mainstream until the 1980s and 1990s. What do you think he would say about how we use event-driven interfaces today (web apps, mobile apps, VR)?

From 1968 to Today: When you write addEventListener(), you're implementing the same fundamental concept Engelbart showed 50+ years ago - computers that respond to human actions in real-time!

Common DOM Patterns ๐Ÿ“š

Real-World Examples

Toggle Dark Mode

btn.addEventListener("click", () => {
  document.body.classList.toggle("dark");
});

Form Validation

input.addEventListener("blur", (e) => {
  if (!e.target.value) {
    e.target.classList.add("error");
  }
});

Dynamic List

addBtn.addEventListener("click", () => {
  const li = document.createElement("li");
  li.textContent = input.value;
  list.appendChild(li);
});

Remove on Click

item.addEventListener("click", (e) => {
  e.target.remove();
});

Where to Put Your Script? ๐Ÿ“

Timing is Everything!

โŒ Problem: Script in Head

<head>
  <script src="script.js"></script>
</head>

DOM doesn't exist yet!

โœ… Solution 1: End of Body

<body>
  <!-- All your HTML -->
  <script src="script.js"></script>
</body>

DOM exists, safe to manipulate!

โœ… Solution 2: DOMContentLoaded

document.addEventListener("DOMContentLoaded", () => {
  // Your code here - DOM is ready!
});

Project: Etch-a-Sketch ๐ŸŽจ

Apply Everything You've Learned!

What You'll Build:

  • ๐Ÿ–ผ๏ธ A grid of divs (like graph paper)
  • ๐Ÿ–ฑ๏ธ Hover effects that "draw" on the grid
  • ๐Ÿ”ข User input to change grid size
  • ๐ŸŽจ Color changes on interaction

Skills Used: createElement, appendChild, addEventListener, event objects, loops, and DOM manipulation!

Project Requirements ๐Ÿ“‹

โœ… Grid Generation

Create a 16ร—16 grid of square divs using JavaScript

โœ… Hover Effect

Change square color when mouse hovers over it

โœ… Reset Button

Clear the grid and prompt for new size

โœ… Size Validation

Limit grid size to maximum 100ร—100

Pro Tip: Use flexbox for the grid layout and keep total pixel size constant!

Getting Started ๐Ÿš€

Break It Down into Steps

Development Steps:

  1. Setup: Create HTML structure with container div
  2. Grid Function: Write function to create 16ร—16 grid
  3. Style Grid: Use flexbox to arrange squares
  4. Hover Effect: Add mouseover event listener
  5. Button: Add reset button with click handler
  6. User Input: Use prompt() for new grid size
  7. Bonus: Add color options, progressive darkening

Concepts to Use ๐Ÿ”‘

Creating Elements

const square = document.createElement("div");
square.classList.add("grid-square");
container.appendChild(square);

Adding Events

square.addEventListener("mouseover", () => {
  square.style.backgroundColor = "black";
});

Creating Multiple Squares

function createGrid(size) {
  for (let i = 0; i < size * size; i++) {
    const square = document.createElement("div");
    // Add event listener and styling
    container.appendChild(square);
  }
}

Flexbox Grid Layout ๐Ÿ“

.container {
  display: flex;
  flex-wrap: wrap;
  width: 960px;
  height: 960px;
}

.grid-square {
  /* If 16ร—16 grid, each square is 960/16 = 60px */
  width: calc(100% / 16);
  height: calc(100% / 16);
  border: 1px solid #ccc;
  box-sizing: border-box;
}
Use box-sizing: border-box;

Bonus Challenges ๐Ÿ†

Level Up Your Project!

๐ŸŒˆ Random Colors

const randomColor = () => {
  const r = Math.floor(Math.random() * 256);
  const g = Math.floor(Math.random() * 256);
  const b = Math.floor(Math.random() * 256);
  return `rgb(${r}, ${g}, ${b})`;
};

๐ŸŒ‘ Progressive Darkening

Each pass makes square 10% darker

Use opacity or RGB calculations

๐ŸŽจ Color Picker

Let user choose the drawing color

๐Ÿงน Clear Button

Reset all squares to white

You Now Know DOM Manipulation! ๐ŸŽ“

Today's Superpowers:

  • โœ… Navigate the DOM tree structure
  • โœ… Select elements with querySelector
  • โœ… Create new elements dynamically
  • โœ… Modify element properties and styles
  • โœ… Add interactive event listeners
  • โœ… Handle multiple elements efficiently
  • โœ… Understand event bubbling
  • โœ… Connect historical innovations to modern practices

Practice Resources:

  • ๐Ÿ“– MDN DOM Documentation
  • ๐ŸŽฎ JavaScript30 by Wes Bos
  • ๐Ÿ’ช Complete the Etch-a-Sketch project

Remember: From OXO in 1952 to Engelbart's 1968 demo to your Etch-a-Sketch today - you're part of computing history! ๐Ÿš€