The Document Object Model (DOM) and Events
HTML in JavaScript
The DOM is a programming interface for HTML (and XML) documents, where HTML elements are represented as a tree of nodes and objects.
<!DOCTYPE html>
<html>
<head>
<title>My title</title>
</head>
<body>
<h1>A heading</h1>
<a href="https://www.google.com/">Link text</a>
</body>
</html>Image source: https://en.wikipedia.org/wiki/File:DOM-model.svg
Examples of how we can transform the DOM in JavaScript:
How do we transform the DOM?
STEP 1
STEP 2
STEP 1
Targets an HTML element on the page
document.querySelector("CSS Selector Here");
This gets the first element on the page that matches a given CSS selector.
const heading = document.querySelector("h1");
console.log(heading); // <h1>My Heading</h1>for JavaScript
For more CSS selectors, see https://www.w3schools.com/cssref/css_selectors.asp
button {
}
#myId {
}
[type="checkbox"] {
}button {
background-color: "#ccfcccc";
}
#myId {
display: "none";
}
[type="checkbox"] {
margin-right: 10px;
}for JavaScript
#id
<button id="myId">Click Me!</button>
document.querySelector("#myId");elementType
<button">Click Me!</button>
document.querySelector("button");E.g. first button on the page
[attribute="value"]
<input type="checkbox">
document.querySelector('[type="checkbox"]');E.g. first checkbox on the page
For more CSS selectors, see https://www.w3schools.com/cssref/css_selectors.asp
Targets more than one element on a page
document.querySelectorAll("CSS Selector Here");
const links = document.querySelectorAll("a");
console.log(links);
/**
* {
* 0: <a href="/about.html">About</a>,
* 1: <a href="https://www.google.com/">Google</a>
* }
*/
This returns an object of HTML (NodeList).
Looping through a NodeList with
const links = document.querySelectorAll("a");
links.forEach((link) => {
console.log(link);
});
/**
* <a href="/about.html">About</a>
* <a href="https://www.google.com/">Google</a>
*/
Looping through a NodeList with a
const links = document.querySelectorAll("a");
for (const link of links) {
console.log(link);
}
/**
* <a href="/about.html">About</a>
* <a href="https://www.google.com/">Google</a>
*/STEP 2
HTML in JavaScript
The DOM is a programming interface for HTML (and XML) documents, where HTML elements are represented as a tree of nodes and objects.
How JavaScript represents HTML elements:
<button id="mybutton" type="button" class="btn btn-primary" style="background-color:#ccfcccc;">Click Me</button>
{
tagName: "BUTTON",
textContent: "Click Me",
id: "mybutton",
type: "button",
classList: { 0: "btn", 1: "btn-primary" },
style: {
backgroundColor: "#ccfcccc"
}
}HTML attributes
Node (JavaScript) properties
From a file with HTML that is loaded to the screen.
What is currently displayed on the screen as JavaScript interprets it.
Note that it does not update when changes occur. (e.g. user types in a textbox, a user checks a box, JavaScript changes something on the screen).
Note that an HTML attribute does not always map to a property (e.g. class, data-, aria- and the original value in href)
Get a property
const div = document.querySelector("#myDiv");
const id = div.id;Check to see if an element has a property
const input = document.querySelector('#myInput');
if (input.value) { // e.g. textbox
// do something
}Set or change a property
const image = document.querySelector("img");
image.src = "my-image.png";Remove a property
const button = document.querySelector("button");
button.disabled = undefined;<input type="password">
const input = document.querySelector("[type=password]");
console.log( input.type ); // password
input.type = "text";
HTML attribute
Node (JavaScript) property
E.g. changing a property
Reading text on a page
<button id="mybutton">Click Me</button>
const button = document.querySelector("#mybutton");
console.log( button.textContent );
// Read Me
HTML
JavaScript
Click Me
Writing or changing text on a page
<button id="mybutton">Next</button>
const button = document.querySelector("#mybutton");
button.textContent = "Loading ...";
HTML
JavaScript
Next
Loading ...
Before:
After:
Writing or changing an inline style
<div id="alert" class="alert alert-warning alert-dismissible">
<strong>Holy guacamole!</strong> Please close me.
<button class="close">×</button>
</div>const alert = document.querySelector("#alert");
alert.style.display = "none";
HTML
JavaScript
Note that you must write style properties in camel case
const alert = document.querySelector("#alert");
alert.style.backgroundColor = "#ccfcccc";
E.g. changing background color
Get all classes
const cssClasses = element.classList;Add a class
element.classList.add("new-class");Remove a
class
element.classList.remove("old-class");Check to see if an element has a class
if (element.classList.contains("my-class")) {
// do something
}Modify a group of elements with
const links = document.querySelectorAll("a");
links.forEach((link) => {
link.target = "_blank";
});
console.log(links);
/**
* {
* 0: <a href="/about.html" target="_blank">About</a>,
* 1: <a href="https://www.google.com/" target="_blank">Google</a>
* }
*/
e.g. a button is clicked, a form is filled out, an option is selected from a list, the page finishes loading
See more events: https://developer.mozilla.org/en-US/docs/Web/Events
Inputs and Other Form Elements
Links, Buttons, Checkboxes and Radio Buttons
Forms
Window (the page as a whole)
Keyboard
How do we handle events?
STEP 1
STEP 2
STEP 3
Save
code that reacts to events
Event handlers can take a callback, which can be either:
const myEventHandler = (event) => { /* Code Here */ }
element.addEventListener("eventType", myEventHandler);With a named function
element.addEventListener("eventType", (event) => {
// code reacts to event here
});With an anonymous function
// STEP 1 Target
const button = document.querySelector("#button");
const handleClick = () => {
};
// STEP 2 React to Event
button.addEventListener("click", handleClick);
const handleClick = () => {
// STEP 3 Do Something
console.log("You clicked me!");
};
// STEP 2 React to Event
button.addEventListener("click", handleClick);
A named function
Save
Removes an event
<button id="button">Click Me</button>const button = document.querySelector("#button");
const handleClick = () => {
console.log("You clicked me!");
};
button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);
HTML
JavaScript
How do we transform the DOM after an event?
callback
// STEP 1 Target
const button = document.querySelector('#button');
const handleClick = () => {
// STEP 3 Do something
// -- Target
const sendingNotification = document.querySelector('#sending');
// -- Transform
sendingNotification.style.display = 'block';
};
// STEP 2 React to Event
button.addEventListener('click', handleClick);E.g. display a notification after we click on a button
Send
Sending ...
// STEP 1 Target
const button = document.querySelector('#button');
const handleClick = () => {
// STEP 3 Do something
button.disabled = 'disabled';
button.textContent = 'Loading ...';
};
// STEP 2 React to Event
button.addEventListener('click', handleClick);E.g. transform the button that the user clicked
Send
Loading
// STEP 1: Target
const buttons = document.querySelectorAll("button");
buttons.forEach((button) => {
// STEP 2: React to an Event
button.addEventListener("click", () => {
// STEP 3: Do something
button.disabled = "disabled";
button.textContent = "Loading ...";
});
});
E.g. transform the button that the user clicked when there are multiple buttons with function scope
Send
Send
Loading
// STEP 1: Target
const alert = document.querySelector("#alert");
const dismissButton = document.querySelector("#alert button");
// STEP 3: Do something
const dismiss = () => {
// Hiding alert by using an inline display
alert.style.display = "none";
};
// STEP 2: React to an event
dismissButton.addEventListener("click", dismiss);
E.g. hidding content on the screen using inline styles
https://stackblitz.com/edit/stackblitz-starters-jrsax6?file=script.js
// STEP 1: Target
const productDescription = document.querySelector("#productDescription");
const showHideLink = document.querySelector("#showHideLink");
// STEP 2: React to an event
showHideLink.addEventListener("click", (e) => {
e.preventDefault(); // We will go over this later
// STEP 3: Do something
// The full product description is hidden because it has a CSS "hidden" class.
if (productDescription.classList.contains("hidden")) {
// This will show the full product description
productDescription.classList.remove("hidden");
} else {
// This will hide the full product description
productDescription.classList.add("hidden");
}
});
E.g. toggling content on the screen using CSS classes
↓ Scroll down
<input type="text" id="name">
// How can I read the input the user types into the textbox?
HTML
JavaScript
By using the event target's value
change or input
const name = document.querySelector("#name");
name.addEventListener("input", event => {
console.log("You typed something!")
// How can I read the input the user types into the textbox?
});
the text that the user enters into a textbox or other type of form element
<input type="text" id="name">const name = document.querySelector("#name");
name.addEventListener("input", event => {
console.log(event.target.value);
// This will log what the user is typing
});
HTML
JavaScript
change or input
<select id="department" class="form-control">
<option value=""></option>
<option value="web-design">Web Design</option>
<option value="web-development">Web Development</option>
<!-- ... -->
</select>
const name = document.querySelector("#name");
name.addEventListener("input", event => {
console.log(event.target.value);
// This will log what is inside "value" in the HTML above
});
HTML
JavaScript
change
<input type="checkbox" id="addExtraCheese">
<label or="addExtraCheese">Extra Cheese</label>
const addExtraCheese = document.querySelector("#addExtraCheese");
addExtraCheese.addEventListener("click", event => {
// This will return true or false, depending on if
// the checkbox is checked
console.log(event.target.checked);
});HTML
JavaScript
click or change
stopping undesired browser behavior
Common Use Case 1: Forms
Stops a form from being submitted, which will refresh the page or go to a new page
Common Use Case 2: Links
Stops a link from navigating to a new page
<form id="randomForm">
<!-- ... -->
</form>
const randomForm = document.querySelector("#randomForm");
randomForm.addEventListener("submit", event => {
event.preventDefault(); // Stops the page from refreshing
// Logs a message and all of the elements in the form
console.log("Form submitted! Elements are ", event.target.elements);
});HTML
JavaScript
submit
You can access the elements in a form with event.target.elements
<div id="communter" class="vehicle">Commuter ...</div>
<div id="commercial" class="vehicle">Commercial ...</div>
// Targeting all the things I need on the page
const options = document.querySelectorAll(".vehicle");
// Looping through each card that the user can click on
options.forEach((option) => {
// Reacts to when the user clicks on the card
option.addEventListener("click", () => {
// Gets the vehicle the user clicked on from the ID
const vehicle = option.id;
console.log(`You selected "${vehicle}".`);
});
});
HTML
JavaScript
E.g. knowing what element the user clicked on in a group using IDs
↓ Scroll down
<div data-vehicle="Communter">Commuter ...</div>
<div data-vehicle="Commercial">Commercial ...</div>
// Targeting all the things I need on the page
const options = document.querySelectorAll("[data-vehicle]");
// Looping through each card that the user can click on
options.forEach((option) => {
// Reacts to when the user clicks on the card
option.addEventListener("click", () => {
// Gets the vehicle the user clicked on from the data attribute
const vehicle = option.getAttribute("data-vehicle");
console.log(`You selected "${vehicle}".`);
});
});
HTML
JavaScript
E.g. knowing what element the user clicked on in a group using data attributes
↓ Scroll down
Let's say you are trying to create this:
<button>Click Me!</button>const button = document.createElement("button");
button.textContent = "Click Me!";
document.querySelector("body").appendChild(button);
Con
It is incredibly verbose. It can take so many lines of code.
create a new HTML element from a string
Let's say you are trying to create this:
<button>Click Me!</button>const buttonStr = "<button>Click Me!</button>";
parent.innerHTML += buttonStr;
create a new HTML element from a string
Let's say you are trying to create this:
<button>Click Me!</button>const buttonStr = "<button>Click Me!</button>";
parent.insertAdjacentHTML("beforeend", buttonStr);
Cons of innerHTML(), insertAdjacentHTML() and anything that creates a new element from a string:
- Are not as performant as document.createElement().
- Are vulnerable to Cross-site scripting (XSS).
Attackers inject harmful code into into your application through elements like textboxes and other sources of user input
To fight against XSS, sanitize user input with a third party library.
https://codesandbox.io/s/element-innerhtml-62muq?fontsize=14
https://codesandbox.io/s/elementinsertadjacenthtml-xyyhl?fontsize=14