Lecture 10

Input Validation and classList Manipulation

Agenda

  • Administrivia
    • Reminder: CP 2 due today (git add/commit/push then turn in!)
    • Sign up for the CP showcase! (CP1 showcase coming soon)
    • Start HW 2 early!
  • Final thoughts on DOM manipulation
  • Input validation
  • Manipulating classLists

DOM tree

Skittles example

Think about the DOM tree structure of this page.

What would you draw this like?

How would you examine the elements of this page?

How would you add elements to the page?

How would you remove elements from the page?

Examining objects

Set a breakpoint in the initialize() function and refresh the page.

Stopping skittles at breakpoint

Then toggle the this: window object open to discover its contents

Showing window object opened

Traversing and Manipulating the DOM

We already know how to get an element of the DOM using document.getElementById(), document.querySelector() and document.querySelectorAll()

We also know we can add things to the tree using appendChild(node) on a DOM element.

The DOM also has

  • properties and methods for traversing the tree
  • methods for removing nodes from the tree

Review: Creating New Nodes

Name Description
document.createElement("tag") creates and returns a new empty DOM node representing an element of that type
document.createTextNode("text") creates and returns a text node containing given text
// create a new <h2> node
let newHeading = document.createElement("h2");
// Add text to the node method 1
let newText = document.createTextNode("This is a new heading!")
newHeading.appendChild(newText);
// Add text to the node method 2
newHeading.innerText = "This is a newer heading!";
document.appendChild(newHeading);

JS

Traversing the DOM Tree Manually

Every node's DOM object has the following (read-only) properties:

Name(s) Description
firstChild, lastChild start/end of this node's list of children, may include text or comments
firstElementChild, lastElementChild start/end of this node's list of children elements
childNodes array of all of this node's children
nextSibling, previousSibling neighboring nodes with the same parent, including whitespace nodes
nextElementSibling, previousElementSibling neighboring element nodes with the same parent, skipping whitespace nodes
parentNode, the element that contains this node

Complete list of DOM node properties

Browser incompatibility information (IE6 sucks)

DOM Tree Traversal Example

<p id="foo">
  This is a paragraph of text with a
  <a href="page.html">link</a>.
</p>

HTML

Element vs. Text Nodes

<div>
  <p id="foo">
    This is a paragraph of text with a
    <a href="page.html">link</a>.
  </p>
</div>

HTML

Q: How many children does the div have? A: 3

  • an element node representing the <p>
  • two text nodes representing "\n\t" (before/after the paragraph)

Q: How many children does the paragraph have? A: 3 (text, a, text)

Q: The a tag? A: 1 (text)

More modifying the DOM Tree

let p = document.createElement("p");
p.innerText = "A result!";
document.getElementById("the-place").appendChild(p);

JS

Every DOM element object has these methods:

Name Description
parentNode.appendChild(node) places the given node at end of this node's child list
parentNode.insertBefore(new, old) places the given node in this node's child list just before old child
parentNode.removeChild(node) removes the given node from this node's child list
node.remove() removes the node from the page
parentNode.replaceChild(new, old) replaces given child with new nodes

Removing DOM elements... a decision

What happens if we don't remove the skittles when we start a new game?

adding too many skittles 1 adding too many skittles 2 adding too many skittles 3

Two methods for removing elements

Method 1: get all of the DOM elements and remove them from the DOM

function clearJar() {
  let skittles = qsa(".skittle");
  for (let i = 0; i < skittles.length; i++) {
    skittles[i].remove();
  }
}

JS

Or ... Method 2: Set the Jar's innerHTML to be empty!

function clearJar() {
  $("jar").innerHTML = "";
}

JS

Note: in general innerHTML hacking is bad

Why not just code this way?

document.getElementById("add").innerHTML =  "<p>A result!</p>";

JS

Bad code quality (maintainability) on many levels

  • Not modular: HTML code embedded within JS
  • What if you have a complicated new node (with many subchildren) to add?
  • Error-prone: must carefully distinguish " and '
  • Can only add at beginning or end, not in middle of child list
// Substitutes all children
$("add").innerHTML =  "<p>A result!</p>";
// adds a node to the front of the list of children.
$("add").innerHTML  = "<p>A result!</p>" + $("result").innerHTML;
// adds a node to the end of the list of children
$("add").innerHTML += "<p>A result!</p>";

JS

One more: removing elements via the parent node

Let's add code to get rid of a skittle when we double click it...

What is the source element? A skittle (div)

What is the event we want to respond to? dblclick

What is the response? removeSkittle

What is the output/elements changed? the parent of the skittle (the jar)

//code added to addSkittle()
skittle.addEventListener("dblclick", removeSkittle);
...
// new function added (with JSDoc not seen here)
function removeSkittle() {
  this.parentNode.removeChild(this);
}

JS

Yes, you can also use remove(this); instead of removing from the parent node.

Input Validation

A user interface is like a joke. If you have to explain it, it’s not that good.

Martin LeBlanc

Example

Can I, as a user, do anything "wrong" here?

UI buttons aren't error prone

But what about the guesses text box?

UI buttons aren't error prone

Solution 1: Add instructions (the user will likely not read)

Solution 2: Prevent the user from doing something they shouldn't

HTML Input Validation

You can add attributes to your <input> tags to help with validation

The Skittles code already has a attribute that restricts the input to a number

<input type="number">

HTML

We can limit the up and down arrows with min (and max if we choose)

<input type="number" min=0>

HTML

To insist that there is a value in the input field we can add required

<input type="number" required>

HTML

To prevent a user from being able to type in erroneous values, we can add a regular expression to the required attribute

<input type="number" required="\d+">

HTML

Aside: What's a Regular Expression? (briefly)

A Regular Expression is way to specify a pattern to match.

We do not go into depth on Regular expressions in this class but they are fun to learn!

Handy resources include:

Now modify the CSS to display the error

input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}

CSS

Text box displaying error condition

What fields on this site warrant what types of validation?

Other Input Validation

Other HTML5 input types that can prevent a user from entering in erroneous input are listed here and include:

  • attributes on single line input fields
    • email
    • password
    • search
    • tel (for phone numbers)
    • url
  • other widgets
    • select/option (drop down list boxes, single or multiple choice)
    • checkbox
    • radio buttons
  • advanced widgets
    • number
    • range (slider)
    • datetime-local
    • month
    • week
    • time
    • color