JavaScript:
Working with the DOM

HTML & CSS: Review

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>All About Cats</title>
  <style type="text/css">
   h1 {
     color: red;
   }
  #mainpicture {
    border: 1px solid black;
  }
  .catname {
    font-weight: bold;
  }
  </style>
 </head>
 <body>
  <h1>CATS!</h1>
  <img id="mainpicture" src="http://placekitten.com/200/300">
  <p>So cute!</p>
  <ul>
   <li class="catname">Lizzie</li>
   <li class="catname">Daemon</li>
  </ul>
 </body>
</html>

JavaScript in HTML

You can put JS inside a script tag (commonly at bottom of the page):

  <script>
    console.log('IM ON A WEBPAGE!');
  </script>
 </body>
</html>

You can also put JS in an external file and reference it:

  <script src="app.js"></script>
 </body>
</html>

The DOM Tree

For this page:

DOM Inspecting

  • Chrome: Right-click -> "Inspect Element"
  • Firefox: Right-click -> "Inspect Element" -> "HTML"


Don't make me cry: don't use Internet Explorer



Chrome Dev Tools

DOM Access

The document object gives us ways of accessing and changing the DOM of the current webpage.

General strategy for DOM manipulation:

  1. Find the DOM node using an access method and store it into a variable.
  2. Manipulate the DOM node by changing its attributes, styles, inner HTML, or appending new nodes to it.

DOM "nodes"

Every DOM "node" has properties that let us traverse the DOM like a tree: parentNode, childNodes, firstChild, prevSibling, nextSibling.

var bodyNode = document.body;
var htmlNode = document.body.parentNode;
for (var i = 0; i < document.body.childNodes.length; i++) {
  var childNode = document.body.childNodes[i];
}

DOM Access: by id

The method signature:

document.getElementById(id);

If the HTML had:

<img id="mainpicture" src="http://placekitten.com/200/300">

We'd access it this way:

var img = document.getElementById('mainpicture');

DOM Access: by tag name

The method signature:

document.getElementByTagName(tagName);

If the HTML had:

<li class="catname">Lizzie</li>
<li class="catname">Daemon</li>

We'd access it this way:

var listItems = document.getElementsByTagName('li');
for (var i =0; i < listItems.length; i++) {
  var listItem = listItems[i];
}

DOM Access: HTML5

The HTML5 spec includes a few even more convenient methods.

Available in IE9+, FF3.6+, Chrome 17+, Safari 5+:

document.getElementsByClassName(className);

var catNames = document.getElementsByClassName('catname');
for (var i =0; i < catNames.length; i++) {
  var catName = catNames[i];
}

DOM Access: HTML5

Available in IE8+, FF3.6+, Chrome 17+, Safari 5+:

document.querySelector(cssQuery);
document.querySelectorAll(cssQuery);

var catNames = document.querySelectorAll('ul li.catname');

DOM Nodes: Attributes

You can access and change attributes of DOM nodes using dot notation.

If we had this HTML:

<img id="mainpicture" src="http://placekitten.com/200/300">

We could change the src attribute this way:

var img = document.getElementById('mainpicture');
var oldSrc = img.src;
img.src = 'http://placekitten.com/100/500';

DOM Nodes: Attributes

Another way: or using getAttribute/setAttribute:

var oldSrc = img.getAttribute('src');
img.setAttribute('src', 'http://placekitten.com/100/500');

To set class, use the property className:

img.className = "picture";

DOM Nodes: Styles

You can change styles on DOM nodes via the style property.

If we had this CSS:

body {
  color: red;
}

We'd run this JS:

var pageNode = document.getElementsByTagName('body')[0];
pageNode.style.color = 'red';

DOM Nodes: Styles

CSS property names with a "-" must be camelCased and number properties must have a unit:

body {
  background-color: pink;
  padding-top: 10px;
}
pageNode.style.backgroundColor = 'pink';
pageNode.style.paddingTop = '10px';

DOM innerHTML

Each DOM node has an innerHTML property with the HTML of all its children:

var pageNode = document.getElementsByTagName('body')[0];

You can read out the HTML like this:

console.log(pageNode.innerHTML);

DOM innerHTML

You can set innerHTML yourself to change the contents of the node:

pageNode.innerHTML = "<h1>Oh Noes!</h1> <p>I just changed the whole page!</p>"

You can also just add to the innerHTML instead of replace:

pageNode.innerHTML += "...just adding this bit at the end of the page.";

DOM Modifying

The document object also provides ways to create nodes from scratch:

document.createElement(tagName);
document.createTextNode(text);
document.appendChild();

DOM Modifying

var pageNode = document.getElementsByTagName('body')[0];

var newImg = document.createElement('img');
newImg.src = 'http://placekitten.com/400/300';
newImg.style.border = '1px solid black';
pageNode.appendChild(newImg);

var newParagraph = document.createElement('p');
var paragraphText = document.createTextNode('Squee!');
newParagraph.appendChild(paragraphText);
pageNode.appendChild(newParagraph);

Exercise!

DOM

If you get stuck, raise your hand.

Getting help

Google for questions or check Stack Overflow. Also look on the Mozilla Developer Network.

Before you share your problematic code, post it to jsbin.com

Homework

tbd

If you get stuck between now and next class, put your code on JSBin.com and email it to your instructor.