Week 9: Interacting with Web Pages - The DOM

Learn how JavaScript breathes life into HTML documents using the Document Object Model.

Explore Chapter 9

Chapter 9: Making Web Pages Dynamic with the DOM

What is the Document Object Model (DOM)?

When a web browser loads an HTML document, it creates a model of that page in memory. This model is called the Document Object Model (DOM). The DOM represents the page structure as a tree of objects, where each object corresponds to an HTML element, attribute, or piece of text.

Think of the DOM as a live, programmable representation of your HTML. JavaScript can access and manipulate this DOM tree to:

  • Change the content of HTML elements (e.g., update text, add images).
  • Modify the attributes of HTML elements (e.g., change an image's src or a link's href).
  • Alter the CSS styles of elements (e.g., change colors, sizes, visibility).
  • Add or remove HTML elements and attributes.
  • React to user events (like clicks, mouse movements, key presses).

Essentially, the DOM is the bridge that connects JavaScript to the visual structure and content of a web page, allowing for dynamic updates without needing to reload the entire page.

The browser provides a global document object, which is the entry point for interacting with the DOM.

// The 'document' object represents the entire HTML document
console.log(document);
console.log(document.body); // Access the <body> element object

Selecting HTML Elements.

Before you can manipulate an element, you need to select it or get a reference to its corresponding object in the DOM. JavaScript provides several methods via the document object for this:

  • getElementById(id): Selects the single element that has the specified id attribute. IDs must be unique within a page. Returns the element object or null if not found.
    <p id="intro">This is the introduction.</p>
    
    <script>
      let introParagraph = document.getElementById("intro");
      console.log(introParagraph); // Logs the <p> element object
    </script>
  • getElementsByTagName(tagName): Selects all elements with the specified tag name (e.g., 'p', 'div', 'li'). Returns an HTMLCollection (a live, array-like list) of the found elements.
    // Get all paragraph elements on the page
    let allParagraphs = document.getElementsByTagName("p");
    console.log(allParagraphs); // HTMLCollection of <p> elements
    console.log(allParagraphs.length); // Number of paragraphs
    console.log(allParagraphs[0]); // Access the first paragraph
    
  • getElementsByClassName(className): Selects all elements that have the specified CSS class name. Returns an HTMLCollection.
    <div class="highlight">Item 1</div>
    <span class="highlight">Item 2</span>
    
    <script>
      let highlightedItems = document.getElementsByClassName("highlight");
      console.log(highlightedItems); // HTMLCollection
    </script>
    
  • querySelector(cssSelector): Selects the *first* element that matches the specified CSS selector (e.g., #myId, .myClass, p, div > span). Returns the element object or null. Very versatile.
    let firstHighlight = document.querySelector(".highlight"); // Selects the first element with class="highlight"
    let intro = document.querySelector("#intro"); // Selects the element with id="intro"
    let firstListItem = document.querySelector("ul > li"); // Selects the first <li> inside a <ul>
    console.log(firstHighlight);
    
  • querySelectorAll(cssSelector): Selects *all* elements that match the specified CSS selector. Returns a static NodeList (array-like list).
    let allHighlights = document.querySelectorAll(".highlight"); // Selects all elements with class="highlight"
    console.log(allHighlights); // NodeList
    allHighlights.forEach(item => { // Can iterate with forEach
        console.log(item);
    });
    

querySelector and querySelectorAll are often preferred in modern JavaScript due to their flexibility with CSS selectors.

Manipulating Element Content and Style.

Once you have selected an element object, you can change its content, attributes, and appearance.

Changing Content:

  • textContent: Gets or sets the text content of an element and all its descendants, ignoring any HTML tags within. It's often safer for setting plain text.
    // Assuming: <p id="myPara">Initial <em>text</em></p>
    let para = document.getElementById("myPara");
    console.log(para.textContent); // "Initial text" (ignores <em>)
    para.textContent = "New text content set via JS.";
    // Now HTML is: <p id="myPara">New text content set via JS.</p>
    
  • innerHTML: Gets or sets the HTML content (including tags) within an element. Use with caution when setting content from untrusted sources, as it can introduce security risks (Cross-Site Scripting - XSS).
    // Assuming: <div id="myDiv"></div>
    let div = document.getElementById("myDiv");
    div.innerHTML = "<strong>Bold text</strong> and a <a href='#'>link</a>.";
    // The div now contains the actual bold text and link elements.
    

Changing Attributes:

  • You can often access common attributes directly as properties of the element object (e.g., id, className, src, href).
  • Use getAttribute(name) and setAttribute(name, value) for any attribute.
<img id="myImage" src="old.jpg" alt="Old Image">
<a id="myLink" href="/old-page">Old Link</a>

<script>
  let img = document.getElementById("myImage");
  let link = document.getElementById("myLink");

  // Using direct properties
  img.src = "new.png";
  img.alt = "New Image";
  link.href = "/new-page";

  // Using setAttribute
  link.setAttribute("target", "_blank"); // Add target="_blank" attribute
</script>

Changing CSS Styles:

You can modify inline CSS styles using the style property of the element object. CSS property names are converted to camelCase (e.g., background-color becomes backgroundColor).

// Assuming: <p id="styledPara">Style me!</p>
let styledP = document.getElementById("styledPara");

styledP.style.color = "blue";
styledP.style.backgroundColor = "#f0f0f0"; // Note camelCase
styledP.style.fontSize = "20px";
styledP.style.padding = "10px";

For more complex styling changes, it's usually better to add or remove CSS classes using the classList property (element.classList.add('newClass'), element.classList.remove('oldClass'), element.classList.toggle('activeClass')).

Basic Event Handling.

Events are actions that happen in the browser, such as a user clicking a button, moving the mouse, or pressing a key. JavaScript allows you to "listen" for these events and execute code (an event handler or listener function) when they occur.

Common Events:

  • click: User clicks an element.
  • mouseover / mouseout: Mouse pointer moves onto / off an element.
  • keydown / keyup: User presses / releases a key.
  • submit: A form is submitted.
  • load: An asset (like an image or the whole page) finishes loading.

Ways to Attach Event Handlers:

  1. Inline HTML Attributes (Older method, generally discouraged):
    <button onclick="alert('Button clicked!')">Click Me (Inline)</button>
  2. DOM Element Properties: Assign a function to the element's on property (e.g., onclick, onmouseover). Only one handler per event type can be assigned this way.
    <button id="btnProp">Click Me (Property)</button>
    
    <script>
      let buttonProp = document.getElementById("btnProp");
      buttonProp.onclick = function() { // Assign a function to the onclick property
        console.log("Button property handler executed!");
      };
      // Assigning again would overwrite the previous handler:
      // buttonProp.onclick = function() { console.log("Overwritten!"); };
    </script>
  3. addEventListener() (Modern, recommended): Attaches an event listener function to an element. Allows multiple listeners for the same event type.
    <button id="btnAdd">Click Me (addEventListener)</button>
    
    <script>
      let buttonAdd = document.getElementById("btnAdd");
    
      function handleClick() {
        alert("addEventListener handler executed!");
      }
    
      // Attach the listener
      buttonAdd.addEventListener('click', handleClick);
    
      // Can add another listener for the same event
      buttonAdd.addEventListener('click', function() {
         console.log('Another click listener ran!');
      });
    
      // To remove: buttonAdd.removeEventListener('click', handleClick);
    </script>

Event handling is key to creating interactive and responsive web pages. We've only scratched the surface here.

Syllabus