JSJavaScript · Lesson 11 of 14

DOM & Events

The DOM is the browser API that lets JavaScript interact with HTML. It is a tree of nodes. You can read it, modify it, and listen for events on it. This is how every interactive web page works.

The Document Object Model represents the HTML structure as a tree of JavaScript objects. document.querySelector gives you the first matching element; document.querySelectorAll gives you a NodeList of all matches. Always wait for DOMContentLoaded before querying elements.

JavaScript
// Selecting elements
const btn   = document.querySelector("#submit-btn")       // by id
const items = document.querySelectorAll(".list-item")     // all matches
const first = document.querySelector("ul > li:first-child")

// Reading & writing content
const p = document.querySelector("p")
console.log(p.textContent)      // get text
p.textContent = "New text"       // set text (safe — no HTML injection)
p.innerHTML  = "<strong>Bold</strong>"  // set HTML (careful with user input!)

// Attributes
const img = document.querySelector("img")
console.log(img.getAttribute("src"))
img.setAttribute("alt", "A description")
img.removeAttribute("hidden")
console.log(img.id, img.className)     // direct property access for common attrs

// Styles and classes
const box = document.querySelector(".box")
box.style.backgroundColor = "red"     // camelCase for CSS properties
box.style.width = "200px"

box.classList.add("active")
box.classList.remove("hidden")
box.classList.toggle("open")           // add if missing, remove if present
box.classList.contains("active")       // true

// Creating and inserting elements
const li = document.createElement("li")
li.textContent = "New item"
li.classList.add("item")

const ul = document.querySelector("ul")
ul.appendChild(li)                     // add at end
ul.prepend(li)                         // add at start
ul.insertBefore(li, ul.children[2])   // insert at position

li.remove()   // remove element
JavaScript
// Events
const btn = document.querySelector("button")

// addEventListener (preferred over onclick attribute)
btn.addEventListener("click", (event) => {
  console.log("clicked!", event.target)
  event.preventDefault()   // prevent default browser action (form submit, link follow)
  event.stopPropagation()  // stop event bubbling up to parent elements
})

// Event delegation — one listener on parent handles all children
document.querySelector("ul").addEventListener("click", (e) => {
  if (e.target.matches("li")) {
    e.target.classList.toggle("done")
  }
})

// Common events
document.addEventListener("DOMContentLoaded", () => {
  // DOM is ready — safe to query elements
})

window.addEventListener("resize", () => {
  console.log(window.innerWidth, window.innerHeight)
})

// Form events
const form = document.querySelector("form")
form.addEventListener("submit", (e) => {
  e.preventDefault()
  const data = new FormData(form)
  console.log(data.get("username"))
})

const input = document.querySelector("input")
input.addEventListener("input", (e) => {
  console.log("current value:", e.target.value)
})

// Keyboard events
document.addEventListener("keydown", (e) => {
  if (e.key === "Escape") closeModal()
  if (e.ctrlKey && e.key === "s") { e.preventDefault(); save() }
})
◆ Note
Never use innerHTML with user-provided content — it executes scripts and enables XSS attacks. Use textContent for plain text, or create elements with createElement and textContent for safe HTML construction.