Web Programming
Lecture 4

DOM manipulation with JavaScript

Josue Obregon

Seoul National University of Science and Technology
Information Technology Management
Lecture slides index

April 14, 2025

Course structure

Roadmaps: Frontend, backend and fullstack

Agenda

  • JavaScript
    • Event-driven programming
    • DOM manipualtion

Separation of concerns

  • Separation of Concerns: a concept from Software Engineering that every part of a program should address a separate “concern”.
  • In web programming, we define those concerns as:
    • Content (words, images)
    • Structure/Meaning (HTML)
    • Style/Appearance (CSS)
    • Behavior
  • What happens if we don’t separate them?
  • How do we improve this?

JavaScript/HTML Connection

  • In general, to add interactivity to our HTML/CSS websites we need to:
    • Link a JavaScript program to our HTML
    • Identify the elements we want to interact with (e.g., <img>, <button, page)
    • Identify the events to respond to (e.g., click, hover, input)
    • Define the response functions that handle the desired behavior
    • Assign event listeners to the elements

Linking to a JS file: <script>

<!--template-->
<script src="filename"></script>

<!--example-->
<script src="example.js"></script>
  • The <script> tag should be placed in the HTML page’s <head>. All JS code used in the page should be stored in a separate .js file
  • JS code can be placed directly in the HTML file’s body or head (like CSS), but this is poor code quality. You should always separate content, presentation, and behavior by keeping these “concerns” in separate files!!

Event-driven programming

  • Unlike Java programs, JS programs have no main; they respond to user actions called events
  • Event-Driven Programming: writing programs driven by user events

Event handling

  • We can use JavaScript to attach functions to elements when an event (e.g. “click”) occurs.
  • To do so, we need to:
    1. Identify the source element to listen for an event
    2. Indicate the event to trigger a response
    3. Specify the response function(s) to call when the event is triggered.
  • Once we have this information, we can use addEventListener to hook everything up!

Identify Source Element

Select the DOM elements to which we will attach event listeners.

DOM tree

<html>
<head>
  <title>My Fancy Title</title>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="styles.css">
  <script src="script.js"></script>
</head>
<body>
  <header>...</header>
  <nav>...</nav>
  <article>
    <section>
      <p>Hello world: <a href="...">here</a></p>
      <p>Welcome!</p>
      <img src="...">
      <a href="...">citation</a>
    </section>
  </article>
  <footer>
    <a href="..."></a>
  </footer>
</body>
</html>
  • Selectors (class ., id # or type )

Document interface

  • The Document1 interface represents any web page loaded in the browser and serves as an entry point into the web page’s content, which is the DOM tree
  • We can access and manipulate the DOM through the Document instance of an HTML page
    • document is the actual object for your html page loaded in browser. This is a DOM object.
    • DOMContentLoaded event fires when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.
      • The window load event is also used for this, it fires when the resources have successfully loaded.
    • getElementById, querySelector and querySelectorAll instance mehtods are used to access elements on the DOM

Accessing an element by id

let name = document.getElementById("id");
  • document.getElementById() returns the DOM object for an element with a given id (note that you omit the # when giving an id)
  • If the id does not exist, there is no error. Instead the returned result is null

Accessing a single node using querySelector

let name = document.querySelector(selector)
  • document.querySelector() returns only the first element that would be matched by the given CSS selector string
  • If no element matches the passed selector, there is no error. Instead the returned result is null

Accessing a collection of nodes using querySelectorAll

let name = document.querySelectorAll(selector)
  • document.querySelectorAll() returns all elements that would be matched by the given CSS selector string
  • If no element matches the passed selector, there is no error. Instead an empty array is returned.

Handy shortcut functions

  • It’s handy to declare a shortcut to help us out as we will use these methods A LOT.
  • You may use the following in your JS programs (these are exceptions to the rule of having descriptive function names):
function id(id) {
  return document.getElementById(id);
}

function qs(selector) {
  return document.querySelector(selector);
}

function qsa(selector) {
  return document.querySelectorAll(selector);
}

Identify the events to respond to

Determine the specific user or page events (e.g., click, hover, input) that should trigger a response.

Common types of JavaScript events

Event Description
load Webpage has finished loading the document
scroll User has scrolled up or down the page
click A pointing device (e.g., mouse) has been pressed and released on an element
dblclick A pointing device button is clicked twice on the same element
keydown Any key is pressed
keyup Any key is released

You can find a full list here

Assign event listeners to the elements

Attach handling functions to the selected elements so that they are triggered when the corresponding events occur

Listening & Responding to Events

// attaching a named function
element.addEventListener("click", handleFunction);

function handleFunction(e) {
// event handler code
// parameter e is optional and captures
// more information about the event
}
// attaching an anonymous function
element.addEventListener("click", function (e) {
  // event handler code  
  });

// attaching an arrow function
element.addEventListener("click", (e) => {
  // event handler code  
});
  • JS functions can be set as event handlers (also known as “callbacks”1)
    • A callback is just a function that’s passed into another function, with the expectation that the callback will be called at the appropriate time
  • When you interact with the element and trigger the event, the callback function will execute
  • click is just one of many event types we’ll use

Event handler function syntax

What’s the difference between Statement 1 and Statment 2?

Statement 1

element.addEventListener("click", openBox);

Statement 2

element.addEventListener("click", openBox());

Event handler function syntax

What’s the difference between Statement 1 and Statment 2?

Statement 1

element.addEventListener("click", openBox);

Statement 2

element.addEventListener("click", openBox());

addEventListener with multiple events

myBtn.addEventListener("click", logClick);
myBtn.addEventListener("click", handleClick);
myBtn.addEventListener("mouseover", handleMouseOver);
  • We can add multiple eventListeners to the same element.
    • Multiple eventListeners for the same event but with different callback functions
    • Multiple eventListeners each for different events

removeEventListener after adding one

myBtn.addEventListener("click", function1);
myBtn.addEventListener("click", function2);

myBtn.removeEventListener("click", function1);
  • After adding an eventListener we can remove it so that the behavior associated with the event is no longer triggered.
  • You cannot remove anonymous functions, since you dont have a name to refer to them
  • Calling removeEventListener() with arguments that do not identify any currently registered event listener on the EventTarget has no effect.

Define the response functions

Create functions that handle the desired behavior when an event occurs, usually manipulating the DOM

What’s inside a DOM Node?

<img src="images/duck.png" alt="A useful rubber duck photo">
<p>picture taken from google</p> 
  • For starters, the HTML attributes. This HTML above is a DOM object
  • Let’s assume a variable for the tag called myImg is properly defined) with these two properties:
    • myImg.src – set by the browser to images/duck.png
    • myImg.alt – set by the browser to “A useful rubber duck photo”
  • Let’s assume a variable for the <p> tag called para is properly defined) with this property
    • para.textContent – set by the browser to “picture taken from google”

Manipulating DOM elements

  • Most JS code manipulates elements on an HTML page
  • We can examine elements’ state
    • e.g. see whether a box is checked
  • We can change the state of elements
    • e.g. insert some new text into a div
  • We can change the style of an element
    • e.g. make a paragraph red

Listening to load events

  • You can only access document element after the window “load” event has fired
  • You can also access the DOM after the document DOMContentLoaded evet has fired
    • without waiting for stylesheets, images, and subframes to finish loading
window.addEventListener("load", init);
//or
document.addEventListener("DOMContentLoaded", init);

// no access to the document here

function init() {
  // we now have access to the DOM tree!
  // set up your initial document event handlers here.
}

Modifying DOM elements

  • We can modify HTML element properties and style

DOM Element

<p id="text">
  This is the original text.
</p>

JS

document.getElementById("text").textContent = "Text has been changed!";

document.querySelector("#text").style.backgroundColor = "lightblue";

Creating DOM elements

  • For creating a new DOM element, we use the document.createElement("tag") function which creates and returns a new empty DOM node representing an element of that type
// create a new <h2> node
let newHeading = document.createElement("h2");
newHeading.textContent = "This is a new heading!";

Important

  • Merely creating an element does not add it to the page
  • You must add the new element as a child of an existing element on the page.

Adding and Moving Nodes on the DOM

  • When you have a parent DOM node, you can add or remove a child DOM node using the following functions:
Name Description
parent.appendChild(node) Places the given node at the end of this node’s child list
parent.insertBefore(new, old) Places the given node in this node’s child list just before the old child
parent.replaceChild(new, old) Replaces the given child with new nodes
parent.insertAdjacentElement(location, new) Inserts a new element at the specif

Example

let li = document.createElement("li");
li.textContent = "A list item!";
id("my-list").appendChild(li);

Removing DOM elements

  • When you have a parent DOM node, you can remove a child DOM node using the following functions:
Name Description
parent.removeChild(node) Removes the given node from this node’s child list
node.remove() Removes the node from the page

Example

document.querySelector(".list-element").remove();
/* or */
let li = document.querySelector(".list-element");
li.parentElement.removeChild(li);

Hiding/Showing DOM elements

How can we hide an HTML element?

#my-img {
  display: none;
}

In JS, it’s possible to modify the style properties of an element directly

document.getElementById("my-img").style.display = "none";

The <button>

<button id="my-btn">Go!</button>
  • Text inside of the button tag renders as the button text

  • To make a responsive button (or other UI controls):

    1. Choose the control (e.g., button) and event (e.g., mouse click) of interest
    2. Write a JS function to run when the event occurs
    3. Attach the function to the event on the control

Open the Box

  • In this example code, we modify an image by pressing a button.

HTML

<img id="mystery-box" src="question-block.png" alt="A Mystery Box">
<button id="box-btn">Click me!</button>

JS

let boxBtn = document.getElementById("box-btn");
boxBtn.addEventListener("click", openBox);

function openBox() {
  let box = document.getElementById("mystery-box"); // 1. Get the box image
  box.src = "star.png"; // 2. Change the box image's src attribute!
}

Next week

Asynchronous JavaScript, JSON and APIs

Acknowledgements


Back to title slide Back to lecture slides index