Week 1

Introduction to HTML

Semantic HTML

Forms

Accessibility (a11y)

DOM Manipulation

DevTools Basics

Practice

Assignment

Back to Track

What is the DOM?

The DOM (Document Object Model) is a programming interface for HTML documents. When a browser loads a web page, it creates a tree-like representation of the HTML that JavaScript can interact with. This lets you make pages dynamic and interactive.

<!-- HTML -->
<div id="container">
  <h1>Hello</h1>
  <p>Welcome</p>
</div>
DOM Tree:
div#container
  ├─ h1
  │   └─ "Hello"
  └─ p
      └─ "Welcome"

Every HTML element becomes a "node" in this tree that JavaScript can find, modify, create, or remove. This is how websites respond to clicks, update content without reloading, and create interactive experiences.

img_htmltree_800.png

Visual representation of the DOM

<aside> 💡

Info

The browser parses your HTML and creates the DOM automatically. When you use JavaScript to change the DOM, the browser immediately updates what you see on the page - no refresh needed.

</aside>

https://www.youtube.com/watch?v=NO5kUNxGIu0

How It Works

<button id="myButton">Click me</button>

<script>
  // 1. Find the button in the DOM
  const button = document.querySelector('#myButton');
  
  // 2. Add interactivity
  button.addEventListener('click', function() {
    button.textContent = 'Clicked!';
  });
</script>

When you click the button, JavaScript modifies the DOM, and the browser updates the display instantly.

<aside> ⌨️

Hands On

Open DevTools Console on any webpage and type: document.querySelector('h1').textContent = 'I changed this!' - watch the heading change instantly. This is DOM manipulation in action.

</aside>

Selecting Elements

Before you can manipulate elements, you need to find them in the DOM.

querySelector() - Select One Element

Returns the first element that matches the selector:

// By ID
const header = document.querySelector('#main-header');

// By class
const button = document.querySelector('.btn');

// By element type
const paragraph = document.querySelector('p');

// By complex selector
const firstLink = document.querySelector('nav a');

// If no match found, returns null
const missing = document.querySelector('.nonexistent'); // null

querySelectorAll() - Select Multiple Elements

Returns a NodeList (like an array) of all matching elements:

// All paragraphs
const paragraphs = document.querySelectorAll('p');

// All elements with class "card"
const cards = document.querySelectorAll('.card');

// All links inside nav
const navLinks = document.querySelectorAll('nav a');

// Loop through results
paragraphs.forEach(function(p) {
  console.log(p.textContent);
});

getElementById() - Select by ID

Older method, still commonly used. Only works with IDs:

const container = document.getElementById('container');
// Same as: document.querySelector('#container')

<aside> 💡

Info

querySelector() is more flexible because it accepts any (CSS) selector. Use querySelector() for single elements and querySelectorAll() for multiple elements.

</aside>

Common patterns

// Select first button
const btn = document.querySelector('button');

// Select all list items
const items = document.querySelectorAll('li');

// Select element by ID
const output = document.querySelector('#output');

// Select nested elements
const firstCardTitle = document.querySelector('.card h2');

<aside> ⌨️

Hands On

Create an HTML file with 3 paragraphs, each with class "text". Use querySelectorAll('.text') to select them all and log each one's text content in the console.

</aside>

Modifying Content

Once you've selected elements, you can change their content and appearance.

textContent - Change Text

Updates the text inside an element:

const heading = document.querySelector('h1');

// Read current text
console.log(heading.textContent); // "Original Heading"

// Change text
heading.textContent = 'New Heading';

innerHTML - Change HTML Content

Updates the HTML inside an element:

const container = document.querySelector('#container');

// Read current HTML
console.log(container.innerHTML); // "<p>Hello</p>"

// Change HTML
container.innerHTML = '<h2>New Title</h2><p>New paragraph</p>';

<aside> ⚠️

Warning

Never use innerHTML with user input - it can execute malicious scripts. Always use textContent for user-provided content. Use innerHTML only when you control the HTML content yourself.

</aside>

Creating and Removing Elements

You can dynamically add or remove elements from the page.

Creating Elements

// 1. Create new element
const newParagraph = document.createElement('p');

// 2. Set its content
newParagraph.textContent = 'This is a new paragraph';

// 3. Add classes or styles
newParagraph.classList.add('intro');

// 4. Append to the page
const container = document.querySelector('#container');
container.appendChild(newParagraph);

Removing Elements

const element = document.querySelector('.remove-me');

// Remove the element
element.remove();

// Old way (still works)
element.parentElement.removeChild(element);

<aside> 💡

Info

element.remove() is modern and simple. parentElement.removeChild(element) is the older method but still widely supported. Both do the same thing.

</aside>

Event Listeners

Event listeners make your page respond to user actions.

addEventListener()

Attach functions that run when events occur:

// Syntax
element.addEventListener('eventType', function() {
  // Code to run when event happens
});

// Example
const button = document.querySelector('#myButton');

button.addEventListener('click', function() {
  console.log('Button was clicked!');
});

Common Events

Mouse events:

// Click
element.addEventListener('click', function() { });

// Double click
element.addEventListener('dblclick', function() { });

// Mouse enter/leave (for hover effects)
element.addEventListener('mouseenter', function() { });
element.addEventListener('mouseleave', function() { });

Keyboard events:

// Any key pressed
document.addEventListener('keydown', function(event) {
  console.log('Key pressed:', event.key);
});

// Specific key
document.addEventListener('keydown', function(event) {
  if (event.key === 'Enter') {
    console.log('Enter was pressed!');
  }
});

Form events:

const form = document.querySelector('form');

// Form submitted
form.addEventListener('submit', function(event) {
  event.preventDefault(); // Prevent page reload
  console.log('Form submitted!');
});

const input = document.querySelector('input');

// Input value changed
input.addEventListener('input', function() {
  console.log('Current value:', input.value);
});

Form handling:

const form = document.querySelector('#contact-form');
const message = document.querySelector('#message');

form.addEventListener('submit', function(event) {
  event.preventDefault();
  
  // Get form values
  const name = document.querySelector('#name').value;
  const email = document.querySelector('#email').value;
  
  // Display message
  message.textContent = `Thanks, ${name}! We'll contact you at ${email}`;
  
  // Clear form
  form.reset();
});

Event Object

Event listeners receive an event object with information:

button.addEventListener('click', function(event) {
  console.log('Clicked element:', event.target);
  console.log('Click position:', event.clientX, event.clientY);
});

input.addEventListener('input', function(event) {
  console.log('Current value:', event.target.value);
});

Preventing Default Behavior

Stop default browser actions, for example a form submission. When a form is submitted, the default action is to perform a POST request. However, you might want to perform a different action or let JavaScript handle the form.

// Prevent form submission reload
form.addEventListener('submit', function(event) {
  event.preventDefault();
  // Handle form with JavaScript instead
});

// Prevent link navigation
link.addEventListener('click', function(event) {
  event.preventDefault();
  // Do something else instead
});

<aside> 😄

</aside>

Best Practices

1. Select elements once, reuse the reference

// Less efficient - queries DOM every click
button.addEventListener('click', function() {
  document.querySelector('#output').textContent = 'Clicked';
});

// Better - query once
const output = document.querySelector('#output');
button.addEventListener('click', function() {
  output.textContent = 'Clicked';
});

2. Use textContent for user input

// Unsafe
element.innerHTML = userInput;

// Safe
element.textContent = userInput;

3. Prefer classList over style

// Less maintainable
element.style.backgroundColor = 'red';
element.style.padding = '20px';

// Better
element.classList.add('error');

4. Check if elements exist

const element = document.querySelector('.might-not-exist');

if (element) {
  element.textContent = 'Found it!';
}