Skip to content

Latest commit

 

History

History
388 lines (281 loc) · 13.9 KB

dom-manipulation.md

File metadata and controls

388 lines (281 loc) · 13.9 KB

DOM manipulation

Learning objectives

  • What is the DOM?
  • Why do we need it?
  • How do we use it?
    • How to select elements from the DOM using selectors
    • How to manipulate elements using .textContent and .classList
    • How to add event listeners
    • how to trigger and respond to events
      • event.preventDefault()
    • Recipes for creating/adding/removing HTML elements using javascript

Code along template

https://github.com/thoughtworks-jumpstart/dom-manipulation

What is the DOM

Example DOM Tree

The Document Object Model (DOM) is an in-memory representation of HTML documents. It represents the web page as a javascript object (document) so that javascript programs can traverse and modify the document structure, style, and content.

Imagine an HTML page with the following structure:

<html>
<head>
    <title>Some title</title>
</head>
<body>
    <p>First paragraph</p>
    <p>Second paragraph</p>
</body>
</html>

The browser exposes a JavaScript interface to query and manipulate this HTML using a global variable called document. Using plain JS objects and arrays, the DOM can be thought to resemble a structure similar to the following:

document = {
    querySelector() { ... },
    querySelectorAll() { ... },
    createElement() { ... },
    children: [
        {
            tagName: 'HTML',
            textContent: '...',
            children: [
                {
                    tagName: 'head',
                    children: [ ... ],
                },
                {
                    tagName: 'body',
                    children: [
                        {
                            tagName: 'p',
                            textContent: 'First paragraph',
                        },
                        {
                            tagName: 'p',
                            textContent: 'Second paragraph',
                        },
                    ]
                }
            ]
        }
    ]
};

Note that this is a model of the DOM, but not how the DOM is actually implemented in the browser.

We can also try to visualize the DOM tree of a given HTML document using this tool.

As you can see, there are different types of nodes in a DOM tree:

  • Element Nodes
  • Text Nodes

DOM manipulation with JavaScript

In this session, we are going to learn how to manipulate a DOM object using the API it offers.

To start with, let's have a glance with the APIs we need to be familiar with:

Some of the APIs may return multiple nodes as NodeList. It's an array-like object that you can iterate through and get the nodes one-by-one.

This may sound boring now, but basically all interactive webpages that you've visited (e.g. Stripe Connect, pac-man, Fancy Checkout ) are possible because the DOM interface lets us manipulate the contents of a webpage without refreshing a page!

How to select elements from the DOM using selectors

<div id="greeting">Hello World!</div>
let greetingDiv = document.getElementById("greeting");
console.log(greetingDiv);

Note: to refer to the current document object, you can use the global variable document.

Other element selectors:

// by class name
// (Note: methods which say getElements... (instead of getElement...) return an array)
document.getElementsByClassName("some-class");

// by HTML tag name (this returns an array)
document.getElementsByTagName("h1");

// by css query selector syntax
document.querySelector("li.my-specific-class");
document.querySelector("li#my-specific-id");

// selecting more than 1 element (this returns an array of all html elements meeting the criteria)
document.querySelectorAll("li");
document.querySelectorAll("li.my-specific-class");

How to change the content of one HTML element

You can change the content of the HTML element

greetingDiv.textContent = "Howdy world!";

How to change the style of one HTML element

You can change the style too!

greetingDiv.style.backgroundColor = "gold";
greetingDiv.style.fontFamily = "Helvetica Neue";
greetingDiv.style.fontSize = "30px";
greetingDiv.style.color = "white";

(Warning: .style is not supported in every browser. This example is for the purpose of illustrating what you can do. A better way to change the style would be via the .classList attribute)

How to update CSS attributes of one HTML element

We can access/update a html element's css class via the .classList attribute

(See MDN docs for a list of available methods)

.my-new-class {
  background-color: gold;
  font-family: "Helvetica Neue";
  font-size: 30px;
  color: white;
}
//list classes
greetingDiv.classList;

//add a class
greetingDiv.classList.add("my-new-class");

//remove a class
greetingDiv.classList.remove("my-new-class");

//check if greetingDiv has a class (returns true or false)
greetingDiv.classList.contains("my-new-class");

How to add html elements

The recipe for add a new element to the DOM is as follows:

  1. create a new element and save it to a variable
  2. modify any properties of the element
  3. attach the element to an existing element on the page

Example:

// step 1
let img = document.createElement("img");

// step 2
img.src = "https://media.giphy.com/media/9gISqB3tncMmY/giphy.gif";
img.width = "400";

// step 3
document.body.appendChild(img);

How to remove html elements

To remove an element from the DOM tree, you can call one of the two APIs:

Handle Events

When users interact with a website (such as moving the mouse around, clicking on a link, etc), some events are generated and can be handled with JavaScripts.

Here is a list of commonly used events:

  • click
  • dblclick
  • mouseover
  • mouseout
  • focus and blur (try this on a input box or a button)
  • keypress

MDN has a nice list of all DOM events that we can listen for.

Let's look at some examples on handling those events.

How to add event listeners

We can hook up custom javascript code (e.g. the lines of code that we've just written above to beautify a 'hello world' div), to DOM events (e.g. click, mouseover, mouseout, keydown, keyup, change).

We do this by adding an event listener to a DOM element (by calling .addEventListener('the-event-we-want', callbackFunction)) and specifying what we want to happen in a callback function

let greetingDiv = document.querySelector("div");
greetingDiv.addEventListener("click", function() {
  greetingDiv.textContent = "bye bye";

  greetingDiv.style.backgroundColor = "gold";
  greetingDiv.style.fontFamily = "Helvetica Neue";
  greetingDiv.style.fontSize = "3em";
  greetingDiv.style.color = "white";
});

Using the event object in our callback function

When we add an event listener, the callback function that comes after can take in an event objet as its first parameter. In the previous example we've left it out and essentially thrown it away because we didn't use it. In some cases, we do want to access the event object's methods or attributes. Here are some example use cases:

Now we can do the page-styler​ exercise.

event attributes

The event object contains several attributes which can be useful. For example:

  • event.screenX and event.screenY tells us the coordinates of the mouse when the event happened.
  • event.key - when listening for keyup or keydown event, we have an event.key attribute which tells us which key was pressed (e.g. Enter, Space, 'a', 's', 'd', up, down, left, right, etc).
  • event.target - is an object which represents the HTML element on which the event was triggered.

Example 1: using event's properties (e.g. screenX and screenY) (Note that event has been shortened to e)

let body = document.querySelector("body");
body.addEventListener("mouseover", function(event) {
  let rgbColor1 = Math.ceil((event.screenY / 200) * 256);
  let rgbColor2 = Math.ceil((event.screenX / 200) * 256);
  body.style.backgroundColor =
    "rgb(" + [rgbColor1, 100, rgbColor2].join(",") + ")";
  console.log(rgbColor1, rgbColor2);
});

// try hovering around your screen!

Example 2: how to (i) listen for keypress, (ii) execute conditional logic using specific keypress event.charCode value, and (iii) get value from input:

<!-- in your html file -->
<body>
...
  <input type="text" id='some-input'>
// in your javascript file
let inputDiv = document.getElementById("some-input");

inputDiv.addEventListener("keydown", event => {
  console.log(`Key "${event.key}" pressed  [event: keydown]`);
  console.log(event.target.value);
});

inputDiv.addEventListener("keyup", event => {
  console.log(`Key "${event.key}" released  [event: keyup]`);
  console.log(event.target.value);
});

event methods

On the event object, there are some useful methods as well. You will encounter the following two sometimes.

event.preventDefault() is a useful method to prevent the default action of the event. For example, when you click on a link, the default action opens a new page. When you submit a form, the default action refreshes the page. That can be irritating, and event.preventDefault() allows you to stop that so that you can define how you want to handle the event.

Example:

<!-- in your html file -->

<a href="http://www.google.com">google</a>
// in your javascript file
let linkElement = document.querySelector("a");
linkElement.addEventListener("click", function(event) {
  event.preventDefault(); // this prevents the default behaviour of clicking a link (i.e. go to link URL)
  console.log(event); // let's see what exactly is an event object
});

The usage of event.stopPropagation is related to a concept called Event Bubbling and Capture. You can also find some discussion on the concept here

How to make sure some JavaScript codes are only executed after the HTML document is fully loaded

HTML and javascript are both loaded sequentially. If your javascript runs to completion before the HTML elements are fully loaded, all of your event listeners and event handlers will not be hooked up. There are 2 ways to make sure this doesn't happen:

  1. Wrap all of your javascript code as a callback for a DOMContentLoaded event
document.addEventListener('DOMContentLoaded', function() {
  // place your DOM manipulation code here
}
  1. Place your javascript code at the bottom of your html body
<html>
<head>
<!-- ... -->
</head>
<body>
<!-- all your html code -->
<script src="./my-javascript-code.js"></script>  // place your DOM manipulation javascript code here
</body>
</html>

Labs

Assignment

https://github.com/thoughtworks-jumpstart/dom-todo-list

Resources

Tutorials on DOM

Tutorials on Events

References