The Document Object Model

CSCI-UA.0480-008

An HTML Document As Boxes

One way to visualize an HTML document is as a set of nested boxes.

Data Structures!

If you were tasked with writing a rendering engine for a browser, what kind of data structure would you use to represent an HTML document in your program?

(maybe you're planning on building your own in Swift or Rust)

  • a linked list?
  • a tree?
  • a hash map?
  • a combination of all of the above?
  • some custom object?


Let's look at another way of visualizing an HTML document

An HTML Document as a Tree

Another way to view an HTML document is as a tree:

  • nested structures, such as ones where each element can have similar sub-elements nested within themselves, can be modeled as a tree
  • all of the elements in a document can be thought of as nodes in a tree
  • for nested elements, the outer element is a parent, and the inner element is a child
  • see the tree diagram in our book

The Document Object Model

The DOM, or Document Object Model, is a standardized programming interface (an API) for representing and working / interacting with objects in HTML documents

  • it's language independent! (…it's not tied to JavaScript) and cross platform
  • the DOM is a fully object-oriented representation of a web page
  • it provides a structured representation of the document and defines the way that the document can be accessed programmatically
  • this access allow the reading and modification of a document's content, structure and even visual presentation
  • it's essentially the bridge between a web page and a programming language!

DOM Continued

Again, the DOM and the programming language are separate entities:

  • page content is stored in the DOM
  • which is manipulated by a programming language
  • the actual implemented DOM API of a web page is the DOM + the programming language


The DOM represents an HTML document as a group of nodes

  • these nodes are organized in a tree structure (as described in the previous slides)
  • each node is an object with properties and methods

JavaScript and the DOM

As a point of comparison… there were built-in global objects that were accessible and specific to JavaScript in Node - what were some built-in objects that we used?

  • console
  • global
  • the require function
  • …and others, like process, module, etc.


The JavaScript engine in your browser also has access to a bunch of built in objects - and those objects let us access the DOM!

Accessing the DOM

The DOM can be accessed by through a built-in global object called document.

document contains additional objects:

  • documentElement - the root of the tree; represents the HTML element (the tags that enclose the entire document)
  • body - the body element
  • head - the head element


Let's see what these objects look like.

Nodes and Node Types

Nodes can be categorized into types. What kind of node types do you think there are in an HTML document (let's check out the tree structure again)?


Notice that the type of a node is specified by a constant. For example…

  • document.ELEMENT_NODE
  • document.TEXT_NODE

Node Types Continued

All nodes have a nodeType property that specifies what kind of node it is.

  • the nodeType maps to the constants contained in the document object (see the previous slide)
  • note that text nodes exist for any text within an element (including white space!)
  • Let's see this in action…


Note that the objects we've seen so far, such as document, document.body, etc. are also nodes.

Consequently, they also have a nodeType property (compare with the constants

Node Name and Node Value

Another two properties of Nodes are:

  • nodeName - the name of the current node (read only)
  • nodeValue
    • for most node types, such as document, element, etc., nodeValue is null (see the docs)
    • for text, comment, and CDATA node types, nodeValue is the actual content of the node
  • let's check these out

Shortcomings

Speaking JavaScript mentions that there are some shortcoming with the way the DOM interface is designed. For example:

  • the childNodes property of a node is not actually an array (let's see… it has length, but what methods would we expect from an array?→)
    • (no slice())
    • (no forEach())
  • there are no facilities to immediately add children to a newly created node
    • rather, each child of a new node must be added one-by-one!

Some Solutions

Fortunately, JavaScript allows us to create abstractions that smooth over these design flaws. There are many libraries available that make manipulating the DOM a breeze (JQuery being the most popular).

  • with that said, we'll still be taking a look at the plain vanilla API that the DOM has to offer
  • in fact, there's a bit of a movement to limit the use of libraries and dependencies to only those that are essential why?
    • page download size increases with each dependency
    • sometimes libraries are too magical (maybe you don't know what it's actually doing under-the-hood)
  • check out youmightnotneedjquery.com for some examples


Of course, you can see that libraries, like JQuery, make things much easier for the programmer.

Moving Around

Some properties that you can use to move around the DOM are:

  • parentNode - the node containing the current node
  • childNodes - an array-like object containing all of the current node's children
    • has a length property
    • does not have typical Array methods, such as slice and forEach
  • firstChild - first child node
  • lastChild - last child node
  • previousSibling - the previous adjacent node
  • nextSibling - the next adjacent node


And… let's see what these look like.

An Exercise

Write a function called talksAbout. Test on this markup.

  • two parameters, a node to search in, and a string to look for
  • returns true if it finds the string anywhere within the node or the node's children
  • talksAbout(document.body, 'schedule'); // returns true if the word 'schedule' is in body
  • try a recursive solution
  • check the node's type by comparing to document.ELEMENT_NODE or document.TEXT_NODE
  • if it's an element node, you know it has children, so call function again on all of those children (return false if the search isn't successful in the child nodes)
  • if it's a text node, use indexOf to determine if the search string is a substring of the node's value (nodeValue)
  • remember that indexOf returns -1 if the substring is not found

A Potential Solution


function talksAbout(node, search) {
	if (node.nodeType === document.ELEMENT_NODE) {
		for (var i = 0; i < node.childNodes.length; i++) {
			if (talksAbout(node.childNodes[i], search)) {
				return true;
			}
		}
		return false
	} else if (node.nodeType === document.TEXT_NODE) {
		return node.nodeValue.indexOf(search) > -1 {
	}
}

A Note on Class vs ID

All HTML elements can have a class and an ID attribute.

  • generally IDs can occur only once in a document: id="foo"
  • however, there can be multiple elements with the same class: class="bar"
  • these are typically not enforced by the browser

Finding Elements

The following methods will give back an element or elements based on search criteria:

  • document.getElementById - returns node with specified id attribute
  • document.getElementsByClassName - returns nodes with specified class attribute (an HTML Collection)
    • also callable on elements (searches only within element called on)
  • document.getElementsByTagName - returns nodes with specified tag name (an HTML Collection)
    • also callable on elements (searches only within element called on)


Modifying Elements

Changing attributes


// we can change certain attributes simply by using assignment... for example, id, src, or href
document.getElementById('foo').id = 'bar';

Changing text node values


// assuming we have an element_node, and we know its first child is a text element
node.firstChild.nodeValue = 'new text'

Modifying Elements Continued

Assuming the following markup within a body tag, how would you change the href of the last link so that it takes you to an image search for cookies (using JavaScript)?


announcement
content

stuff 1

stuff 2

stuff 3 with a link

Um Cookies 🍪 🍪 🍪 🍪 🍪