Week 10

JavaScript in the

Browser

The Document Object Model (DOM) and Events

Document Object Model (DOM)

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:

  • Update text content (what is between <mytag></mytag>)
  • Create, remove and edit HTML elements
  • Add, remove and edit HTML attributes
  • Add CSS classes and inline styles

How do we transform the DOM?

STEP 1

Target

STEP 2

Transform

STEP 1

Target

Targets an HTML element on the page

document.querySelector()

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>

Common CSS Selectors

for JavaScript

button {

}

#myId {

}

[type="checkbox"] {

}
button {
  background-color: "#ccfcccc";
}

#myId {
  display: "none"; 
}

[type="checkbox"] {
  margin-right: 10px;
}

Common CSS Selectors

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

Targets more than one element on a page

document.querySelectorAll()

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

.forEach()

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

for ... of loop

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

Transform

Document Object Model (DOM)

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

HTML Attribute

From a file with HTML that is loaded to the screen.

Node Property

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)

Node Properties

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
}

Node Properties

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

element.textContent

<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

element.textContent

<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

element.style.styleProperty

<div id="alert" class="alert alert-warning alert-dismissible">
  <strong>Holy guacamole!</strong> Please close me.
  <button class="close">&times;</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

CSS Classes

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

document.querySelectorAll()

and .forEach()

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>
 * }
 */

Events

e.g. a button is clicked, a form is filled out, an option is selected from a list, the page finishes loading

Inputs and Other Form Elements

  • change
  • input
  • focus
  • blur

Links, Buttons, Checkboxes and Radio Buttons

  • click

Forms

  • submit

Window (the page as a whole)

  • load
  • resize
  • scroll
  • error

Keyboard

  • keydown

How do we handle events?

STEP 1

Target

STEP 2

React to an Event

STEP 3

Do something

Save

Event Handlers

code that reacts to events

Event handlers can take a callback, which can be either:

  1. a named function
  2. an anonymous function
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

element.removeEventListener()

<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

 

 

 

Forms

<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

Textboxes

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?
});

event.target.value

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

Textboxes

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

Selectboxes

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

Checkboxes

click or change

stopping undesired browser behavior

event.preventDefault()

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

Forms

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

 

 

 

Creating Elements

Creating Elements

Here are ways you can create elements on page:

  1. Using document.createElement()
  2. By turning a string into HTML elements
  3. A templating engine like Pug, Handlebars, Moustache, or EJS
  4. With a library or framework like React, Vue or Angular

document.createElement()

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.

https://codesandbox.io/s/vanilla-wo-build-q1sks?fontsize=14

element.innerHTML()

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;

element.insertAdjacentHTML()

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).

Cross-Site Scripting (XSS)

Attackers inject harmful code into into your application through elements like textboxes and other sources of user input

Week 10

By Jamal Taylor

Week 10

  • 245