The Document Object Model
The DOM, in short, is an in-memory object representing an HTML document. There is a good introduction in MDN.
What is DOM nodes
You can view a HTML tags as a nodes. But actually, it has different names on it:
Element
representsHTML tags
.Text nodes
represents text or white spaceComments
represents HTML comments.
So HTML
is an element, head
, body
is an element nodes, too.
Understand Node Properties
first, We use document
to represents entire HTML document. Everything is from here. It is an HTMLDocument
element inheriting from Node
properties | which node? | return what? | explain |
---|---|---|---|
nodeName | Element | uppercase, HTML tags | text node is #text |
nodeType | nodes | 1 is element, 3 is text | MDN |
nodeValue | Text | Element nodes don’t have a value | |
textContent | Element | all child nodes concatenated into a single String |
Types of Node
- All objects in DOM are Nodes
element
andtext nodes
are most commons
Different types are with different methods and properties. If you want to play with the DOM fluently. You have to remember this.
Some useful Elements:
- HTMLAnchorElement
- HTMLBodyElement
- HTMLButtonElement
- HTMLCanvasElement
- HTMLDivElement
- HTMLDocument
- HTMLFormElement
- HTMLHeadingElement
- HTMLHtmlElement
- HTMLImageElement
- HTMLInputElement
- HTMLLIElement
- HTMLLabelElement
Use instanceof
method or tagName
It is good if you want to find multiple elements. For example:
function findAllParagraphs() {
var matches = [];
document.body.childNodes.forEach(function(child) {
if (child instanceof HTMLParagraphElement) {
matches.push(child);
}
});
return matches;
}
findAllParagraphs();
Traversing Nodes
parent Node Properties | value |
---|---|
firstChild |
childNodes[0] or null |
lastChild |
childNodes[childNodes.length-1] or null |
childNodes |
Live collection of all child nodes |
child node properties | value |
---|---|
nextSibling | parent.childNodes[n+1] or null |
previousSibling | parent.childNodes[n-1] or null |
parentNode | immediate parent of this node |
Use recursive function to walk the dom
// the Douglas Crockford's way
function walkTheDOM(node, func) {
func(node);
node = node.firstChild;
while (node) {
walkTheDOM(node, func);
node = node.nextSibling;
}
}
you can take a look how Douglas Crockford’s explanation
// walk() calls the Function callback once for each node
function walk(node, callback) {
callback(node);
for (var i = 0; i < node.childNodes.length; i++) {
walk(node.childNodes[i], callback);
}
}
walk(document.body, function(node) {
console.log(node.nodeName);
});
Get/Set Attributes
Method | Description | Returns |
---|---|---|
getAttribute(name) | Retrieve value of attribute name | Value of attribute as String |
setAttribute(name, newValue) | Set value of attribute name to newValue | undefined |
hasAttribute(name) | Check whether element has attribute name | true or false |
use classList
to modify class attribute.
classList
is an array-like DOMTokenList
object:
Name | Description |
---|---|
add(name) | Add class name to element |
remove(name) | Remove class name from element |
toggle(name) | Add class name to element if it doesn’t exist, remove if it does exist. |
contains(name) | Return true or false depending on whether element has class name. |
length | The number of classes to which element belongs. |
use style
to set css properties.
for example, we can do this: h1.style.color = 'blue'
Finding DOM nodes
in document
, you can do with this, if there is an id attribute on an element.
document.getElementById(id)
: Element with specified id.
Method | Returns |
---|---|
document.getElementsByTagName(tagName) | HTMLCollection or NodeList of matching Elements |
document.getElementsByClassName(className) | HTMLCollection or NodeList matching Elements |
There is something you should be careful:
- it returns a collection, if your are sure to get only one object, please use like
collection[i]
to retrive. - if it is no select. it will return empty array-like
- use
for(var i = 0;i < collection.length; i += 1) {}
to iterate. This is not a realArray
. : - getElement*s*, there is an ‘s’.
use CSS selector
This works like in the css
file, when you select the element in the HTML. Think you are using css:
Method | Returns |
---|---|
document.querySelector(selector) | First matching Element or null |
document.querySelectorAll(selector) | NodeList of matching Elements |
It is Selector
, not Select
.
Traversing Elements
The DOM also provide some methods that let you retrive element
directly, ignoring other Nodes
like Text
.
Parent Element Properties | Value |
---|---|
firstElementChild | children[0] or null |
lastElementChild | children[children.length-1] or null |
children | Live collection of all child elements |
childElementCount | children.length |
Child Element Properties | Value |
---|---|
nextElementSibling | parentNode.children[n+1] or null |
previousElementSibling | parentNode.children[n-1] or null |
Create/Move DOM
It is good to find them all. But what if you want to create a nodes? or you want to remove them?
Create new Nodes
Node Creation Method | Returns |
---|---|
document.createElement(tagName) | A new Element node |
document.createTextNode(text) | A new Text node |
node.cloneNode(deepClone) | Returns a copy of node |
Add nodes to the exist DOM:
Parent Node Method | Description |
---|---|
parent.appendChild(node) | Append node to the end of parent.childNodes |
parent.insertBefore(node, targetNode) | Insert node into parent.childNodes before targetNode |
parent.replaceChild(node, targetNode) | Remove targetNode from parent.childNodes and insert node at its former position |
If you want to insert nodes to its neighbor?
Element Insertion Method | Description |
---|---|
element.insertAdjacentElement(position, newElement) | Inserts newElement at position relative to element |
element.insertAdjacentText(position, text) | Inserts Text node containing text at position relative to element |
Be aware that , you have to put a string with specific term in position
:
Position | Description |
---|---|
beforebegin | Before the element itself |
afterbegin | Just inside the element, before its first child |
beforeend | Just inside the element, after its last child |
afterend | After the element itself |
Remove them!
Good to add these Nodes
. How about removing them?
Element Method | Description |
---|---|
node.remove() | Removes node from the DOM |
parent.removeChild(node) | Remove node from parent.childNodes |
Let’s play with DOM
So you are with your weapons. You know how to find them, add/remove/change attribute, and you also know how to traversing the element; you also can find a specific nodes with class/id; even more, you can create and move the nodes!! With all these weapons. You know are able to play on any pages.
If we create a HTML just as the same DOM tree at the bigining, that’s play with this one:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>DOM Tree Example</title>
</head>
<body>
<h1>Lorem ipsum</h1>
<div>
<p id='first'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus efficitur in lectus ac sollicitudin. Aenean id fermentum ligula, sed volutpat ex. Sed leo tortor, dignissim ac tempor vitae, porta eleifend libero. Nam tristique vel nisi non dictum. Sed faucibus arcu nec magna ornare, porta laoreet nulla tristique. Maecenas id dapibus magna. Nulla ac ante nec eros pretium molestie. Fusce volutpat interdum massa, vitae tempor justo sollicitudin ut. Maecenas aliquam, diam et bibendum imperdiet, risus lacus facilisis purus, id dignissim ligula leo vel ipsum. Sed eget ornare quam. Etiam at justo id sem blandit aliquam. Mauris sed gravida velit. </p>
<p id='second'>Phasellus malesuada dolor eget orci placerat euismod. Vestibulum mattis libero eget luctus vehicula. Fusce feugiat sapien a euismod sodales. Donec pellentesque consectetur pulvinar. Aenean non lectus nec ex hendrerit varius. Nunc a mauris a turpis ornare tincidunt. Morbi convallis porta augue. Donec orci justo, porta id lobortis in, rutrum ut tellus. Quisque rhoncus tempor ipsum, id lobortis purus ultrices a. </p>
</div>
</body>
</html>
If you use the walk the dom
, you will get:
"BODY" //element
"#text" //text
"H1" //element
"#text"
"#text"
"DIV"
"#text"
"P"
"#text"
"#text"
"P"
"#text"
"#text"
If we want to add class='article'
in the paragraph with id = 'first'
. How to do with it?
var fisrt = document.getElementById('first');
first.setAttribute('class', 'article');
Then I want this paragraph’s color turn to blue?
first.style.color = 'blue';
Then, I want to change this paragraph with the short content with ‘hello world’?
first.textContent = 'hello world';
I also want add another div
after the div
that contains with the same content as first
?
var newDiv = document.createElement('div');
newDiv.appendChild(first.cloneNode(true));
var originDiv = first.parentElement;
originDiv.insertAdjacentElement('afterend', newDiv);
Good, But I want to know how many p
in this document?
// use walk
var count = 0;
walk(document, function(node) {
if (node.nodeName === "P") {
count++;
}
});
console.log(count); //3
Or we can use querySelectorAll
:
var paraList = document.querySelectorAll('p');
paraList.length; //3
Of course, you can remove them!
originDiv.removeChild(first);
If you play with them in your Chrome, now you have try to find them, walk through them, add more nodes, remove them. Besides, you also change there attributes.
Summary
This is some useful ways to manipulate DOMs. There are more way to use DOM in MDN documentation. But there are too many things there. If you want to quick get start with it. This is a short notes about how to use DOM methods.