Lesson 9 - DOM manipulation in JavaScript
In the previous lesson, Introduction to DOM and events in JavaScript, we started with the most used DOM method
- getElementById()
and we also talked about events. This JavaScript
tutorial will be more theoretical. We're going to learn what we can do with DOM,
and in the next lesson, we'll create a larger web application using the
knowledge we gained in this lesson.
Selecting elements
Before we can manipulate with elements, we must find them somehow. The
getElementById()
method is very efficient (and fast) but is not
always ideal. Sometimes we need to select multiple elements, and sometimes we
need to select elements which have no id
. We won't always select
elements from a document to which we have access so we can't ensure the presence
of id
s.
Selecting by class
We use the getElementsByClassName()
method to select elements by
their class. When writing it, keep in mind that the word "elements" is a plural,
and that every first letter of each word (except for the first word) is in upper
case. If you make a mistake, you'll cause an error (but you won't see it). The
method returns an array of all the elements that have a given class. If there is
no element with this class, the method returns an empty array. (More accurately,
the method returns an empty HTMLCollection
, which is a more
primitive array for storing HTML elements).
document.getElementsByClassName("class");
Selecting by tag
Every element has its tag (its markup). The
getElementsByTagName()
method returns all the elements that have a
given tag. In this way, we can select all paragraphs, for example. If no element
has such a tag, it returns an empty HTMLCollection
.
document.getElementsByTagName("tag");
There are also selection methods based on the tag and its namespace
(getElementsByTagNameNS()
). These will be appreciated especially by
XML fans. And we can search by the name
attribute
(getElementsByName()
), which we use to look for elements in forms
where the name
attribute is assigned. Both methods return an empty
HTMLCollection
if nothing meets the specified conditions.
document.getElementsByName("name"); document.getElementsByTagNameNS("tag", "NS");
Selecting by CSS selector
In HTML document, we can search even more comfortably using CSS selectors as
we are used to from webdesign. There are two methods to make this possible. The
querySelector()
method returns the first element that the selector
meets, and the querySelectorAll()
method returns an array of all
the elements for which the selector is valid. We'll show it straight on the
example.
document.querySelector("input[type=text].pretty#introduction");
This selector returns an <input>
element which
type
attribute is set to text
, which has the
.pretty
class and the #introduction
id
.
You may have noticed that if we search by id
, we could
theoretically use only the following selector (since id
s must be
unique).
document.querySelector("#introduction");
It's going to be a little more interesting with the
querySelectorAll()
method, which in many cases may be the only way
to select something.
document.querySelectorAll("div[data-countdown]");
The selector returns all the elements that have the
data-countdown
attribute assigned.
Since we're able to select any element in DOM, we can start editing them.
Editing DOM contents
innerHTML
First, let's look at the contents of elements. One of the most basic
properties of DOM elements is the innerHTML
property that carries
the element's contents. Consider the following element:
<p><span>Hello</span>world</p>
If we access its innerHTML
property:
p.innerHTML
it'll return <span>Hello</span>world
. We can change
the contents using the property as well. Just remember that the nested HTML tags
are processed.
innerText
Similarly as innerHTML
, there's also the innerText
property. The only difference is that innerText
doesn't contain
nested HTML elements, but only their text content. If we used the same content
as the example above, p.innerText
would return
Hello world
. The property was previously non-standard, but all
browsers support it today.
textContent
textContent
does almost the same as innerText
. The
difference between the properties is that innerText
returns only
visible text, while textContent
also returns text hidden through
CSS.
Now we already know how to read/change the contents of elements. Now let's look at their attributes.
Editing DOM attributes
Has attribute?
The basic question is whether an element has the attribute we're looking for
at all. We can determine this by the hasAttribute()
method, which
takes the name of the attribute as parameter and returns a boolean value.
There's also the hasAttributes()
method (plural), which returns
whether an element has any attributes. If there is none, it returns
false
, if there's at least one, it returns true
. The
method doesn't take any parameters. The method also has a namespace variant and
can return the attribute's Node
with the namespace optionally.
p.hasAttribute("data-size");
Element's children
An element may or may not have child elements. These are all the elements that are nested in it. Let's show a form as an example:
<form> <input type="text" /> <button>Submit</button> </form>
The <input>
and <button>
elements are
the child elements of the <form>
element. In other words, the
<input>
and <button>
elements are
descendants of the <form>
element.
Selecting child elements
The list of all the child elements of an element is in its
childNodes
property (it works as an array but it's represented by
the NodeList
collection).
firstChild
Child elements are, of course, sorted. It's from the oldest to the youngest
one depending on how long they're present in the parent element. Simply put,
they're in the order in which the browser read them (we know it's from top to
bottom). The firstChild
property contains the first one of
them.
lastChild
On the contrary, the lastChild
property contains the last child
element.
We should mention that the firstChild
and lastChild
properties do not necessarily contain only physical elements, but also HTML
comments, texts (typically <p>
elements has a child which
holds its text), and many other things we do not usually care about (we do care
about these nodes when parsing XML documents which we'll learn while working
with AJAX in advanced courses). To keep things simple, there are also the
firstElementChild
and lastElementChild
properties
which omit all the non-element nodes around (especially whitespaces can be nasty
) and return only HTML
elements.
Creating new elements
The createElement()
method creates a new element. The tag is
specified as string as the first parameter. The method returns a new element, we
can work with it straight away, but we must keep in mind that this element is
not in the document yet. We can create and attach other elements into it, but we
will not see them until we put the element somewhere in the document. There is
also a variant that creates an element and assigns a namespace to it -
createElementNS()
.
let span = document.createElement("span"); let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
Appending and moving elements
We append an element into another element using the
appendChild()
method. The method appends the new element after the
last child. If we pass an element which is already somewhere in the document,
the element will be moved from its original location.
p.appendChild(span);
Inserting before elements
Sometimes, appending an element as the new last child using the
appendChild()
method is not what we need. There is the
insertBefore()
method, which accepts a new element as the first
parameter and the child element before which it should be inserted/moved as the
second parameter.
document.body.insertBefore(span, p);
Replacing child elements
We can replace an element's child elements. It can be done using the
replaceChild()
method, which accepts a new child as the first
parameter and the original child as the second parameter.
svg.replaceChild(arc, rect);
Removing child elements
We can remove the element's child by the removeChild()
method,
which takes the child as its parameter:
p.removeChild(span);
The element's parent
Each element has its parent (the element to which it belongs). There's only
one element with no parent - the root <html>
element. We get
the parent of an element using the parentElement
property
(parentNode
also works but may contain non-element document nodes).
The method returns null
if called on the <html>
element. The <html>
element is sometimes omitted in documents
since it's not required.
Well, in the end, we've listed pretty much all the methods and properties (maybe I omitted some NS variants) which return another element/attribute/content by some way and we demonstrated how to modify contents and element attributes. To put it in mind, we'll try it all in the next lesson, Table editor in JavaScript. Finally, we'll create a real web application which would be hard to confuse with a website