# DOM manipulation
The Document Object Model (DOM) represents the document (the web page) as a tree of nodes (or objects or elements)
With JavaScript, you can modify (add/remove/change) the entire DOM
node types | description |
---|---|
window | represents the browser window |
document | represents the entire document (the root node of the DOM tree) |
element node | represents an element (an HTML tag) |
attribute node | the attribute of an element |
text node | the text inside an element |
comment node | comments inside an element |
REMARK
The Elements tab inside Chrome's DevTools shows the (modified) DOM (after execution of the scripts), which can differ a lot from the original HTML code (CTRL
+ U
)
For example for stubru.be (opens new window), both the original HTML code (only scripts!) and the DOM code are very different ...
# Select elements
Before you can modify the DOM, we first have to select an element on the page The four most commonly used selection methods are:
selector | description |
---|---|
document.body (opens new window) | select the body element |
document.getElementById(<id>) (opens new window) | select the element whose id equals <id> |
document.querySelectorAll(<CSS selector>) (opens new window) | select ALL elements matching <CSS selector> |
document.querySelector(<CSS selector>) (opens new window) | select THE FIRST element matching <CSS selector> |
Open the developer console on this page and use REPL (Read-Eval-Print-Loop) to select some elements
document.body
document.getElementById('app')
document.querySelector('img')
document.querySelector('img[alt=DOM]')
document.querySelectorAll('h2')
# Loop over NodeList
document.getElementById()
and document.querySelector()
always return one element. On the other hand, document.querySelectorAll()
always returns a NodeList, even if there is only one item selected.
A NodeList can be iterated as an array.
In this example:
- select all buttons
- loop, with the
forEach()
(opens new window) method, over the NodeList ofbuttons
The first parameter of the callback function insideforEach()
represents the element (the button), the second (optional) parameter is theindex
inside the loop - outputs the information about every button to the console
See the Pen FSLoopNodeList by Jitse Beyens (@BeyensJ) on CodePen.
# Modify content
property | description |
---|---|
document.createElement('<element>') (opens new window) | create a new element node that you can modify and display |
<element>.append(<element>, ...) (opens new window) | append specific element(s) to another element |
<element>.textContent (opens new window) | get or set ALL text inside the <element> (including spaces and hidden text) |
<element>.innerText (opens new window) | get or set only the VISIBLE text inside the <element> (including spaces but without hidden text) |
<element>.innerHTML (opens new window) | get or set the HTML content inside <element> |
See the Pen FSModifyElements by Jitse Beyens (@jitse-beyens) on CodePen.
# Modify attributes
Every HTML element can have some (default) attributes: e.g. src
, title
, href
, ...
method | description |
---|---|
<element>.getAttribute(<attribute>) (opens new window) | get the <attribute> of the <element> |
<element>.setAttribute(<attribute>, <value>) (opens new window) | set the <attribute> of the <element> to <value> |
<element>.<attribute> | shorthand to get/set the <attribute> of the <element> |
<element>.hasAttribute(<attribute>) (opens new window) | check if the <attribute> exists on the <element> :returns true or false |
<element>.removeAttribute(<attribute>) (opens new window) | remove the <attribute> on the <element> |
<element>.attributes | get all the attributes on the <element> |
See the Pen FSModifyAttributes by Jitse Beyens (@jitse-beyens) on CodePen.
WARNING
Always use <element>.value
to get/set the value
of an input/form element
<element>.getAttribute('value')
returns the initial value of the element's value
attribute (even if/after the input element is changed by the user!)
<element>.setAttribute('value', ...)
(only) changes the (initial) value
attribute of the element (and not the current value of the element)
# The data-* attribute
data-*
attributes are a very handy way to add valid, custom attributes to an element (and thus, to store custom data with an element)
The attribute name should not contain any uppercase letters, and must be at least one character long after the data-
prefix
Examples: data-id
, data-photographer
, data-unsplash-url
, ...
data-*
attributes are available via the dataset
property:
property | example | description |
---|---|---|
<element>.dataset.* (opens new window) | get or set the data-* attribute of the <element> | |
<element>.dataset.photographer | use only the suffix after data- ( data-abc <=> <element>.dataset.abc ) | |
<element>.dataset.unsplashUrl | if the suffix contains (a) hypen(s), write the suffix in camelCase ( data-abc--opq-xyz <=> <element>.dataset.abcOpqXyz |
See the Pen FSDataAttribute by Jitse Beyens (@BeyensJ) on CodePen.
# Modify classes
property | description |
---|---|
<element>.className (opens new window) | get or replace all the classes on the <element> |
<element>.classList (opens new window) | get all the classes on the <element> |
<element>.classList.add(<c1>, ...) | add class(es) to the <element> |
<element>.classList.remove(<c1>, ...) | remove class(es) from the <element> |
<element>.classList.replace(<c1>, <c2>) | replace class <c1> by <c2> on the <element> |
<element>.classList.toggle(<c>) | toggle the class <c> on the <element> :- add the class if it doesn't exist - remove the class if it exists |
<element>.classList.contains(<c>) | check if the class <c> exists on the <element> :returns true or false |
See the Pen FSModifyClasses by Jitse Beyens (@BeyensJ) on CodePen.