[go: up one dir, main page]

0% found this document useful (0 votes)
5 views222 pages

3 Dom

This document provides an overview of the Document Object Model (DOM) in JavaScript, explaining its structure as a tree of nodes and the various node types. It also details methods for selecting elements in an HTML document, including getElementById(), getElementsByName(), getElementsByTagName(), and getElementsByClassName(), along with examples of their usage. The document emphasizes the importance of understanding node relationships and the properties associated with different node types.

Uploaded by

ROSHAN URKANDE
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views222 pages

3 Dom

This document provides an overview of the Document Object Model (DOM) in JavaScript, explaining its structure as a tree of nodes and the various node types. It also details methods for selecting elements in an HTML document, including getElementById(), getElementsByName(), getElementsByTagName(), and getElementsByClassName(), along with examples of their usage. The document emphasizes the importance of understanding node relationships and the properties associated with different node types.

Uploaded by

ROSHAN URKANDE
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 222

Section 1.

Getting started

Document Object Model


Summary: in this tutorial, you will learn about the Document Object Model in JavaScript.

What is Document Object Model (DOM)


The Document Object Model (DOM) is an application programming interface (API) for
manipulating HTML documents.

The DOM represents an HTML document as a tree of nodes. The DOM provides functions
that allow you to add, remove, and modify parts of the document effectively.

Note that the DOM is cross-platform and language-independent ways of manipulating HTML
and XML documents.

A document as a hierarchy of nodes


The DOM represents an HTML document as a hierarchy of nodes. Consider the following
HTML document:

<html>
<head>
<title>JavaScript DOM</title>
</head>
<body>
<p>Hello DOM!</p>
</body>
</html>

The following tree represents the above HTML document:


In this DOM tree, the document is the root node. The root node has one child node which is
the <html> element. The <html> element is called the document element.

Each document can have only one document element. In an HTML document,
the document element is the <html> element. Each markup can be represented by a node in
the tree.

Node Types
Each node in the DOM tree is identi ed by a node type. JavaScript uses integer numbers to
determine the node types. The following table illustrates the node type constants:

Constant Value Description


Node.ELEMENT_NODE 1 An Element node like <p> or <div>.
Node.TEXT_NODE 3 The actual Text inside an Element or Attr.
Node.CDATA_SECTION_NODE 4 A CDATASection, such as <!
CDATA[[ … ]]>.
Node.PROCESSING_INSTRUCT 7 A ProcessingInstruction of an XML
ION_NODE document, such as <?xml-stylesheet … ?
>.
Node.COMMENT_NODE 8 A Comment node, such as <!-- … -->.
Node.DOCUMENT_NODE 9 A Document node.
Node.DOCUMENT_TYPE_NODE 10 A DocumentType node, such as <!DOCTYPE
html>.
Node.DOCUMENT_FRAGMENT 11 A DocumentFragment node.
_NODE

To get the type of node, you use the nodeType property:

node.nodeType

You can compare the nodeType property with the above constants to determine the node
type. For example:

if (node.nodeType == Node.ELEMENT_NODE) {
// node is the element node
}
fi
The nodeName and nodeValue properties
A node has two important properties: nodeName and nodeValue that provide speci c
information about the node.

The values of these properties depend on the node type. For example, if the node type is the
element node, the nodeName is always the same as the element’s tag name
and nodeValue is always null.

For this reason, it’s better to test node type before using these properties:

if (node.nodeType == Node.ELEMENT_NODE) {
let name = node.nodeName; // tag name like <p>
}

Node and Element


Sometimes it’s easy to confuse between the Node and the Element.

A node is a generic name of any object in the DOM tree. It can be any built-in DOM element
such as the document. Or it can be any HTML tag speci ed in the HTML document
like <div> or <p>.

An element is a node with a speci c node type Node.ELEMENT_NODE, which is equal to 1.

In other words, the node is the generic type of element. The element is a speci c type of the
node with the node type Node.ELEMENT_NODE.

The following picture illustrates the relationship between the Node and Element types:
fi
fi
fi
fi
Note that the getElementById() and querySelector() returns an object with the Element type
while getElementsByTagName() or querySelectorAll() returns NodeList which is a collection of
nodes.

Node Relationships
Any node has relationships to other nodes in the DOM tree. The relationships are the same
as the ones described in a traditional family tree.

For example, <body> is a child node of the <html> node, and <html> is the parent of
the <body> node.

The <body> node is the sibling of the <head> node because they share the same immediate
parent, which is the <html> element.

The following picture illustrates the relationships between nodes:

Summary
• An HTML or XML document can be represented as a tree of nodes, like a traditional
family tree.
• Each markup can be represented as a node with a speci c node type.
• Element is a speci c type of node with the node type Node.ELEMENT_NODE.
• In the DOM tree, a node has relationships with other nodes.
fi
fi
Section 2. Selecting elements

getElementById
Summary: in this tutorial, you will learn how to use the JavaScript getElementById() to select
an element by a speci ed id.

Introduction to JavaScript getElementById() method


The document.getElementById() method returns an Element object that represents an HTML
element with an id that matches a speci ed string.

If the document has no element with the speci ed id, the document.getElementById() returns null.

Because the id of an element is unique within an HTML document,


the document.getElementById() is a quick way to access an element.

Unlike the querySelector() method, the getElementById() is only available on the document object,
not other elements.

The following shows the syntax of the getElementById() method:

const element = document.getElementById(id);

In this syntax, the id is a string that represents the id of the element to select. The id is case-
sensitive. For example, the 'root' and 'Root' are totally different.

The id is unique within an HTML document. However, HTML is a forgiving language. If the HTML
document has multiple elements with the same id, the document.getElementById() method returns
the rst element it encounters.

JavaScript getElementById() method example


Suppose you have the following HTML document:

<html>
<head>
<title>JavaScript getElementById() Method</title>
</head>
<body>
<p id="message">A paragraph</p>
</body>
</html>
fi
fi
fi
fi
The document contains a <p> element that has the id attribute with the value message:

const p = document.getElementById('message');
console.log(p);

Output:

<p id="message">A paragraph</p>

After selecting an element, you can add styles to the element, manipulate its attributes, and
traverse to parent and child elements.

Summary
• The document.getElementById() returns a DOM element speci ed by an id or null if no
matching element found.
• If multiple elements have the same id, even though it is invalid, the getElementById() returns
the rst element it encounters.
fi
fi
getElementsByName
Summary: in this tutorial, you will learn how to use the JavaScript getElementsByName() method to
get elements with a given name in a document.

Introduction to JavaScript getElementsByName() method


Every element on an HTML document may have a name attribute:

<input type="radio" name="language" value="JavaScript">

Unlike the id attribute, multiple HTML elements can share the same value of the name attribute like
this:

<input type="radio" name="language" value="JavaScript">


<input type="radio" name="language" value="TypeScript">

To get all elements with a speci ed name, you use the getElementsByName() method of
the document object:

let elements = document.getElementsByName(name);

The getElementsByName() accepts a name which is the value of the name attribute of
elements and returns a live NodeList of elements.

The return collection of elements is live. It means that the return elements are automatically
updated when elements with the same name are inserted and/or removed from the
document.

JavaScript getElementsByName() example


The following example shows a radio group that consists of radio buttons that have the same
name (rate).

When you select a radio button and click the submit button, the page will show the selected
value such as Very Poor, Poor, OK, Good, or Very Good:
fi
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>JavaScript getElementsByName Demo</title>
</head>

<body>
<p>Please rate the service:</p>
<p>
<label for="very-poor">
<input type="radio" name="rate" value="Very poor" id="very-poor"> Very poor
</label>
<label for="poor">
<input type="radio" name="rate" value="Poor" id="poor"> Poor
</label>
<label for="ok">
<input type="radio" name="rate" value="OK" id="ok"> OK
</label>
<label for="good">
<input type="radio" name="rate" value="Good"> Good
</label>
<label for="very-good">
<input type="radio" name="rate" value="Very Good" id="very-good"> Very Good
</label>
</p>
<p>
<button id="btnRate">Submit</button>
</p>
<p id="output"></p>
<script>
let btn = document.getElementById('btnRate');
let output = document.getElementById('output');

btn.addEventListener('click', () => {
let rates = document.getElementsByName('rate');
rates.forEach((rate) => {
if (rate.checked) {
output.innerText = `You selected: ${rate.value}`;
}
});

});
</script>
</body>

</html>
How it works:

• First, select the submit button by its id btnRate using the getElementById() method.
• Second, listen to the click event of the submit button.
• Third, get all the radio buttons using the getElementsByName() and show the selected
value in the output element.

Notice that you will learn about events like click later. For now, you just need to focus
on the getElementsByName() method.

Output:
Please rate the service:

Very poor Poor OK Good Very Good

Submit

You selected: OK

Summary
• The getElementsByName() returns a live NodeList of elements with a speci ed name.
• The NodeList is an array-like object, not an array object.
fi
getElementsByTagName
Summary: in this tutorial, you will learn how to use the JavaScript getElementsByTagName() to
select elements with a given tag name.

Introduction to JavaScript getElementsByTagName() method


The getElementsByTagName() is a method of the document object or a speci c DOM element.

The getElementsByTagName() method accepts a tag name and returns a live HTMLCollection of
elements with the matching tag name in the order which they appear in the document.

The following illustrates the syntax of the getElementsByTagName():

let elements = document.getElementsByTagName(tagName);

The return collection of the getElementsByTagName() is live, meaning that it is automatically


updated when elements with the matching tag name are added and/or removed from the
document.

Note that the HTMLCollection is an array-like object, like arguments object of a function.
fi
JavaScript getElementsByTagName() example
The following example illustrates how to use the getElementsByTagName() method to get the
number of H2 tags in the document.

When you click the Count H2 button, the page shows the number of H2 tags:

<! DOCTYPE html>


<html>
<head>
<title>JavaScript getElementsByTagName() Demo</title>
</head>
<body>
<h1>JavaScript getElementsByTagName() Demo</h1>
<h2>First heading</h2>
<p>This is the rst paragraph.</p>
<h2>Second heading</h2>
<p>This is the second paragraph.</p>
<h2>Third heading</h2>
<p>This is the third paragraph.</p>

<button id="btnCount">Count H2</button>

<script>
let btn = document.getElementById('btnCount');
btn.addEventListener('click', () => {
let headings = document.getElementsByTagName('h2');
alert(`The number of H2 tags: ${headings.length}`);
});
</script>
</body>

</html>
fi
Output

JavaScript getElementsByTagName() Demo


First heading
This is the rst paragraph.

Second heading
This is the second paragraph.

Third heading
This is the third paragraph.

Count H2

How it works:

• First, select the button Count H2 by using the getElementById() method.


• Second, hook the click event of the button to an anonymous function.
• Third, in the anonymous function, use the document.getElementsByTagName() to get a
list of H2 tags.
• Finally, show the number of H2 tags using the alert() function.
Summary
• The getElementsByTagName() is a method of the document or element object.
• The getElementsByTagName() accepts a tag name and returns a list of elements with
the matching tag name.
• The getElementsByTagName() returns a live HTMLCollection of elements.
The HTMLCollection is an array-like object.
fi
getElementsByClassName
Summary: in this tutorial, you will learn how to use the getElementsByClassName() method
to select elements by class name.

Introduction to the getElementsByClassName() method


The getElementsByClassName() method returns an array-like of objects of the child
elements with a speci ed class name. The getElementsByClassName() method is available
on the document element or any other elements.

When calling the method on the document element, it searches the entire document and
returns the child elements of the document:

let elements = document.getElementsByClassName(names);

However, when calling the method on a speci c element, it returns the descendants of that
speci c element with the given class name:

let elements = rootElement.getElementsByClassName(names);

The method returns the elements which is a live HTMLCollection of the matches elements.

The names parameter is a string that represents one or more class names to match; To use
multiple class names, you separate them by space.
fi
fi
fi
JavaScript getElementsByClassName() method examples
Let’s take some examples of using the getElementsByClassName() method.

Suppose that you have the following HTML document:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript getElementsByClassName</title>
</head>
<body>
<header>
<nav>
<ul id="menu">
<li class="item">HTML</li>
<li class="item">CSS</li>
<li class="item highlight">JavaScript</li>
<li class="item">TypeScript</li>
</ul>
</nav>
<h1>getElementsByClassName Demo</h1>
</header>
<section>
<article>
<h2 class="secondary">Example 1</h2>
</article>
<article>
<h2 class="secondary">Example 2</h2>
</article>
</section>
</body>
</html>

1) Calling JavaScript getElementsByClassName() on an element example


The following example illustrates how to use the getElementsByClassName() method to select
the <li> items which are the descendants of the <ul> element:

let menu = document.getElementById('menu');


let items = menu.getElementsByClassName('item');

let data = [].map.call(items, item => item.textContent);

console.log(data);
Output:

['HTML', 'CSS', 'JavaScript', 'TypeScript']

How it works:

• First, select the <ul> element with the class name menu using the getElementById() method.
• Then, select <li> elements, which are the descendants of the <ul> element, using
the getElementsByClassName() method.
• Finally, create an array of the text content of <li> elements by borrowing the map() method of
the Array object.

2) Calling JavaScript getElementsByClassName() on the document example


To search for the element with the class heading-secondary, you use the following code:

let elements = document.getElementsByClassName('secondary');


let data = [].map.call(elements, elem => elem.textContent);

console.log(data);

Output:

["Example 1", "Example 2"]

This example calls the getElementsByClassName() method on the document object.


Therefore, it searches for the elements with the class secondary in the entire document.

Summary
• Use the JavaScript getElementsByClassName() method to select the child elements of
an element that has one or more give class names.
querySelector
Summary: in this tutorial, you will learn how to use the JavaScript querySelector() and querySelectorAll() to
nd elements based on CSS selectors.

Introduction to JavaScript querySelector() and querySelectorAll() methods

The querySelector() is a method of the Element interface. The querySelector() method allows
you to select the rst element that matches one or more CSS selectors.
The following illustrates the syntax of the querySelector() method:

let element = parentNode.querySelector(selector);

In this syntax, the selector is a CSS selector or a group of CSS selectors to match the
descendant elements of the parentNode.
If the selector is not valid CSS syntax, the method will raise a SyntaxError exception.
If no element matches the CSS selectors, the querySelector() returns null.

The querySelector() method is available on the document object or any Element object.

Besides the querySelector(), you can use the querySelectorAll() method to select all
elements that match a CSS selector or a group of CSS selectors:
The querySelectorAll() method returns a static NodeList of elements that match the CSS

let elementList = parentNode.querySelectorAll(selector);

selector. If no element matches, it returns an empty NodeList.

Note that the NodeList is an array-like object, not an array object. However, in modern
web browsers, you can use the forEach() method or the for...of loop.

To convert the NodeList to an array, you use the Array.from() method like this:

let nodeList = document.querySelectorAll(selector);


let elements = Array.from(nodeList);
fi
fi
Basic selectors
Suppose that you have the following HTML document:

<!DOCTYPE html>
<html lang="en">
<head>
<title>querySelector() Demo</title>
</head>
<body>
<header>
<div id="logo">
<img src="img/logo.jpg" alt="Logo" id="logo">
</div>
<nav class="primary-nav">
<ul>
<li class="menu-item current"><a href="#home">Home</a></li>
<li class="menu-item"><a href="#services">Services</a></li>
<li class="menu-item"><a href="#about">About</a></li>
<li class="menu-item"><a href="#contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<h1>Welcome to the JS Dev Agency</h1>

<div class="container">
<section class="section-a">
<h2>UI/UX</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem placea</p>
<button>Read More</button>
</section>
<section class="section-b">
<h2>PWA Development</h2>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Magni fugiat .</p>
<button>Read More</button>
</section>
<section class="section-c">
<h2>Mobile App Dev</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi eos </p>
<button>Read More</button>
</section>
</div>
</main>
<script src="js/main.js"></script>
</body>
</html>
1) Universal selector
The universal selector is denoted by * that matches all elements of any type:

The following example uses the querySelector() selects the rst element in the document:

let element = document.querySelector('*');

And this select all elements in the document:

let elements = document.querySelectorAll('*');

2) Type selector
To select elements by node name, you use the type selector e.g., a selects all <a> elements:

elementName

The following example nds the rst h1 element in the document:

let rstHeading = document.querySelector('h1');

And the following example nds all h2 elements:

let heading2 = document.querySelectorAll('h2');

3) Class selector
To nd the element with a given CSS class, you use the class selector syntax:

.className

The following example nds the rst element with the menu-item class:

let note = document.querySelector('.menu-item');

And the following example nds all elements with the menu class:

let notes = document.querySelectorAll('.menu-item');


fi
fi
fi
fi
fi
fi
fi
fi
fi
4) ID Selector
To select an element based on the value of its id, you use the id selector syntax:

#id

The following example nds the rst element with the id #logo:

let logo = document.querySelector('#logo');

Since the id should be unique in the document, the querySelectorAll() is not relevant.

5) Attribute selector
To select all elements that have a given attribute, you use one of the following attribute
selector syntaxes:

[attribute]
[attribute=value]
[attribute~=value]
[attribute|=value]
[attribute^=value]
[attribute$=value]
[attribute*$*=value]

The following example nds the rst element with the attribute [autoplay] with any value:

let autoplay = document.querySelector('[autoplay]');

And the following example nds all elements that have [autoplay] attribute with any value:

let autoplays = document.querySelectorAll('[autoplay]');

Grouping selectors
To group multiple selectors, you use the following syntax:

selector, selector, ...

The selector list will match any element with one of the selectors in the group.
The following example nds all <div> and <p> elements:

let elements = document.querySelectorAll('div, p');


fi
fi
fi
fi
fi
fi
Combinators
1) descendant combinator
To nd descendants of a node, you use the space ( ) descendant combinator syntax:

selector selector

For example p a will match all <a> elements inside the p element:

let links = document.querySelector('p a');

2) Child combinator
The > child combinator nds all elements that are direct children of the rst element:

selector > selector

The following example nds all li elements that are directly inside a <ul> element:

let listItems = document.querySelectorAll('ul > li');

To select all li elements that are directly inside a <ul> element with the class nav:

let listItems = document.querySelectorAll('ul.nav > li');

3) General sibling combinator


The ~ combinator selects siblings that share the same parent:

selector ~ selector

For example, p ~ a will match all <a> elements that follow the p element, immediately or not:

let links = document.querySelectorAll('p ~ a');


fi
fi
fi
fi
4) Adjacent sibling combinator
The + adjacent sibling combinator selects adjacent siblings:

selector + selector

For example, h1 + a matches all elements that directly follow an h1:

let links = document.querySelectorAll('h1 + a');

And select the rst <a> that directly follows an h1:

let links = document.querySelector('h1 + a');

Pseudo
1) Pseudo-classes
The : pseudo matches elements based on their states:

element:state

For example, the li:nth-child(2) selects the second <li> element in a list:

let listItem = document.querySelectorAll('li:nth-child(2)');

2) Pseudo-elements
The :: represent entities that are not included in the document.
For example, p:: rst-line matches the rst line of all p elements:

let links = document.querySelector('p:: rst-line');

Summary
• The querySelector() nds the rst element that matches a CSS selector or a group of CSS selectors.
• The querySelectorAll() nds all elements that match a CSS selector or a group of CSS selectors.
• A CSS selector de nes elements to which a CSS rule applies.
fi
fi
fi
fi
fi
fi
fi
fi
Section 3. Traversing elements

Get the Parent Element of a Node


Summary: in this tutorial, you will learn how to get the parent node of an element by using
the JavaScript parentNode attribute of the Node object.

Introduction to parentNode attribute


To get the parent node of a speci ed node in the DOM tree, you use the parentNode property:

let parent = node.parentNode;

The parentNode is read-only.

The Document and DocumentFragment nodes do not have a parent. Therefore, the parentNode will
always be null.

If you create a new node but haven’t attached it to the DOM tree, the parentNode of that node will also
be null.

JavaScript parentNode example


See the following HTML document:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript parentNode</title>
</head>
<body>
<div id="main">
<p class="note">This is a note!</p>
</div>

<script>
let note = document.querySelector('.note');
console.log(note.parentNode);
</script>
</body>
</html>
fi
The following picture shows the output in the Console:

How it works:
• First, select the element with the .note class by using the querySelector() method.
• Second, nd the parent node of the element.

Summary
• The node.parentNode returns the read-only parent node of a speci ed node or null if it
does not exist.
• The document and DocumentFragment do not have a parent node.
fi
fi
Getting Child Elements of a Node
Summary: in this tutorial, you will learn how to get the rst child element, last child element,
and all children of a speci ed element.
Suppose that you have the following HTML fragment:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Get Child Elements</title>
</head>
<body>
<ul id="menu">
<li class=" rst">Home</li>
<li>Products</li>
<li class="current">Customer Support</li>
<li>Careers</li>
<li>Investors</li>
<li>News</li>
<li class="last">About Us</li>
</ul>
</body>
</html>

Get the rst child element


To get the rst child element of a speci ed element, you use the rstChild property of the element:

let rstChild = parentElement. rstChild;

If the parentElement does not have any child element, the rstChild returns null.
The rstChild property returns a child node which can be any node type such as an element node,
a text node, or a comment node. The following script shows the rst child of the #menu element:

let content = document.getElementById('menu');


let rstChild = content. rstChild.nodeName;
console.log( rstChild);

Output:

#text
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
The Console window show #text because a text node is inserted to maintain the whitespace
between the openning <ul> and <li> tags. This whitespace creates a #text node.
Note that any whitespace such as a single space, multiple spaces, returns, and tabs will
create a #text node. To remove the #text node, you can remove the whitespaces as follows:

<article id="content"><h2>Heading</h2><p>First paragraph</p></article>

Or to get the rst child with the Element node only, you can use the rstElementChild property:

let rstElementChild = parentElement. rstElementChild;

The following code returns the rst list item which is the rst child element of the menu:

let content = document.getElementById('menu');


console.log(content. rstElementChild);

Output:

<li class=" rst">Home</li>

In this example:
• First, select the #menu element by using the getElementById() method.
• Second, get the rst child element by using the rstElementChild property.

Get the last child element


To get the last child element of a node, you use the lastChild property:

let lastChild = parentElement.lastChild;

In case the parentElement does not have any child element, the lastChild returns null. Similar
to the the rstChild property, the lastChild property returns the rst element node, text node,
or comment node. If you want to select only the last child element with the element node
type, you use the lastElementChild property:

let lastChild = parentElement.lastElementChild;

The following code returns the list item which is the last child element of the menu:

let menu = document.getElementById('menu');


console.log(main.lastElementChild);
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
Output:

<li class="last">About Us</li>

Get all child elements


To get a live NodeList of child elements of a speci ed element, you use the childNodes property:

let children = parentElement.childNodes;

The childNodes property returns all child elements with any node type. To get the child element with
only the element node type, you use the children property:

let children = parentElement.children;

The following example selects all child elements of the element with the Id main:

let menu = document.getElementById('menu');


let children = menu.children;
console.log(children);

Output:

Summary
• The rstChild and lastChild return the rst and last child of a node, which can be any
node type including text node, comment node, and element node.
• The rstElementChild and lastElementChild return the rst and last child Element node.
• The childNodes returns a live NodeList of all child nodes of any node type of a speci ed
node. The children return all child Element nodes of a speci ed node.
fi
fi
fi
fi
fi
fi
fi
Get Siblings of an element Node
Summary: in this tutorial, you will learn how to select the next siblings, previous siblings, and
all siblings of an element.
Let’s say you have the following list of items:

<ul id="menu">
<li>Home</li>
<li>Products</li>
<li class="current">Customer Support</li>
<li>Careers</li>
<li>Investors</li>
<li>News</li>
<li>About Us</li>
</ul>

Get the next siblings


To get the next sibling of an element, you use the nextElementSibling attribute:

let nextSibling = currentNode.nextElementSibling;

The nextElementSibling returns null if the speci ed element is the last one in the list.
The following example uses the nextElementSibling property to get the next sibling of the list
item that has the current class:

let current = document.querySelector('.current');


let nextSibling = current.nextElementSibling;

console.log(nextSibling);

Output:

<li>Careers</li>

In this example:
• First, select the list item whose class is current using the querySelector().
• Second, get the next sibling of that list item using the nextElementSibling property.
To get all the next siblings of an element, you can use the following code:
fi
let current = document.querySelector('.current');
let nextSibling = current.nextElementSibling;

while(nextSibling) {
console.log(nextSibling);
nextSibling = nextSibling.nextElementSibling;
}

Get the previous siblings


To get the previous siblings of an element, you use the previousElementSibling attribute:

let current = document.querySelector('.current');


let prevSibling = currentNode.previousElementSibling;

The previousElementSibling property returns null if the current element is the rst one in the list.

The following example uses the previousElementSibling property to get the previous siblings of the
list item that has the current class:

let current = document.querySelector('.current');


let prevSiblings = current.previousElementSibling;

console.log(prevSiblings);

And the following example selects all the previous siblings of the list item that has the current class:

let current = document.querySelector('.current');


let prevSibling = current.previousElementSibling;
while(prevSibling) {
console.log(prevSibling);
prevSibling = current.previousElementSibling;
}
fi
Get all siblings of an element

To get all siblings of an element, we’ll use the logic:


• First, select the parent of the element whose siblings you want to nd.
• Second, select the rst child element of that parent element.
• Third, add the rst element to an array of siblings.
• Fourth, select the next sibling of the rst element.
• Finally, repeat the 3rd and 4th steps until there are no siblings left. In case the sibling is
the original element, skip the 3rd step.

The following function illustrates the steps:

let getSiblings = function (e) {


// for collecting siblings
let siblings = [];
// if no parent, return no sibling
if(!e.parentNode) {
return siblings;
}
// rst child of the parent node
let sibling = e.parentNode. rstChild;

// collecting siblings
while (sibling) {
if (sibling.nodeType === 1 && sibling !== e) {
siblings.push(sibling);
}
sibling = sibling.nextSibling;
}
return siblings;
};
fi
fi
fi
fi
fi
fi
Put it all together:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Siblings</title>
</head>
<body>
<ul id="menu">
<li>Home</li>
<li>Products</li>
<li class="current">Customer Support</li>
<li>Careers</li>
<li>Investors</li>
<li>News</li>
<li>About Us</li>
</ul>

<script>
let getSiblings = function (e) {
// for collecting siblings
let siblings = [];
// if no parent, return no sibling
if(!e.parentNode) {
return siblings;
}
// rst child of the parent node
let sibling = e.parentNode. rstChild;
// collecting siblings
while (sibling) {
if (sibling.nodeType === 1 && sibling !== e) {
siblings.push(sibling);
}
sibling = sibling.nextSibling;
}
return siblings;
};

let siblings = getSiblings(document.querySelector('.current'));


siblingText = siblings.map(e => e.innerHTML);
console.log(siblingText);
</script>
</body>
</html>

Output:

["Home", "Products", "Careers", "Investors", "News", "About Us"]


fi
fi
Summary
• The nextElementSibling returns the next sibling of an element or null if the element is the last
one in the list.
• The previousElementSibling returns the previous sibling of an element or null if the element is
the rst one in the list.
• To get all siblings of an element, you can use a helper function that utilizes
the nextElementSibling property.
fi
Section 4. Manipulating elements

CreateElement
Summary: in this tutorial, you will learn how to use the JavaScript document.createElement() to
create a new HTML element and attach it to the DOM tree.

To create an HTML element, you use the document.createElement() method:

let element = document.createElement(htmlTag);

The document.createElement() accepts an HTML tag name and returns a new Node with
the Element type.

1) Creating a new div example


Suppose that you have the following HTML document:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS CreateElement Demo</title>
</head>
<body>

</body>
</html>

The following example uses the document.createElement() to create a new <div> element:

let div = document.createElement('div');

And add an HTML snippet to the div:

div.innerHTML = '<p>CreateElement example</p>';

To attach the div to the document, you use the appendChild() method:

document.body.appendChild(div);
Put it all together:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS CreateElement Demo</title>
</head>
<body>
<script>
let div = document.createElement('div');
div.id = 'content';
div.innerHTML = '<p>CreateElement example</p>';
document.body.appendChild(div);
</script>
</body>
</html>

Adding an id to the div


If you want to add an id to a div, you set the id attribute of the element to a value, like this:

let div = document.createElement('div');


div.id = 'content';
div.innerHTML = '<p>CreateElement example</p>';

document.body.appendChild(div);

Adding a class to the div


The following example set the CSS class of a new div note:

let div = document.createElement('div');


div.id = 'content';
div.className = 'note';
div.innerHTML = '<p>CreateElement example</p>';

document.body.appendChild(div);
Adding text to a div
To add a piece of text to a <div>, you can use the innerHTML property as the above
example, or create a new Text node and append it to the div:

// create a new div and set its attributes


let div = document.createElement('div');
div.id = 'content';
div.className = 'note';

// create a new text node and add it to the div


let text = document.createTextNode('CreateElement example');
div.appendChild(text);

// add div to the document


document.body.appendChild(div);

Adding an element to a div


To add an element to a div, you create an element and append it to the div using the appendChild() method:

let div = document.createElement('div');


div.id = 'content';
div.className = 'note';

// create a new heading and add it to the div


let h2 = document.createElement('h2');
h2.textContent = 'Add h2 element to the div';
div.appendChild(h2);

// add div to the document


document.body.appendChild(div);

2) Creating new list items (li) example


Let’s say you have a list of items:

<ul id="menu">
<li>Home</li>
</ul>
The following code adds two li elements to the ul:

let li = document.createElement('li');
li.textContent = 'Products';
menu.appendChild(li);

li = document.createElement('li');
li.textContent = 'About Us';

// select the ul menu element


const menu = document.querySelector('#menu');
menu.appendChild(li);

Output:

<ul id="menu">
<li>Home</li>
<li>Products</li>
<li>About Us</li>
</ul>

3) Creating a script element example


Sometimes, you may want to load a JavaScript le dynamically. To do this, you can use
the document.createElement() to create the script element and add it to the document.
The following example illustrates how to create a new script element and loads the /lib.js le
to the document:

let script = document.createElement('script');


script.src = '/lib.js';
document.body.appendChild(script);

You can rst create a new helper function that loads a JavaScript le from an URL:

function loadJS(url) {
let script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}

And then use the helper function to load the /lib.js le:

loadJS('/lib.js');
fi
fi
fi
fi
fi
To load a JavaScript le asynchronously, you set the async attribute of the script element to true:

function loadJSAsync(url) {
let script = document.createElement('script');
script.src = url;
script.async = true;
document.body.appendChild(script);
}

Summary
• The document.createElement() creates a new HTML element.
• The element.appendChild() appends an HTML element to an existing element.
fi
appendChild
Summary: in this tutorial, you will learn how to use the JavaScript appendChild() method to
add a node to the end of the list of child nodes of a speci ed parent node.

Introduction to the JavaScript appendChild() method


The appendChild() is a method of the Node interface. The appendChild() method allows you
to add a node to the end of the list of child nodes of a speci ed parent node.
The following illustrates the syntax of the appendChild() method:

parentNode.appendChild(childNode);

In this method, the childNode is the node to append to the given parent node. The appendChild() returns
the appended child.

If the childNode is a reference to an existing node in the document, the appendChild() method moves
the childNode from its current position to the new position.

JavaScript appendChild() examples


Let’s take some examples of using the appendChild() method.

1) Simple appendChild() example


Suppose that you have the following HTML markup:

<ul id="menu">
</ul>

The following example uses the appendChild() method to add three list items to the <ul> element:

function createMenuItem(name) {
let li = document.createElement('li');
li.textContent = name;
return li;
}
// get the ul#menu
const menu = document.querySelector('#menu');
// add menu item
menu.appendChild(createMenuItem('Home'));
menu.appendChild(createMenuItem('Services'));
menu.appendChild(createMenuItem('About Us'));
fi
fi
How it works:
• First, the createMenuItem() function create a new list item element with a speci ed
name by using the createElement() method.
• Second, select the <ul> element with id menu using the querySelector() method.
• Third, call the createMenuItem() function to create a new menu item and use
the appendChild() method to append the menu item to the <ul> element

Output:

<ul id="menu">
<li>Home</li>
<li>Services</li>
<li>About Us</li>
</ul>

Put it all together:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>JavaScript appendChild() Demo</title>
</head>
<body>
<ul id="menu">
</ul>

<script>
function createMenuItem(name) {
let li = document.createElement('li');
li.textContent = name;
return li;
}
// get the ul#menu
const menu = document.querySelector('#menu');
// add menu item
menu.appendChild(createMenuItem('Home'));
menu.appendChild(createMenuItem('Services'));
menu.appendChild(createMenuItem('About Us'));
</script>
</body>
</html>
fi
2) Moving a node within the document example
Assuming that you have two lists of items:

<ul id=" rst-list">


<li>Everest</li>
<li>Fuji</li>
<li>Kilimanjaro</li>
</ul>

<ul id="second-list">
<li>Karakoram Range</li>
<li>Denali</li>
<li>Mont Blanc</li>
</ul>

The following example uses the appendChild() to move the rst child element from the rst list
to the second list:

// get the rst list


const rstList = document.querySelector('# rst-list');
// take the rst child element
const everest = rstList. rstElementChild;
// get the second list
const secondList = document.querySelector('#second-list');
// append the everest to the second list
secondList.appendChild(everest)

How it works:
• First, select the rst element by its id ( rst-list) using the querySelector() method.
• Second, select the rst child element from the rst list.
• Third, select the second element by its id (second-list) using
the querySelector() method.
• Finally, append the rst child element from the rst list to the second list using
the appendChild() method.
Here are the list before and after moving:
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
Summary
• Use appendChild() method to add a node to the end of the list of child nodes of a
speci ed parent node.
• The appendChild() can be used to move an existing child node to the new position
within the document.
fi
textContent
Summary: in this tutorial, you will learn how to use the JavaScript textContent property to get
the text content of a node and its descendants.

Reading textContent from a node


To get the text content of a node and its descendants, you use the textContent property:

let text = node.textContent;

Suppose that you have the following HTML snippet:

<div id="note">
JavaScript textContent Demo!
<span style="display:none">Hidden Text!</span>
<!-- my comment -->
</div>

The following example uses the textContent property to get the text of the <div> element:

let note = document.getElementById('note');


console.log(note.textContent);

How it works.
• First, select the div element with the id note by using the getElementById() method.
• Then, display the text of the node by accessing the textContent property.

Output:

JavaScript textContent Demo!


Hidden Text!

As you can see clearly from the output, the textContent property returns the concatenation of
the textContent of every child node, excluding comments (and also processing instructions).

textContent vs. innerText


On the other hand, the innerText takes the CSS style into account and returns only human-
readable text. For example:

let note = document.getElementById('note');


console.log(note.innerText);
Output:

JavaScript textContent Demo!

As you can see, the hidden text and comments are not returned.
Since the innerText property uses the up-to-date CSS to compute the text, accessing it will
trigger a re ow, which is computationally expensive.

A re ow occurs when a web brower needs to process and draw parts or all of a webpage
again.

Setting textContent for a node


Besides reading textContent, you can also use the textContent property to set the text for a node:

node.textContent = newText;

When you set textContent on a node, all the node’s children will be removed and replaced by
a single text node with the newText value. For example:

let note = document.getElementById('note');


note.textContent = 'This is a note';

Summary
• Use the textContent property to return the concatenation of the textContent of every
child node. You can use it to set a text for a node.
• The innerText returns the human-readable text that takes CSS into account.
fl
fl
innerHTML
Summary: in this tutorial, you will learn how to use the JavaScript innerHTML property of an
element to get or set an HTML markup contained in the element.
The innerHTML is a property of the Element that allows you to get or set the HTML markup
contained within the element:

element.innerHTML = 'new content';


element.innerHTML;

Reading the innerHTML property of an element


To get the HTML markup contained within an element, you use the following syntax:

let content = element.innerHTML;

When you read the innerHTML of an element, the web browser has to serialize the HTML
fragment of the element’s descendants.

1) Simple JavaScript innerHTML example


Suppose that you have the following markup:

<ul id="menu">
<li>Home</li>
<li>Services</li>
</ul>

The following example uses the innerHTML property to get the content of the <ul> element:

let menu = document.getElementById('menu');


console.log(menu.innerHTML);

How it works:
• First, select the <ul> element by its id (menu) using the getElementById() method.
• Then, get the HTML content of the <ul> element using the innerHTML.
Output:

<li>Home</li>
<li>Services</li>
2) Examining the current HTML source
The innerHTML property returns the current HTML source of the document, including all
changes that have been made since the page was loaded.
See the following example:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript innerHTML</title>
</head>
<body>
<ul id="menu">
<li>Home</li>
<li>Services</li>
</ul>
<script>
let menu = document.getElementById('menu');

// create new li element


let li = document.createElement('li');
li.textContent = 'About Us';
// add it to the ul element
menu.appendChild(li);

console.log(menu.innerHTML);
</script>
</body>
</html>

Output:

<li>Home</li>
<li>Services</li>
<li>About Us</li>

How it works.
• First, get the <ul> element with the id menu using the getElementById() method.
• Second, create a new <li> element and add it to the <ul> element using
the createElement() and appendChild() methods.
• Third, get the HTML of the <ul> element using the innerHTML property of the <ul>
element. The contents of the <ul> element include the initial content and the dynamic
content created dynamically by JavaScript.
Setting the innerHTML property of an element
To set the value of innerHTML property, you use this syntax:

element.innerHTML = newHTML;

The setting will replace the existing content of an element with the new content.
For example, you can remove the entire contents of the document by clearing the contents of
the document.body element:

document.body.innerHTML = '';

⚠ Security Risk

HTML5 speci es that a <script> tag inserted with innerHTML should not execute.
Suppose you have the following index.html document:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS innerHTML example</title>
</head>

<body>
<div id="main"></div>
<script src="app.js"></script>
</body>

</html>

And the app.js le looks like this:

const scriptHTML = `<script>alert("Alert from innerHTML");</script>`;


const main = document.getElementById('main');

main.innerHTML = scriptHTML;

In this example, the alert() inside the <script> tag will not execute.
However, if you change the source code of the app.js to the following:
fi
fi
const main = document.getElementById('main');

const externalHTML = `<img src='1' onerror='alert("Error loading image")'>`;


// shows the alert
main.innerHTML = externalHTML;

In this example, the image with the src 1 will not be loaded successfully. Therefore, the on error will
execute that runs the alert().

Instead of having a simple alert(), hackers may include malicious code, the users who open the
webpage will be vulnerable.

Therefore, you should not set the contents that you have no control to the innerHTML or you will
face a potential security risk.

If you want to insert plain text into the document, you can use the textContent property instead of
the innerHTML. The textContent will not be parsed as the HTML but as the raw text.

Summary
• Use innerHTML property of an element to get or set HTML contained within the element.
• The innerHTML property returns the current HTML source of the element, including any
change that has been made since the page was loaded.
• Do not use innerHTML to set new contents that you have no control to avoid a security risk.
innerHTML vs createElement
Summary: in this tutorial, you’ll learn the difference between the innerHTML and createElement() when it
comes to creating new elements in the DOM tree.

1) createElement is more performant


Suppose that you have a div element with the class container:

<div class="container"></div>

You can new elements to the div element by creating an element and appending it:

let div = document.querySelector('.container');

let p = document.createElement('p');
p.textContent = 'JS DOM';
div.appendChild(p);

You can also manipulate an element’s HTML directly using innerHTML like this:

let div = document.querySelector('.container');


div.innerHTML += '<p>JS DOM</p>';

Using innerHTML is cleaner and shorter when you want to add attributes to the element:

let div = document.querySelector('.container');


div.innerHTML += '<p class="note">JS DOM</p>';

However, using the innerHTML causes the web browsers to reparse and recreate all DOM
nodes inside the div element. Therefore, it is less ef cient than creating a new element and
appending to the div. In other words, creating a new element and appending it to the DOM
tree provides better performance than the innerHTML.

2) createElement is more secure


As mentioned in the innerHTML tutorial, you should use it only when the data comes from a
trusted source like a database.
If you set the contents that you have no control over to the innerHTML, the malicious code
may be injected and executed.
fi
3) Using DocumentFragment for composing DOM Nodes
Assuming that you have a list of elements and you need in each iteration:

let div = document.querySelector('.container');

for (let i = 0; i < 1000; i++) {


let p = document.createElement('p');
p.textContent = `Paragraph ${i}`;
div.appendChild(p);
}

This code results in recalculation of styles, painting, and layout every iteration. This is not very ef cient.

To overcome this, you typically use a DocumentFragment to compose DOM nodes and append it to the
DOM tree:

let div = document.querySelector('.container');

// compose DOM nodes


let fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
let p = document.createElement('p');
p.textContent = `Paragraph ${i}`;
fragment.appendChild(p);
}

// append the fragment to the DOM tree


div.appendChild(fragment);

In this example, we composed the DOM nodes by using the DocumentFragment object and
append the fragment to the active DOM tree once at the end.
A document fragment does not link to the active DOM tree, therefore, it doesn’t incur any
performance.
fi
DocumentFragment
Summary: in this tutorial, you’ll learn about the JavaScript DocumentFragment interface to
compose DOM nodes and update them to the active DOM tree.

Introduction to the JavaScript DocumentFragment interface


The DocumentFragment interface is a lightweight version of the Document that stores a
piece of document structure like a standard document. However, a DocumentFragment isn’t
part of the active DOM tree.
If you make changes to the document fragment, it doesn’t affect the document or incurs any
performance.
Typically, you use the DocumentFragment to compose DOM nodes and append or insert it to
the active DOM tree using appendChild() or insertBefore() method.
To create a new document fragment, you use the DocumentFragment constructor like this:

let fragment = new DocumentFragment();

Or you can use the createDocumentFragment() method of the Document object:

let fragment = document.createDocumentFragment();

This DocumentFragment inherits the methods of its parent, Node, and also implements those of
the ParentNode interface such as querySelector() and querySelectorAll().
JavaScript DocumentFragment example
Suppose that you have a <ul> element with the id language:

<ul id="language"></ul>

The following code creates a list of <li> elements (<li>) and append each to the <ul> element
using the DocumentFragment:

let languages = ['JS', 'TypeScript', 'Elm', 'Dart','Scala'];

let langEl = document.querySelector('#language')

let fragment = new DocumentFragment();


languages.forEach((language) => {
let li = document.createElement('li');
li.innerHTML = language;
fragment.appendChild(li);
})

langEl.appendChild(fragment);

Output

Js
TypeScript
Elm
Dart
Scale

How it works:
• First, select the <ul> element by its id using the querySelector() method.
• Second, create a new document fragment.
• Third, for each element in the languages array, create a list item element, assign the list
item’s innerHTML to the language, and append all the newly created list items to the
document fragment.
• Finally, append the document fragment to the <ul> element.
Put it all together:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DocumentFragment Demo</title>
</head>
<body>
<ul id="language"></ul>

<script>
let languages = ['JS', 'TypeScript', 'Elm', 'Dart', 'Scala'];

let langEl = document.querySelector('#language');


let fragment = new DocumentFragment();

languages.forEach((language) => {
let li = document.createElement('li');
li.innerHTML = language;
fragment.appendChild(li);
})

langEl.appendChild(fragment);
</script>

</body>
</html>

Summary
• Use the DocumentFragment to compose DOM nodes before updating them to the
active DOM tree to get better performance.
after()
Summary: in this tutorial, you’ll learn how to use the JavaScript after() method to insert a
node after an element.

Introduction to the JavaScript after() method


The after() is a method of the Element type. The element.after() method allows you to insert
one or more nodes after the element.
Here’s the syntax of the after() method:

Element.after(node)

In this syntax, the after() method inserts the node after the Element in the DOM tree.
For example, suppose you have a <h1> element and you want to insert a <p> element after
it, you can use the after() method like this:

h1.after(p)

To insert multiple nodes after an element, you pass the nodes to the after() method as follows:

Element.after(node1, node2, ... nodeN)

The after() method also accepts one or more strings. In this case, the after() method treats
the strings as Text nodes:

Element.after(str1, str2, ... strN)

The after() method returns unde ned. If a node cannot be inserted, it’ll throw a HierarchyRequestError exception.
fi
JavaScript after() examples
Let’s take some examples of using the JavaScript after() method.

1) Using JavaScript after() to insert a node after an element


The following example uses the after() method to insert a paragraph after a <h1> element:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript DOM - after()</title>
</head>

<body>
<h1>JavaScript DOM - after()</h1>

<script>
const h1 = document.querySelector('h1');

// create a new paragraph element


const p = document.createElement('p');
p.innerText = 'This is JavaScript DOM after() method demo';

// insert the paragraph after the heading


h1.after(p);
</script>
</body>

</html>

How it works.
First, get the heading element using the querySelector() method:

const h1 = document.querySelector('h1');

Second, create a new paragraph element and set its innerText:

const p = document.createElement('p');
p.innerText = 'This is JavaScript DOM after() method demo';

Third, insert the <p> element after the <h1> element:

h1.after(p);
2) Using JavaScript after() to insert multiple nodes after an element
The following example uses the after() method to insert multiple nodes after an element:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript DOM - after()</title>
</head>
<body>
<ul>
<li>Angular</li>
<li>Vue</li>
</ul>
<script>
const list = document.querySelector('ul');

const libs = ['React', 'Meteor', 'Polymer'];


const items = libs.map((lib) => {
const item = document.createElement('li');
item.innerText = lib;
return item;
});

list.lastChild.after(...items);

</script>
</body>
</html>

How it works:
First, select the ul element using the querySelector() method:

const list = document.querySelector('ul');

Second, de ne an array of strings. In practice, you may get it from an API call.

const libs = ['React', 'Meteor', 'Polymer'];

Third, transform the array of strings into an array of li elements using the map() method:

const items = libs.map((lib) => {


const item = document.createElement('li');
item.innerText = lib;
return item;
});
fi
Finally, insert the list item elements after the last child of the ul element:

list.lastChild.after(...items);

Note that the ...items uses the spread operator to spread out the element of the items array.
The ul element will look like the following:

<ul>
<li>Angular</li>
<li>Vue</li>
<li>React</li>
<li>Meteor</li>
<li>Polymer</li>
</ul>

The last three items (React, Meteor, and Polymer) were inserted after the item Vue, which
was the last child of the <ul> element.

3) Using JavaScript after() to insert strings


When you use strings in the after() method, it will treat them as Text nodes. For example:

<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript DOM - after()</title>
<style>
button {
padding: 0.75em 1em;
background-color: #F7DF1E;
color: #000;
cursor: pointer;
border-radius: 50vw;
}
</style>
</head>
<body>
<button>Donate Here</button>
<script>
const button = document.querySelector('button');
button. rstChild.after(' 🧡 ');
</script>
</body>
</html>

Summary

• Use the element.after() method to insert one or more nodes after the element.
fi
append
Summary: in this tutorial, you’ll learn how to use the JavaScript append() method to insert a
set of Node objects or DOMString objects after the last child of a parent node.

Introduction to JavaScript append() method


The parentNode.append() method inserts a set of Node objects or DOMString objects after
the last child of a parent node:

parentNode.append(...nodes);
parentNode.append(...DOMStrings);

The append() method will insert DOMString objects as Text nodes.

Note that a DOMString is a UTF-16 string that maps directly to a string.

The append() method has no return value. It means that the append() method implicitly returns unde ned.

JavaScript append() method examples


Let’s take some examples of using the append() method.

1) Using the append() method to append an element example


Suppose that you have the following ul element:

<ul id="app">
<li>JavaScript</li>
</ul>

The following example shows how to create a list of li elements and append them to the ul element:

let app = document.querySelector('#app');

let langs = ['TypeScript','HTML','CSS'];

let nodes = langs.map(lang => {


let li = document.createElement('li');
li.textContent = lang;
return li;
});

app.append(...nodes);
fi
Output HTML:

<ul id="app">
<li>JavaScript</li>
<li>TypeScript</li>
<li>HTML</li>
<li>CSS</li>
</ul>

How it works:
• First, select the ul element by its id by using the querySelector() method.
• Second, declare an array of languages.
• Third, for each language, create a new li element with the textContent is assigned to the
language.
• Finally, append li elements to the ul element by using the append() method.

2) Using the append() method to append text to an element example


Assume that you have the following HTML:

<div id="app"></div>

You can use the append() method to append a text to an element:

let app = document.querySelector('#app');


app.append('append() Text Demo');

console.log(app.textContent);

Output HTML:

<div id="app">append() Text Demo</div>


append vs. appendChild()
Here are the differences between append() and appendChild():
Differences append() appendChild()
Return value unde ned The appended Node object

Input Multiple Node Objects A single Node object

Parameter Types Accept Node and DOMString Only Node

Summary
• Use the parentNode.append() method to append a set of Node objects or DOMString objects
after the last child node of the parentNode.
fi
prepend
Summary: in this tutorial, you’ll learn about the JavaScript prepend() method that inserts Node objects
or DOMString objects before the rst child of a parent node.

Introduction to JavaScript prepend() method


The prepend() method inserts a set of Node objects or DOMString objects before the rst child of a
parent node:

parentNode.prepend(...nodes);
parentNode.prepend(...DOMStrings);

The prepend() method inserts DOMString objects as Text nodes. Note that a DOMString is a
UTF-16 string that directly maps to a string.
The prepend() method returns unde ned.

JavaScript prepend() method examples


Let’s take some examples of using the prepend() method.

1) Using the prepend() method to prepend an element example


Let’s say you have the following <ul> element:

<ul id="app">
<li>HTML</li>
</ul>

This example shows how to create a list of li elements and prepend them to the ul element:

let app = document.querySelector('#app');

let langs = ['CSS','JavaScript','TypeScript'];

let nodes = langs.map(lang => {


let li = document.createElement('li');
li.textContent = lang;
return li;
});

app.prepend(...nodes);
fi
fi
fi
Output HTML:

<ul id="app">
<li>CSS</li>
<li>JavaScript</li>
<li>TypeScript</li>
<li>HTML</li>
</ul>

How it works:
• First, select the ul element by its id by using the querySelector() method.
• Second, declare an array of strings.
• Third, for each element in an array, create a new li element with the textContent is
assigned to the array element.
• Finally, prepend the li elements to the ul parent element by using the prepend() method.

2) Using the prepend() method to prepend text to an element example


Suppose that you have the following element:

<div id="app"></div>

The following shows how to use the prepend() method to prepend a text to the above <div> element:

let app = document.querySelector('#app');


app.prepend('prepend() Text Demo');

console.log(app.textContent);

Output HTML:

<div id="app">prepend() Text Demo</div>

Summary
• Use the parentNode.prepend() method to prepend a list of Node objects or DOMString objects
before the rst child node of the parent node.
fi
insertAdjacentHTML
Summary: in this tutorial, you’ll learn how to use the insertAdjacentHTML() method to insert
HTML into the document.

Introduction to JavaScript insertAdjacentHTML() method


The insertAdjacentHTML() is a method of the Element interface so that you can invoke it from any
element.

The insertAdjacentHTML() method parses a piece of HTML text and inserts the resulting nodes into
the DOM tree at a speci ed position:

element.insertAdjacentHTML(positionName, text);

The insertAdjacentHTML() method has two parameters:

1) position
The positionName is a string that represents the position relative to the element.
The positionName accepts one of the following four values:
• 'beforebegin': before the element
• 'afterbegin': before its rst child of the element.
• 'beforeend': after the last child of the element
• 'afterend': after the element
Note that the 'beforebegin' and 'afterend' are only relevant if the element is in the DOM tree
and has a parent element.
The insertAdjacentHTML() method has no return value, or unde ned by default.
The following visualization illustrates the position name:
fi
fi
fi
2) text
The text parameter is a string that the insertAdjacentHTML() method parses as HTML or
XML. It cannot be Node objects

Security consideration
Like the innerHTML, if you use the user input to pass into the insertAdjacentHTML() method,
you should always escape it to avoid security risk.

JavaScript insertAdjacentHTML() method example


The following JavaScript example uses the insertAdjacentHTML() method to insert various
elements into the page with the positions relative to the ul element:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>insertAdjacentHTML() Demo</title>
</head>
<body>
<ul id="list">
<li>CSS</li>
</ul>

<script>
let list = document.querySelector('#list');

list.insertAdjacentHTML('beforebegin', '<h2>Web Technology</h2>');


list.insertAdjacentHTML('afterbegin', '<li>HTML</li>');
list.insertAdjacentHTML('beforeend', '<li>JavaScript</li>');
list.insertAdjacentHTML('afterend', '<p>For frontend developers</p>');
</script>
</body>
</html>

Output:

Web Technology
• HTML
• CSS
• JavaScript

For frontend developers


How it works:
• First, select the ul element by its id list using the querySelector() method.
• Next, use the insertAdjacentHTML() method to insert a heading 2 element before
the ul element. The position is 'beforebegin'.
• Then, use the insertAdjacentHTML() method to insert a new list item element before the
rst child of the ul element. The position is 'afterbegin'.
• After that, use the insertAdjacentHTML() method to insert a new list item element after
the last child of the ul element with the position 'beforeend'.
• Finally, insert use the insertAdjacentHTML() method to insert a new paragraph element
after the ul element with the position 'afterend'.
Summary
• Use the insertAdjacentHTML() method to insert a text as Nodes into the DOM tree at a
speci ed position.
• Always escape the user input text that you pass into the insertAdjacentHTML() method
to avoid security risk
fi
fi
replaceChild
Summary: in this tutorial, you will learn how to use the JavaScript Node.replaceChild() method to
replace an HTML element by a new one.

To replace an HTML element, you use the node.replaceChild() method:

parentNode.replaceChild(newChild, oldChild);

In this method, the newChild is the new node to replace the oldChild node which is the old
child node to be replaced.
Suppose that you have the following list of items:

<ul id="menu">
<li>Homepage</li>
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>

The following example creates a new list item element and replaces the rst list item element
in the menu by the new one:

let menu = document.getElementById('menu');


// create a new node
let li = document.createElement('li');
li.textContent = 'Home';
// replace the rst list item

menu.replaceChild(li, menu. rstElementChild);


fi
fi
fi
Put it all together.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript DOM: Replace Elements</title>
</head>
<body>
<ul id="menu">
<li>Homepage</li>
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>
<script>
let menu = document.getElementById('menu');
// create a new node
let li = document.createElement('li');
li.textContent = 'Home';
// replace the rst list item

menu.replaceChild(li, menu. rstElementChild);


</script>
</body>
</html>

Summary
• Use Node.replaceChild() to replace a child element of a node by a new element.
fi
fi
cloneNode
Summary: in this tutorial, you will learn how to use the JavaScript cloneNode() method to
clone an element.
The cloneNode() is a method of the Node interface that allows you to clone an element:

let clonedNode = originalNode.cloneNode(deep);

Pamaraters
deep
The cloneNode() method accepts an optional parameter deep:
• If the deep is true, then the original node and all of its descendants are cloned.
• If the deep is false, only the original node will be cloned. All the node’s descendants
will not be cloned.
The deep parameter defaults to false if you omit it.

originalNode
The originalNode is the element to be cloned.

Return value
The cloneNode() returns a copy of the originalNode.

Usage notes
Besides the DOM structure, the cloneNode() copies all attributes and inline listeners of the original
node. However, it doesn’t copy the event listeners added via addEventListener() or assignment to
element’s properties such as originalNode.onclick = eventHandler().

If you clone a node with an id attribute and place the cloned node in the same document, the id will
be duplicate. In this case, you need to change the id before adding it to the DOM tree.
JavaScript cloneNode() example
The following example uses the cloneNode() method to copy the <ul> element and place it in
the same document:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript cloneNode() Demo</title>
</head>
<body>
<ul id="menu">
<li>Home</li>
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>
<script>
let menu = document.querySelector('#menu');
let clonedMenu = menu.cloneNode(true);
clonedMenu.id = 'menu-mobile';
document.body.appendChild(clonedMenu);
</script>
</body>
</html>

How it works.
• First, select the <ul> with the id menu by using the querySelector() method.
• Second, create a deep clone of the <ul> element using the cloneNode() method.
• Third, change the id of the cloned element to avoid duplicate.
• Finally, append the cloned element to the child nodes of the document.body using
the appendChild() method.
Output:

Summary
• Use the node.cloneNode() method to clone the node.
• Pass true into the cloneNode() method to create a deep clone of a DOM element.
removeChild
Summary: in this tutorial, you will learn how to use the JavaScript removeChild() method to remove
a child node from a parent node.

Introduction to JavaScript removeChild() method


To remove a child element of a node, you use the removeChild() method:

let childNode = parentNode.removeChild(childNode);

The childNode is the child node of the parentNode that you want to remove. If the childNode is not
the child node of the parentNode, the method throws an exception.

The removeChild() returns the removed child node from the DOM tree but keeps it in the memory,
which can be used later.

If you don’t want to keep the removed child node in the memory, you use the following syntax:

parentNode.removeChild(childNode);

The child node will be in the memory until it is destroyed by the JavaScript garbage collector.

JavaScript removeChild() example


Suppose you have the following list of items:

<ul id="menu">
<li>Home</li>
<li>Products</li>
<li>About Us</li>
</ul>

The following example uses the removeChild() to remove the last list item:

let menu = document.getElementById('menu');


menu.removeChild(menu.lastElementChild);

How it works:
• First, get the ul element with the id menu by using the getElementById() method.
• Then, remove the last element of the ul element by using the removeChild() method.
The menu.lastElementChild property returns the last child element of the menu.
Put it all together.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript removeChild()</title>
</head>
<body>
<ul id="menu">
<li>Home</li>
<li>Products</li>
<li>About Us</li>
</ul>
<script>
let menu = document.getElementById('menu');
menu.removeChild(menu.lastElementChild);
</script>
</body>
</html>

Removing all child nodes of an element


To remove all child nodes of an element, you use the following steps:
• Get the rst node of the element using the rstChild property.
• Repeatedly removing the child node until there are no child nodes left.
The following code shows how to remove all list items of the menu element:

let menu = document.getElementById('menu');


while (menu. rstChild) {
menu.removeChild(menu. rstChild);
}

You can remove all child nodes of an element by setting the innerHTML property of the parent node
to blank:

let menu = document.getElementById('menu');


menu.innerHTML = '';

Summary
• Use parentNode.removeChild() to remove a child node of a parent node.
• The parentNode.removeChild() throws an exception if the child node cannot be found in
the parent node.
fi
fi
fi
fi
insertBefore
Summary: in this tutorial, you will learn how to use the JavaScript insertBefore() to insert a
node before another node as a child node of a speci ed parent node.

Introduction to JavaScript insertBefore() method


To insert a node before another node as a child node of a parent node, you use the parentNode.insertBefore() method:

parentNode.insertBefore(newNode, existingNode);

In this method:
• The newNode is the new node to be inserted.
• The existingNode is the node before which the new node is inserted. If the existingNode is null,
the insertBefore() inserts the newNode at the end of the parentNode‘s child nodes.
The insertBefore() returns the inserted child node.

JavaScript insertBefore() helper function


The following insertBefore() function inserts a new node before a speci ed node:

function insertBefore(newNode, existingNode) {


existingNode.parentNode.insertBefore(newNode, existingNode);
}

JavaScript insertBefore() example


Suppose that you have the following list of items:

<ul id="menu">
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>

The following example uses the insertBefore() method to insert a new node as the rst list item:

let menu = document.getElementById('menu');


// create a new li node
let li = document.createElement('li');
li.textContent = 'Home';

// insert a new node before the rst list item


menu.insertBefore(li, menu. rstElementChild);
fi
fi
fi
fi
fi
How it works.
• First, get the menu element using the getElementById() method.
• Second, create a new list item using the createElement() method.
• Third, insert the list item element before the rst child element of the menu element
using the insertBefore() method.

Put it all together.

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>JavaScript insertBefore()</title>
</head>

<body>
<ul id="menu">
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>
<script>
let menu = document.getElementById('menu');
// create a new li node
let li = document.createElement('li');
li.textContent = 'Home';

// insert a new node before the rst list item


menu.insertBefore(li, menu. rstElementChild);
</script>
</body>

</html>

Summary
• Use the parentNode.insertBefore() to insert a new node before an existing node as a
child node of a parent node.
fi
fi
fi
insertAfter
Summary: in this tutorial, you will learn how to insert a new node after an existing node as a
child node of a parent node.

This tutorial was written when DOM API did not support the after() method. Now, you can
use the after() method to insert a node after an element.

JavaScript DOM provides the insertBefore() method that allows you to insert a new node after an
existing node as a child node.

To insert a new node after an existing node as a child node, you can use the following approach:

• First, select the next sibling node of the existing node.


• Then, select the parent node of the existing node and call the insertBefore() method on the
parent node to insert a new node before that immediate sibling node.
The following insertAfter() function illustrates the logic:

function insertAfter(newNode, existingNode) {


existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}

Suppose that you have the following list of items:

<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>

The following inserts a new node after the last list item:

let menu = document.getElementById('menu');


// create a new li node
let li = document.createElement('li');
li.textContent = 'Services';

// insert a new node after the last list item


insertAfter(li, menu.lastElementChild);
How it works:
• First, select the ul element by its id (menu) using the getElementById() method.
• Second, create a new list item using the createElement() method.
• Third, use the insertAfter() method to insert a list item element after the last list item element.

Put it all together.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript insertAfter() Demo</title>
</head>
<body>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
<script>
function insertAfter(newNode, existingNode) {
existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}

let menu = document.getElementById('menu');


// create a new li node
let li = document.createElement('li');
li.textContent = 'Services';
insertAfter(li, menu.lastElementChild);
</script>
</body>
</html>

The menu looks like the following after the insert:

<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>Services</li>
</ul>

Summary
• JavaScript DOM hasn’t supported the insertAfter() method yet.
• Use the insertBefore() method and the nextSibling property to insert a new before an
existing node as a child of a parent node.
Section 5. Working with Attributes

HTML Attributes & DOM Object’s Properties


Summary: in this tutorial, you will learn the relationships between HTML attributes and DOM object’s properties.
When the web browser loads an HTML page, it generates the corresponding DOM objects based
on the DOM nodes of the document.

For example, if a page contains the following input element:

<input type="text" id="username">

The web browser will generate an HTMLInputElement object.


The input element has two attributes:
• The type attribute with the value text.
• The id attribute with the value username.
The generated HTMLInputElement object will have the corresponding properties:
• The input.type with the value text.
• The input.id with the value username.
In other words, the web browser will automatically convert attributes of HTML elements to
properties of DOM objects.
However, the web browser only converts the standard attributes to the DOM object’s
properties. The standard attributes of an element are listed on the element’s speci cation.
Attribute-property mapping is not always one-to-one. For example:

<input type="text" id="username" secured="true">

In this example, the secured is a non-standard attribute:

let input = document.querySelector('#username');


console.log(input.secured); // unde ned
fi
fi
Attribute methods
To access both standard and non-standard attributes, you use the following methods:
• element.getAttribute(name) – get the attribute value
• element.setAttribute(name, value) – set the value for the attribute
• element.hasAttribute(name) – check for the existence of an attribute
• element.removeAttribute(name) – remove the attribute

element.attributes
The element.attributes property provides a live collection of attributes available on a speci c element.
For example:

let input = document.querySelector('#username');

for(let attr of input.attributes) {


console.log(`${attr.name} = ${attr.value}` )
}

Output:

type = text
id = username
secure = true

Note that element.attributes is a NamedNodeMap, not an Array, therefore, it has no Array’s methods.

Attribute-property synchronization
When a standard attribute changes, the corresponding property is auto-updated with some
exceptions and vice versa.
Suppose that you have the following input element:

<input type="text" id="username" tabindex="1">


fi
The following example illustrates the change of the tabindex attribute is propagated to
the tabIndex property and vice versa:

let input = document.querySelector('#username');

// attribute -> property


input.setAttribute('tabindex', 2);
console.log(input.tabIndex); // 2

// property -> attribute


input.tabIndex = 3;
console.log(input.getAttribute('tabIndex')); // 3

The following example shows when the value attribute changes, it re ects in the value property, but
not the other way around:

let input = document.querySelector('#username');

// attribute -> property: OK


input.setAttribute('value','guest');
console.log(input.value); // guest

// property -> attribute: doesn't change


input.value = 'admin';
console.log(input.getAttribute('value')); // guest

DOM properties are typed


The value of an attribute is always a string. However, when the attribute is converted to the
property of a DOM object, the property value can be a string, a boolean, an object, etc.
The following checkbox element has the checked attribute. When the checked attribute is
converted to the property, it is a boolean value:

<input type="checkbox" id="chkAccept" checked> Accept

let checkbox = document.querySelector('#chkAccept');


console.log(checkbox.checked); // true

The following shows an input element with the style attribute:

<input type="password" id="password" style="color:red;with:100%">


fl
The style attribute is a string while the style property is an object:

let input = document.querySelector('#password');

let styleAttr = input.getAttribute('style');


console.log(styleAttr);

console.dir(input.style);

Output:

[object CSSStyleDeclaration]

The data-* attributes


If you want to add a custom attribute to an element, you should pre x it with the data- e.g., data-
secured because all attributes start with data- are reserved for the developer’s uses.

To access data-* attributes, you can use the dataset property. For example, we have the
following div element with custom attributes:

<div id="main" data-progress="pending" data-value="10%"></div>

The following shows how to access the data-* attributes via the dataset property:

let bar = document.querySelector('#main');


console.log(bar.dataset);

Output:

[object DOMStringMap] {
progress: "pending",
value: "10%"
}

Summary
• Attributes are speci ed in HTML elements.
• Properties are speci ed DOM objects.
• Attributes are converted to properties respectively.
• Use the element.attributes property to access standard and custom attributes of an element.
• Use the element.dataset property to access the data-* attributes.
fi
fi
fi
setAttribute
Summary: in this tutorial, you will learn how to use the JavaScript setAttribute() method to
set a value for an attribute on a speci ed element.

Introduction to the JavaScript setAttribute() method


To set a value of an attribute on a speci ed element, you use the setAttribute() method:

element.setAttribute(name, value);

Parameters
The name speci es the attribute name whose value is set. It’s automatically converted to
lowercase if you call the setAttribute() on an HTML element.
The value speci es the value to assign to the attribute. It’s automatically converted to a string
if you pass a non-string value to the method.

Return value
The setAttribute() returns unde ned.
Note that if the attribute already exists on the element, the setAttribute() method updates the
value; otherwise, it adds a new attribute with the speci ed name and value.
Typically, you use the querySelector() or getElementById() to select an element before calling
the setAttribute() on the selected element.
To get the current value of an attribute, you use the getAttribute() method. To remove an
attribute, you call the removeAttribute() method.
fi
fi
fi
fi
fi
fi
JavaScript setAttribute() example
See the following example:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS setAttribute() Demo</title>
</head>
<body>
<button id="btnSend">Send</button>

<script>
let btnSend = document.querySelector('#btnSend');
if (btnSend) {
btnSend.setAttribute('name', 'send');
btnSend.setAttribute('disabled', '');
}
</script>
</body>
</html>

How it works:
• First, select the button with the id btnSend by using the querySelector() method.
• Second, set the value of the name attribute to send using the setAttribute() method.
• Third, set the value of the disabled attribute so that when users click the button, it will do
nothing.

Note that the disabled attribute is special because it is a Boolean attribute. If a Boolean
attribute is present, whatever value it has, the value is considered to be true. To set the
value of a Boolean attribute to false, you need to remove the entire attribute using
the removeAttribute() method.

Summary
• Use the setAttribute() to set the value of an attribute on a speci ed element.
• Setting the value of a Boolean attribute to whatever value, that value will be considered
to be true.
fi
getAttribute
Summary: in this tutorial, you will learn how to use the JavaScript getAttribute() method to
get the value of a speci ed attribute on an element.

Introduction to the JavaScript getAttribute() method


To get the value of an attribute on a speci ed element, you call the getAttribute() method of
the element:

let value = element.getAttribute(name);

Parameters
The getAttribute() accepts an argument which is the name of the attribute from which you
want to return the value

Return value
If the attribute exists on the element, the getAttribute() returns a string that represents the
value of the attribute. In case the attribute does not exist, the getAttribute() returns null.
Note that you can use the hasAttribute() method to check if the attribute exists on the
element before getting its value.

JavaScript getAttribute() example


Consider the following example:

<!DOCTYPE html>
<html>
<head>
<title>JS getAttribute() Demo</title>
</head>
<body>
<a href="https://www.javascripttutorial.net"
target="_blank"
id="js">JavaScript Tutorial
</a>
<script>
let link = document.querySelector('#js');
if (link) {
let target = link.getAttribute('target');
console.log(target);
}
</script>
</body>
</html>
fi
fi
Output

_blank

How it works:
• First, select the link element with the id js using the querySelector() method.
• Second, get the target attribute of the link by calling the getAttribute() of the selected
link element.
• Third, show the value of the target on the Console window.
The following example uses the getAttribute() method to get the value of the title attribute of
the link element with the id js:

let link = document.querySelector('#js');


if (link) {
let title = link.getAttribute('title');
console.log(title);
}

Output:

null

Summary
• Get the value of an attribute of a speci ed element by calling the getAttribute() method
on the element.
• The getAttribute() returns null if the attribute does not exist.
fi
removeAttribute
Summary: in this tutorial, you will learn how to use the JavaScript removeAttribute() to
remove the attribute with the speci ed name from the element.

Introduction to JavaScript removeAttribute() method


The removeAttribute() removes an attribute with a speci ed name from an element:

element.removeAttribute(name);

Parameters
The removeAttribute() accepts an argument which is the name of the attribute that you want to
remove. If the attribute does not exist, the removeAttribute() method wil not raise an error.

Return value
The removeAttribute() returns a value of unde ned.

Usage notes
HTML elements have some attributes which are Boolean attributes. To set false to the
Boolean attributes, you cannot simply use the setAttribute() method, but you have to remove
the attribute entirely using the removeAttribute() method.
For example, the values of the disabled attributes are true in the following cases:

<button disabled>Save Draft</button>


<button disabled="">Save</button>
<button disabled="disabled">Cancel</button>

Similarly, the values of the following readonly attributes are true:

<input type="text" readonly>


<textarea type="text" readonly="">
<textarea type="text" readonly="readonly">
fi
fi
fi
JavaScript removeAttribute() example
The following example uses the removeAttribute() method to remove the target attribute from
the link element with the id js:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS removeAttribute() Demo</title>
</head>
<body>
<a href="https://www.javascripttutorial.net"
target="_blank"
id="js">JavaScript Tutorial</a>

<script>
let link = document.querySelector('#js');
if (link) {
link.removeAttribute('target');
}
</script>
</body>
</html>

How it works:
• Select the link element with id js using the querySelector() method.
• Remove the target attribute by calling the removeAttribute() on the selected link element.

Summary
• Use the removeAttribute() to remove an attribute from a speci ed element.
• Setting the value of a Boolean attribute to false will not work; use
the removeAttribute() method instead.
fi
hasAttribute
Summary: in this tutorial, you will learn how to use the JavaScript hasAttribute() to check if an
element has an attribute.

Introduction to the JavaScript hasAttribute() method


To check an element has a speci ed attribute or not, you use the hasAttribute() method:

let result = element.hasAttribute(name);

Parameters
The hasAttribute() method accepts an argument that speci es the name of the attribute that
you want to check.

Return value
The hasAttribute() returns a Boolean value that indicates if the element has the speci ed attribute.

If the element contains an attribute, the hasAttribute() returns true; otherwise, it returns false.

JavaScript hasAttribute() example


See the following example:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS hasAttribute() Demo</title>
</head>
<body>

<button id="btnSend" disabled>Send</button>

<script>
let btn = document.querySelector('#btnSend');
if (btn) {
let disabled = btn.hasAttribute('disabled');
console.log(disabled);
}
</script>
</body>
</html>
fi
fi
fi
Output:

true

How it works:
• Select the button with the id btnSend by using the querySelector() method.
• Check if the button has the disabled attribute by calling the hasAttribute() method on the
button element.

Summary
• Use the hasAttribute() method to check if an element contains a speci ed attribute.

fi
Section 6. Manipulating Element’s Styles

Style Property
Summary: in this tutorial, you will learn how to use the style property to manipulate the inline
style of the HTML elements.

Setting inline styles


To set the inline style of an element, you use the style property of that element:

element.style

The style property returns the read-only CSSStyleDeclaration object that contains a list of CSS
properties. For example, to set the color of an element to red, you use the following code:

element.style.color = 'red';

If the CSS property contains hyphens (-) for example -webkit-text-stroke you can use the
array-like notation ([]) to access the property:

element.style.['-webkit-text-stock'] = 'unset';

The following table shows the common CSS properties:


JavaScript
CSS

background background
background-attachment backgroundAttachment
background-color backgroundColor
background-image backgroundImage
background-position backgroundPosition
background-repeat backgroundRepeat
border border
border-bottom borderBottom
border-bottom-color borderBottomColor
border-bottom-style borderBottomStyle
border-bottom-width borderBottomWidth
JavaScript
CSS

border-color borderColor
border-left borderLeft
border-left-color borderLeftColor
border-left-style borderLeftStyle
border-left-width borderLeftWidth
border-right borderRight
border-right-color borderRightColor
border-right-style borderRightStyle
border-right-width borderRightWidth
border-style borderStyle
border-top borderTop
border-top-color borderTopColor
border-top-style borderTopStyle
border-top-width borderTopWidth
border-width borderWidth
clear clear
clip clip
color color
cursor cursor
display display
lter lter
oat cssFloat
font font
font-family fontFamily
font-size fontSize
font-variant fontVariant
font-weight fontWeight
height height
left left
letter-spacing letterSpacing
line-height lineHeight
fl
fi
fi
JavaScript
CSS

list-style listStyle
list-style-image listStyle
list-style-position listStylePosition
list-style-type listStyleType
margin margin
margin-bottom marginBottom
margin-left marginLeft
margin-right marginRight
margin-top marginTop
over ow over ow
padding padding
padding-bottom paddingBottom
padding-left paddingLeft
padding-right paddingRight
padding-top paddingTop
page-break-after pageBreakAfter
page-break-before pageBreakBefore
position position
stroke-dasharray strokeDasharray
stroke-dashoffset strokeDashoffset
stroke-width strokeWidth
text-align textAlign
text-decoration textDecoration
text-indent textIndent
text-transform textTransform
top top
vertical-align verticalAlign
visibility visibility
width width
z-index zIndex
fl
fl
To completely override the existing inline style, you set the cssText property of the style object.
For example:

element.style.cssText = 'color:red;background-color:yellow';

Or you can use the setAttribute() method:

element.setAttribute('style','color:red;background-color:yellow');

Once setting the inline style, you can modify one or more CSS properties:

element.style.color = 'blue';

If you do not want to completely overwrite the existing CSS properties, you can concatenate
the new CSS property to the cssText as follows:

element.style.cssText += 'color:red;background-color:yellow';

In this case, the += operator appends the new style string to the existing one.
The following css() helper function is used to set multiple styles for an element from an object
of key-value pairs:

function css(e, styles) {


for (const property in styles)
e.style[property] = styles[property];
}

You can use this css() function to set multiple styles for an element with the id #content as follows:

let content = document.querySelector('#content');


css(content, { background: 'yellow', border: 'solid 1px red'});
The following example uses the style object to set the CSS properties of a paragraph with the
id content:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Style Demo</title>
</head>
<body>
<p id="content">JavaScript Setting Style Demo!</p>
<script>
let p = document.querySelector('#content');
p.style.color = 'red';
p.style.fontWeight = 'bold';
</script>
</body>
</html>

How it works:
• First, select the paragraph element whose id is content by using the querySelector() method.
• Then, set the color and font-weight properties of the paragraph by setting
the color and fontWeight properties of the style object.

Getting inline styles


The style property returns the inline styles of an element. It is not very useful in practice because
the style property doesn’t return the rules that come from elsewhere e.g., styles from an external
style sheet.

To get all styles applied to an element, you should use the window.getComputedStyle() method.

Summary
• Use the properties of element.style object to set the inline CSS properties for the HTML
element.
getComputedStyle
Summary: in this tutorial, you will learn how to use the JavaScript getComputedStyle() to get
the computed CSS properties of an element.

Introduction to JavaScript getComputedStyle() method


The getComputedStyle() is a method of the window object, which returns an object that contains the
computed style an element:

let style = window.getComputedStyle(element [,pseudoElement]);

Parameters
The getComputedStyle() method accepts two arguments:
• element is the element that you want to return the computed styles. If you pass
another node type e.g., Text node, the method will throw an error.
• pseudoElement speci es the pseudo-element to match. It defaults to null.
For example, if you want to get the computed value of all the CSS properties of a link with the
hover state, you pass the following arguments to the getComputedStyle() method:

let link = document.querySelector('a');


let style = getComputedStyle(link,':hover');
console.log(style);

Note that window is the global object, therefore, you can omit it when calling get the getComputedStyle() method.

Return value
The getComputedStyle() method returns a live style object which is an instance of
the CSSStyleDeclaration object. The style is automatically updated when the styles of the
element are changed.
fi
JavaScript getComputedStyle() examples
Let’s take some examples of using the getComputedStyle() method.

1) Simple getComputedStyle() example


Consider the following example:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>JS getComputedStyle() Demo</title>
<style type="text/css">
.message {
background-color: # f3d4;
border: solid 1px #f6b73c;
padding: 20px;
color: black;
}
</style>
</head>
<body>

<p class="message" style="color:red">


This is a JS getComputedStyle() Demo!
</p>

<script>
let message = document.querySelector('.message');
let style = getComputedStyle(message);

console.log('color:', style.color);
console.log('background color:', style.backgroundColor);
</script>
</body>
</html>

Note that for the demonstration purpose, we mix all CSS and JavaScript with HTML. In
practice, you should separate them in different les.
Output:

color: rgb(255, 0, 0)
background color: rgb(255, 243, 212)
ff
fi
How it works:
• First, de ne CSS rules for the message class in the head section of the HTML le. The
text color is black.
• Second, declare a paragraph element whose text color is red as de ned in the inline
style. This rule will override the one de ned in the head section.
• Third, use the getComputedStyle() method to get all the computed style of the
paragraph element. The color property is red as indicated in the Console window
( rgb(255, 0, 0)) as expected.

2) The getComputedStyle() for pseudo-elements example


The following example uses the getComputedStyle() method to pull style information from a
pseudo-element:

<html>
<head>
<title>JavaScript getComputedStyle() Demo</title>
<style>
body {
font: arial, sans-serif;
font-size: 1em;
line-height: 1.6;
}

p:: rst-letter {
font-size: 1.5em;
font-weight: normal
}
</style>
</head>
<body>
<p id='main'>JavaScript getComputedStyle() Demo for pseudo-elements</p>
<script>
let p = document.getElementById('main');
let style = getComputedStyle(p, ':: rst-letter');
console.log(style.fontSize);
</script>
</body>
</html>

Output:

24px
fi
fi
fi
fi
fi
fi
How it works:
• First, de ne CSS rules for the rst letter of any paragraph element in the head section of
the HTML le.
• Then, use the getComputedStyle() method to pull the computed style of the pseudo-
element. The font-size of the rst letter of the paragraph with the id is 24px.

Summary
• The getComputedStyle() is a method of the window object.
• The getComputedStyle() method returns an object that contains the computed style of
an element.
fi
fi
fi
fi
className property
Summary: in this tutorial, you will learn how to use the JavaScript className property to
manipulate CSS classes of an element.

Introduction to the JavaScript className


The className is the property of an element that returns a space-separated list of CSS
classes of the element as a string:

element.className

Suppose that you have the following ul element:

<ul id="menu" class="vertical main">


<li>Homepage</li>
<li>Services</li>
<li>About</li>
<li>Contact</li>
</ul>

The following shows the classes of the ul element in the console window:

let menu = document.querySelector('#menu');


console.log(menu.className);

Output:

vertical main

To add a new class to an element using the className property, you can concatenate the
existing class name with a new one:

element.className += newClassName;

The += operator concatenates newClassName to the existing class list of the element. Therefore,
you need to pre x the new class name with a space like this:

let menu = document.querySelector('#menu');


menu.className += ' new';
console.log(menu.className);
fi
Output:

'vertical main new'

In practice, you’ll use the classList to add a new class to the existing classes of an element:

let menu = document.querySelector('#menu');


menu.classList.add('new');
console.log(menu.className);

Output:

'vertical main new'

To completely overwrite all the classes of an element, you use a simple assignment operator.
For example:

element.className = "class1 class2";

To get a complete list of classes of an element, you just need to access the className property:

let classes = element.className;

Because the class is a keyword in JavaScript, the name className is used instead of the class.

Also the class is an HTML attribute:

<div id="note" class="info yellow-bg red-text">JS className</div>

while className is a DOM property of the element:

let note = document.querySelector('#note');


console.log(note.className);

Output:

info yellow-bg red-text

An element has another property that helps you better manipulate its CSS classes called classList.

Summary
• className returns a space-separated list of classes of an element as a string.
classList property
Summary: in this tutorial, you will learn how to use the JavaScript classList property to work with
the CSS classes of an element.

Introduction to JavaScript classList property


The classList is a read-only property of an element that returns a live collection of CSS classes:

const classes = element.classList;

The classList is a DOMTokenList object that represents the contents of the element’s class attribute.

Even though the classList is read-only, but you can manipulate the classes it contains using various
methods.

JavaScript classList examples


Let’s take some examples of manipulating CSS classes of the element via the classList‘s interface.

1) Get the CSS classes of an element


Suppose that you have a div element with two classes: main and red.

<div id="content" class="main red">JavaScript classList</div>

The following code displays the class list of the div element in the Console window:

let div = document.querySelector('#content');


for (let cssClass of div.classList) {
console.log(cssClass);
}

Output:

main
red

How it works:
• First, select the div element with the id content using the querySelector() method.
• Then, iterate over the elements of the classList and show the classes in the Console window.
2) Add one or more classes to the class list of an element
To add one or more CSS classes to the class list of an element, you use the add() method of
the classList.
For example, the following code adds the info class to the class list of the div element with
the id content:

let div = document.querySelector('#content');


div.classList.add('info');

The following example adds multiple CSS classes to the class list of an element:

let div = document.querySelector('#content');


div.classList.add('info','visible','block');

3) Remove element’s classes


To remove a CSS class from the class list of an element, you use the remove() method:

let div = document.querySelector('#content');


div.classList.remove('visible');

Like the add() method, you can remove multiple classes once:

let div = document.querySelector('#content');


div.classList.remove('block','red');

4) Replace a class of an element


To replace an existing CSS class with a new one, you use the replace() method:

let div = document.querySelector('#content');


div.classList.replace('info','warning');

5) Check if an element has a speci ed class


To check if the element has a speci ed class, you use the contains() method:

let div = document.querySelector('#content');


div.classList.contains('warning'); // true

The contains() method returns true if the classList contains a speci ed class; otherwise false.
fi
fi
fi
6) Toggle a class
If the class list of an element contains a speci ed class name, the toggle() method removes
it. If the class list doesn’t contain the class name, the toggle() method adds it to the class list.
The following example uses the toggle() method to toggle the visible class of an element with
the id content:

let div = document.querySelector('#content');


div.classList.toggle('visible');

Summary
• The element’s classList property returns the live collection of CSS classes of the element.
• Use add() and remove() to add CSS classes to and remove CSS classes from the class list of
an element.
• Use replace() method to replace an existing class with a new one.
• Use contains() method to check if the class list of an element contains a speci ed class.
• Use the toggle() method to toggle a class.
fi
fi
Width and Height of an Element
Summary: in this tutorial, you will learn how to get the current computed dimension of an
element, including width and height.

The following picture displays the CSS box model that includes a block element with content,
padding, border, and margin:

To get the element’s width and height that include the padding and border, you use
the offsetWidth and offsetHeight properties of the element:

let box = document.querySelector('.box');


let width = box.o setWidth;
let height = box.o setHeight;

The following picture illustrates the offsetWidth and offsetHeight of an element:


ff
ff
See the following example:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Getting the Width and Height of an Element</title>
</head>

<body>
<div class="box" style="width:100px;height:150px;border:solid 1px
#000;padding:10px"></div>
<script>
let box = document.querySelector('.box');
let width = box.o setWidth;
let height = box.o setHeight;
console.log({ width, height });
</script>
</body>

</html>

Output:

{width: 122, height: 172}

In this example:
• The width is 100px
• The border is 1px on each side, so 2px for both
• The padding 10px on each side, so 20px for both
Therefore, the total width 12px. Similarly, the height is 172px.
To get the width & height of an element as oating-point after CSS transformation, you use
the getBoundingClientRect() method of the DOM element. For example:
ff
ff
fl
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Getting the Width and Height of an Element</title>
</head>

<body>
<div class="box" style="width:100px;height:150px;border:solid 1px
#000;padding:10px"></div>
<script>
let box = document.querySelector('.box');
let width = box.o setWidth;
let height = box.o setHeight;
console.log({ width, height });

const domRect = box.getBoundingClientRect();


console.log(domRect);
</script>
</body>

</html>

Output:

{width: 122, height: 172}

DOMRect {x: 7.997685432434082, y: 7.997685432434082, width: 121.95602416992188,


height: 171.95602416992188, top: 7.997685432434082, …}

clientWidth & clientHeight


To get the element’s width and height that include padding but without the border, you use
the clientWidth and clientHeight properties:

let box = document.querySelector('.box');


let width = box.clientWidth;
let height = box.clientHeight;

The following picture illustrates the clientWidth and clientHeight of an element:


ff
ff
To get the margin of an element, you use the getComputedStyle() method:

let box = document.querySelector('.box');


let style = getComputedStyle(box);

let marginLeft = parseInt(style.marginLeft);


let marginRight = parseInt(style.marginRight);
let marginTop = parseInt(style.marginTop);
let marginBottom = parseInt(style.marginBottom);

To get the border width of an element, you use the property of the style object returned by
the getComputedStyle() method:

let box = document.querySelector('.box');


let style = getComputedStyle(box);

let borderTopWidth = parseInt(style.borderTopWidth) || 0;


let borderLeftWidth = parseInt(style.borderLeftWidth) || 0;
let borderBottomWidth = parseInt(style.borderBottomWidth) || 0;
let borderRightWidth = parseInt(style.borderRightWidth) || 0;

To get the height and width of the window, you use the following code:

let width = window.innerWidth || document.documentElement.clientWidth ||


document.body.clientWidth;
let height = window.innerHeight || document.documentElement.clientHeight ||
document.body.clientHeight;

Summary
• Use offsetWidth & offsetHeight properties of the DOM element to get its the width and
height.
Section 7. Working with Events

Events
Summary: in this tutorial, you will learn about the JavaScript events, event models, and how
to handle events.

Introduction to JavaScript events


An event is an action that occurs in the web browser, which the web browser feedbacks to
you so that you can respond to it.
For example, when users click a button on a webpage, you may want to respond to
this click event by displaying a dialog box.
Each event may have an event handler which is a block of code that will execute when the
event occurs.
An event handler is also known as an event listener. It listens to the event and executes
when the event occurs.
Suppose you have a button with the id btn:

<button id="btn">Click Me!</button>

To de ne the code that will be executed when the button is clicked, you need to register an
event handler using the addEventListener() method:

let btn = document.querySelector('#btn');

function display() {
alert('It was clicked!');
}

btn.addEventListener('click',display);

How it works.
• First, select the button with the id btn by using the querySelector() method.
• Then, de ne a function called display() as an event handler.
• Finally, register an event handler using the addEventListener() so that when users click
the button, the display() function will be executed.

fi
fi
A shorter way to register an event handler is to place all code in an anonymous function, like this:

let btn = document.querySelector('#btn');

btn.addEventListener('click',function() {
alert('It was clicked!');
});

Event ow
Assuming that you have the following HTML document:

<!DOCTYPE html>
<html>
<head>
<title>JS Event Demo</title>
</head>
<body>
<div id="container">
<button id='btn'>Click Me!</button>
</div>
</body>

When you click the button, you’re clicking not only the button but also the button’s container,
the div, and the whole webpage.
Event ow explains the order in which events are received on the page from the element
where the event occurs and propagated through the DOM tree.
There are two main event models: event bubbling and event capturing.

Event bubbling
In the event bubbling model, an event starts at the most speci c element and then ows
upward toward the least speci c element (the document or even window).
When you click the button, the click event occurs in the following order:
1. button
2. div with the id container
3. body
4. html
5. document
fl
fl
fi
fi
fl
The click event rst occurs on the button which is the element that was clicked. Then
the click event goes up the DOM tree, ring on each node along its way until it reaches
the document object.
The following picture illustrates the event bubbling effect when users click the button:

Note that modern web browsers bubble the event up to the window object.

Event capturing
In the event capturing model, an event starts at the least speci c element and ows
downward toward the most speci c element.
When you click the button, the click event occurs in the following order:
1. document
2. html
3. body
4. div with the id container
5. button
fi
fi
fi
fi
fl
The following picture illustrates the event capturing effect:

DOM Level 2 Event ow

DOM level 2 events specify that event ow has three phases:


• First, event capturing occurs, which provides the opportunity to intercept the event.
• Then, the actual target receives the event.
• Finally, event bubbling occurs, which allows a nal response to the event.
The following picture illustrates the DOM Level 2 event model when users click the button:
fl
fl
fi
Event object
When the event occurs, the web browser passed an Event object to the event handler:

let btn = document.querySelector('#btn');

btn.addEventListener('click', function(event) {
console.log(event.type);
});

Output:

'click'

The following table shows the most commonly-used properties and methods of the event object:
Property / Method Description
bubbles true if the event bubbles
cancelable true if the default behavior of the event can
be canceled

currentTarget the current element on which the event is ring


defaultPrevented return true if the preventDefault() has been
called.
detail more informatio nabout the event
eventPhase 1 for capturing phase, 2 for target, 3 for bubbling

preventDefault() cancel the default behavior for the event.


This method is only effective if
the cancelable property is true
stopPropagation() cancel any further event capturing or
bubbling. This method only can be used if
the bubbles property is true.
target the target element of the event
type the type of event that was red
fi
fi
Note that the event object is only accessible inside the event handler. Once all the event
handlers have been executed, the event object is automatically destroyed.

preventDefault()
To prevent the default behavior of an event, you use the preventDefault() method.
For example, when you click a link, the browser navigates you to the URL speci ed in
the href attribute:

<a href="https://www.javascripttutorial.net/">JS Tutorial</a>

However, you can prevent this behavior by using the preventDefault() method of the event object:

let link = document.querySelector('a');

link.addEventListener('click',function(event) {
console.log('clicked');
event.preventDefault();
});

Note that the preventDefault() method does not stop the event from bubbling up the DOM. And
an event can be canceled when its cancelable property is true.

stopPropagation()
The stopPropagation() method immediately stops the ow of an event through the DOM tree.
However, it does not stop the browers default behavior.
See the following example:

let btn = document.querySelector('#btn');

btn.addEventListener('click', function(event) {
console.log('The button was clicked!');
event.stopPropagation();
});

document.body.addEventListener('click',function(event) {
console.log('The body was clicked!');
});

Without the stopPropagation() method, you would see two messages on the Console window.
However, the click event never reaches the body because the stopPropagation() was called on
the click event handler of the button.
fl
fi
Summary
• An event is an action that occurs in the web browser e.g., a mouse click.
• Event ow has two main models: event bubbling and event capturing.
• DOM Level 2 Event speci es that the event ow has three phases: event bubbling, the
event occurs at the exact element, and event capturing.
• Use addEventListener() to register an event that connects an event to an event listener
• The event object is accessible only within the event listener.
• Use preventDefault() method to prevent the default behavior of an event, but does not
stop the event ow.
• Use stopPropagation() method to stop the ow of an event through the DOM tree, but
does not cancel the browser default behavior.
fl
fl
fi
fl
fl
Handling Events
Summary: in this tutorial, you will learn the various ways to perform event handling in
JavaScript.

When an event occurs, you can create an event handler which is a piece of code that will
execute to respond to that event. An event handler is also known as an event listener. It
listens to the event and responds accordingly to the event res.
An event listener is a function with an explicit name if it is resuable or an anonymous function
in case it is used one time.
An event can be handled by one or multiple event handlers. If an event has multiple event
handlers, all the event handlers will be executed when the event is red.
There are three ways to assign event handlers.

1) HTML event handler attributes


Event handlers typically have names that begin with on, for example, the event handler for
the click event is onclick.
To assign an event handler to an event associated with an HTML element, you can use an
HTML attribute with the name of the event handler. For example, to execute some code when
a button is clicked, you use the following:

<input type="button" value="Save" onclick="alert('Clicked!')">

In this case, when the button is clicked, the alert box is shown.
When you assign JavaScript code as the value of the onclick attribute, you need to escape
the HTML characters such as ampersand (&), double quotes ("), less than (<), etc., or you
will get a syntax error.
An event handler de ned in the HTML can call a function de ned in a script. For example:

<script>
function showAlert() {
alert('Clicked!');
}
</script>
<input type="button" value="Save" onclick="showAlert()">
fi
fi
fi
fi
In this example, the button calls the showAlert() function when it is clicked.
The showAlert() is a function de ned in a separate <script> element, and could be placed in
an external JavaScript le.

Important notes
The following are some important points when you use the event handlers as attributes of the
HTML element:
First, the code in the event handler can access the event object without explicitly de ning it:

<input type="button" value="Save" onclick="alert(event.type)">

Second, the this value inside the event handler is equivalent to the event’s target element:

<input type="button" value="Save" onclick="alert(this.value)">

Third, the event handler can access the element’s properties, for example:

<input type="button" value="Save" onclick="alert(value)">

Disadvantages of using HTML event handler attributes


Assigning event handlers using HTML event handler attributes are considered as bad
practices and should be avoided as much as possible because of the following reasons:
First, the event handler code is mixed with the HTML code, which will make the code more
dif cult to maintain and extend.
Second, it is a timing issue. If the element is loaded fully before the JavaScript code, users
can start interacting with the element on the webpage which will cause an error.
For example, suppose that the following showAlert() function is de ned in an external
JavaScript le:

<input type="button" value="Save" onclick="showAlert()">

And when the page is loaded fully and the JavaScript has not been loaded, the showAlert() function
is unde ned. If users click the button at this moment, an error will occur.
fi
fi
fi
fi
fi
fi
fi
2) DOM Level 0 event handlers
Each element has event handler properties such as onclick. To assign an event handler, you
set the property to a function as shown in the example:

let btn = document.querySelector('#btn');

btn.onclick = function() {
alert('Clicked!');
};

In this case, the anonymous function becomes the method of the button element. Therefore,
the this value is equivalent to the element. And you can access the element’s properties
inside the event handler:

let btn = document.querySelector('#btn');

btn.onclick = function() {
alert(this.id);
};

Output:

btn

By using the this value inside the event handler, you can access the element’s properties and
methods.
To remove the event handler, you set the value of the event handler property to null:

btn.onclick = null;

The DOM Level 0 event handlers are still being used widely because of its simplicity and
cross-browser support.

3) DOM Level 2 event handlers


DOM Level 2 Event Handlers provide two main methods for dealing with the registering/
deregistering event listeners:
• addEventListener() – register an event handler
• removeEventListener() – remove an event handler
These methods are available in all DOM nodes.
The addEventListener() method
The addEventListener() method accepts three arguments: an event name, an event handler
function, and a Boolean value that instructs the method to call the event handler during the
capture phase (true) or during the bubble phase (false). For example:

let btn = document.querySelector('#btn');


btn.addEventListener('click',function(event) {
alert(event.type); // click
});

It is possible to add multiple event handlers to handle a single event, like this:

let btn = document.querySelector('#btn');


btn.addEventListener('click',function(event) {
alert(event.type); // click
});

btn.addEventListener('click',function(event) {
alert('Clicked!');
});

The removeEventListener() method


The removeEventListener() removes an event listener that was added via the addEventListener().
However, you need to pass the same arguments as were passed to the addEventListener(). For
example:

let btn = document.querySelector('#btn');

// add the event listener


let showAlert = function() {
alert('Clicked!');
};
btn.addEventListener('click', showAlert);

// remove the event listener


btn.removeEventListener('click', showAlert);
Using an anonymous event listener as the following will not work:

let btn = document.querySelector('#btn');


btn.addEventListener('click',function() {
alert('Clicked!');
});

// won't work
btn.removeEventListener('click', function() {
alert('Clicked!');
});

Summary
• There are three ways to assign an event handler: HTML event handler attribute,
element’s event handler property, and addEventListener().
• Assign an event handler via the HTML event handler attribute should be avoided.
Page Load Events
Summary: in this tutorial, you will learn about the events that are related to the page load
including DOMContentLoaded, load, beforeunload, and unload.

Overview of JavaScript page load events


When you open a page, the following events occur in sequence:
• DOMContentLoaded – the browser fully loaded HTML and completed building the
DOM tree. However, it hasn’t loaded external resources like stylesheets and images.
In this event, you can start selecting DOM nodes or initialize the interface.
• load – the browser fully loaded the HTML and also external resources like images and
stylesheets.
When you leave the page, the following events re in sequence:
• beforeunload – res before the page and resources are unloaded. You can use this
event to show a con rmation dialog to con rm if you really want to leave the page. By
doing this, you can prevent data loss in case you are lling out a form and accidentally
click a link to navigate to another page.
• unload – res when the page has completely unloaded. You can use this event to
send the analytic data or to clean up resources.

Handling JavaScript page load events


To handle the page events, you can call the addEventListener() method on the document object:

document.addEventListener('DOMContentLoaded',() => {
// handle DOMContentLoaded event
});

document.addEventListener('load',() => {
// handle load event
});

document.addEventListener('beforeunload',() => {
// handle beforeunload event
});

document.addEventListener('unload',() => {
// handle unload event
});
fi
fi
fi
fi
fi
fi
The following example illustrates how to handle the page load events:

<!DOCTYPE html>
<html>
<head>
<title>JS Page Load Events</title>
</head>

<body>
<script>
addEventListener('DOMContentLoaded', (event) => {
console.log('The DOM is fully loaded.');
});

addEventListener('load', (event) => {


console.log('The page is fully loaded.');
});

addEventListener('beforeunload', (event) => {


// show the con rmation dialog
event.preventDefault();
// Google Chrome requires returnValue to be set.
event.returnValue = '';
});

addEventListener('unload', (event) => {


// send analytic data
});
</script>
</body>
</html>
fi
load event
Summary: in this tutorial, you will learn how to handle the load event that res on the
document, image, and script elements in JavaScript.

The window’s load event


For the window object, the load event is red when the whole webpage (HTML) has loaded
fully, including all dependent resources, including JavaScript les, CSS les, and images.
To handle the load event, you register an event listener using the addEventListener() method:

window.addEventListener('load', (event) => {


console.log('The page has fully loaded');
});

Or use the onload property of the window object:

window.onload = (event) => {


console.log('The page has fully loaded');
};

If you maintain a legacy system, you may nd that the load event handler is registered in of
the body element of the HTML document, like this:

<!DOCTYPE html>
<html>
<head>
<title>JS load Event Demo</title>
</head>
<body onload="console.log('Loaded!')">
</body>
</html>

It’s a good practice to use the addEventListener() method to assign the onload event handler
whenever possible.
fi
fi
fi
fi
fi
The image’s load event
The load event also res on images. To handle the load event on images, you use
the addEventListener() method of the image elements.
The following example uses the load event handler to determine if an image, which exists in
the DOM tree, has been completely loaded:

<!DOCTYPE html>
<html>
<head>
<title>Image load Event Demo</title>
</head>
<body>
<img id="logo">
<script>
let logo = document.querySelector('#logo');

logo.addEventListener('load', (event) => {


console.log('Logo has been loaded!');
});

logo.src = "logo.png";
</script>
</body>
</html>

You can assign an onload event handler directly using the onload attribute of the <img> element, like
this:

<img id="logo"
src="logo.png"
onload="console.log('Logo loaded!')">

If you create an image element dynamically, you can assign an onload event handler before
setting the src property as follows:

window.addEventListener('load' () => {
let logo = document.createElement('img');
// assign and onload event handler
logo.addEventListener('load', (event) => {
console.log('The logo has been loaded');
});
// add logo to the document
document.body.appendChild(logo);
logo.src = 'logo.png';
});
fi
How it works:
• First, create an image element after the document has been fully loaded by placing the
code inside the event handler of the window’s load event.
• Second, assign the onload event handler to the image.
• Third, add the image to the document.
• Finally, assign an image URL to the src attribute. The image will be downloaded to the
element as soon as the src property is set.

The script’s load event


The <script> element also supports the load event slightly different from the standard ways. The
script’s load event allows you to check if a JavaScript le has been completely loaded.

Unlike images, the web browser starts downloading JavaScript les only after the src property has
been assigned and the <script> element has been added to the document.

The following code loads the app.js le after the page has been completely loaded. It assigns
an onload event handler to check if the app.js has been fully loaded.

window.addEventListener('load', checkJSLoaded)

function checkJSLoaded() {
// create the script element
let script = document.createElement('script');

// assign an onload event handler


script.addEventListener('load', (event) => {
console.log('app.js le has been loaded');
});

// load the script le


script.src = 'app.js';
document.body.appendChild(script);
}

Summary
• The load event occurs when the document has been completely loaded, including dependent
resources like JavaScript les, CSS les, and images.
• The <img> and <script> elements also support the load event.
• Use the addEventListener() method to register an onload event handler.
fi
fi
fi
fi
fi
fi
fi
DOMContentLoaded
Summary: in this tutorial, you will learn about the JavaScript DOMContentLoaded event.
The DOMContentLoaded res when the DOM content is loaded, without waiting for images and
stylesheets to nish loading.

You need to handle the DOMContentLoaded event when you place the JavaScript in the head of
the page but referencing elements in the body, for example:

<!DOCTYPE html>
<html>

<head>
<title>JS DOMContentLoaded Event</title>
<script>
let btn = document.getElementById('btn');
btn.addEventListener('click', (e) => {
// handle the click event
console.log('clicked');
});
</script>
</head>

<body>
<button id="btn">Click Me!</button>
</body>

</html>

In this example, we reference the button in the body from the JavaScript in the head.
Because the DOM has not been loaded when the JavaScript engine parses the JavaScript in
the head, the button with the id btn does not exist.
To x this, you place the code inside an DOMContentLoaded event handler, like this:
fi
fi
fi
<!DOCTYPE html>
<html>

<head>
<title>JS DOMContentLoaded Event</title>
<script>
document.addEventListener('DOMContentLoaded', () => {
let btn = document.getElementById('btn');
btn.addEventListener('click', () => {
// handle the click event
console.log('clicked');
});
});
</script>
</head>

<body>
<button id="btn">Click Me!</button>
</body>

</html>

When you place JavaScript in the header, it will cause bottlenecks and rendering delays, so
it’s better to move the script before the </body> tag. In this case, you don’t need to place the
code in the DOMContentLoaded event, like this:

<!DOCTYPE html>
<html>

<head>
<title>JS DOMContentLoaded Event</title>
</head>

<body>
<button id="btn">Click Me!</button>
<script>
document.addEventListener('DOMContentLoaded', () => {
let btn = document.getElementById('btn');
btn.addEventListener('click', () => {
// handle the click event
console.log('clicked');
});
});
</script>
</body>
</html>
Summary
• The DOMContentLoaded event res when the DOM content is loaded, without waiting
for images and stylesheets to nish loading.
• Only handle DOMContentLoaded event if you place the JavaScript code in the head,
which references elements in the body section.

fi
fi
beforeunload Event
Summary: in this tutorial, you will learn about the JavaScript beforeunload event that allows
you to display a con rmation dialog when before you leave a webpage.

Introduction to JavaScript beforeunload event


Before the webpage and its resources are unloaded, the beforeunload event is red. At this
time, the webpage is still visible and you have an opportunity to cancel the event.
To register for the beforeunload event, you use the window.addEventListener() method:

window.addEventListener('beforeunload',(event) =>{
// do something here
});

Since the window is the global object, you can omit it like this:

addEventListener('beforeunload',(event) =>{
// do something here
});

If a webpage has a beforeunload event listener and you are about to leave the page,
the beforeunload event will trigger a con rmation dialog to con rm if you really want to leave
the page.
If you con rm, the browser navigates you to the new page. Otherwise, it cancels the
navigation.
According to the speci cation, you need to call the preventDefault() method inside
the beforeunload event handler in order to show the con rmation dialog. However, not all
browsers implement this:

addEventListener('beforeunload',(event) => {
event.preventDefault();
});

Historically, some browsers allow you to display a custom message on the con rmation
dialog. This was intended to inform the users that they will lose data if they navigate away.
Unfortunately, this feature is often used to scam users. As a result, a custom message is no
longer supported.
fi
fi
fi
fi
fi
fi
fi
fi
Based on the HTML speci cation, the calls to alert(), con rm(), and prompt() are ignored in
the beforeunload event handler.

JavaScript beforeunload event example


The following example attaches an event handler to the beforeunload event. If you click the
link to navigate to another page, the browser will show a con rmation dialog.

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS beforeunload Event</title>
</head>

<body>
<a href="https://www.javascripttutorial.net/">JavaScript Tutorial</a>
<script>
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
// Google Chrome requires returnValue to be set.
event.returnValue = '';
});
</script>
</body>

</html>

Summary
• The beforeunload event is red before the webpage and its resources are about to unload.
• Use beforeunload to con rm if users really want to leave the page to prevent data loss.
fi
fi
fi
fi
fi
unload Event
Summary: in this tutorial, you will learn how to use the JavaScript unload event that res
when the document is fully unloaded.

Note that you should never use the unload event, it’s only for reference.

Introduction to the JavaScript unload event


The unload event res when a document has completely unloaded. Typically, the unload event res
when you navigate from one page to another.

The unload event is red after:

• beforeunload event
• pagehide event
At this moment, the HTML document is in the following state:

• UI is not visible to the users and is not effective.


• All the resources like img, iframe, etc., still exist.
• An error won’t stop the unloading ow.
In practice, you should never use the unload event because it is not reliable on mobile devices
and causes an issue with bfcache.

Handling the JavaScript unload event


To handle the unload event, you can use the addEventListener() method:

addEventListener('unload', (event) => {


console.log('The page is unloaded');
});

Or assign an event handler to the onunload property of the window object:

window.onunload = (event) => {


console.log('The page is unloaded');
};

Or assign an event handler to the onunload attribute of the <body> element:


fi
fi
fl
fi
fi
<!DOCTYPE html>
<html>
<head>
<title>JS unload Event Demo</title>
</head>
<body onunload="console.log('The page is unloaded')">

</body>
</html>

It’s a good practice to use the addEventListener() to register the unload event handler.

Summary
• JavaScript res the unload event when a document has been completely unloaded.
• In practice, do not use the unload event.
fi
Mouse Events
Summary: in this tutorial, you will learn about the basic mouse events and their properties in
JavaScript.

Introduction to JavaScript mouse events


Mouse events re when you use the mouse to interact with the elements on the page. DOM
Level 3 events de ne nine mouse events.

mousedown, mouseup, and click


When you click an element, there are no less than three mouse events re in the following
sequence:
1. The mousedown res when you depress the mouse button on the element.
2. The mouseup res when you release the mouse button on the element.
3. The click res when one mousedown and one mouseup detected on the element.

If you depress the mouse button on an element and move your mouse off the element, and
then release the mouse button. The only mousedown event res on the element.
Likewise, if you depress the mouse button, move the mouse over the element, and release
the mouse button, the only mouseup event res on the element.
In both cases, the click event never res.
fi
fi
fi
fi
fi
fi
fi
fi
fi
dblclick
In practice, you rarely use the dblclick event. The dblclick event res when you double click
over an element.
It takes two click events to cause a dblclick event to re. The dblclick event has four events
red in the following order:
1. mousedown
2. mouseup
3. click
4. mousedown
5. mouseup
6. click
7. dblclick

As you can see, the click events always take place before the dblclick event. If you register
both click and dblclick event handlers on the same element, you will not know exactly what
user actually has clicked or double-clicked the element.
fi
fi
fi
mousemove
The mousemove event res repeatedly when you move the mouse cursor around an element.
Even when you move the mouse one pixel, the mousemove event still res. It will cause the
page slow, therefore, you only register mousemove event handler only when you need it and
immediately remove the event handler as soon as it is no longer used, like this:

element.onmousemove = mouseMoveEventHandler;
// ...
// later, no longer use
element.onmousemove = null;

mouseover / mouseout
The mouseover res when the mouse cursor is outside of the element and then move to inside the
boundaries of the element.

The mouseout res when the mouse cursor is over an element and then moves another element.

mouseenter / mouseleave
The mouseenter res when the mouse cursor is outside of an element and then moves to
inside the boundaries of the element.
The mouseleave res when the mouse cursor is over an element and then moves to the
outside of the element’s boundaries.
Both mouseenter and mouseleave does not bubble and does not re when the mouse cursor
moves over descendant elements.

Registering mouse event handlers


To register a mouse event, you use these steps:
• First, select the element by using querySelector() or getElementById() method.
• Then, register the mouse event using the addEventListener() method.
For example, suppose that you have the following button:

<button id="btn">Click Me!</button>


fi
fi
fi
fi
fi
fi
fi
To register a mouse click event handler, you use the following code:

let btn = document.querySelector('#btn');

btn.addEventListener('click',(event) => {
console.log('clicked');
});

or you can assign a mouse event handler to the element’s property:

let btn = document.querySelector('#btn');

btn.onclick = (event) => {


console.log('clicked');
};

In legacy systems, you may nd that the event handler is assigned in the HTML attribute of
the element:

<button id="btn" onclick="console.log('clicked')">Click Me!</button>

It’s a good practice to always use the addEventListener() to register a mouse event handler.

Detecting mouse buttons


The event object passed to the mouse event handler has a property called button that
indicates which mouse button was pressed on the mouse to trigger the event.
The mouse button is represented by a number:
• 0: the main mouse button is pressed, usually the left button.
• 1: the auxiliary button is pressed, usually the middle button or the wheel button.
• 2: the secondary button is pressed, usually the right button.
• 3: the fourth button is pressed, usually the Browser Back button.
• 4: the fth button is pressed, usually the Browser Forward button.
fi
fi
See the following example:

<!DOCTYPE html>
<html>
<head>
<title>JS Mouse Events - Button Demo</title>
</head>
<body>
<button id="btn">Click me with any mouse button: left, right, middle, ...</button>
<p id="message"></p>
<script>
let btn = document.querySelector('#btn');

// disable context menu when right-mouse clicked


btn.addEventListener('contextmenu', (e) => {
e.preventDefault();
});

// show the mouse event message


btn.addEventListener('mouseup', (e) => {
let msg = document.querySelector('#message');
switch (e.button) {
case 0:
msg.textContent = 'Left mouse button clicked.';
break;
case 1:
msg.textContent = 'Middle mouse button clicked.';
break;
case 2:
msg.textContent = 'Right mouse button clicked.';
break;
default:
msg.textContent = `Unknown mouse button code: ${event.button}`;
}
});
</script>
</body>
</html>

In this example, when you click the button with your mouse (left-click, right-click, and middle-
click), it shows a corresponding message on the <div> element.

Output:

Click me with any mouse button: left,right,middle,…….


Modi er keys
When you click an element, you may press one or more modi er keys: Shift, Ctrl, Alt, and Meta.

Note the Meta key is the Windows key on Windows keyboards and the Command key on the Apple
keyboard.

To detect if these modi er keys have been pressed, you can use the event object passed to the
mouse event handler.

The event object has four Boolean properties, where each is set to true if the key is being held
down or false if the key is not pressed.

See the following example:

<!DOCTYPE html>
<html>
<head>
<title>JS Modi er Keys Demo</title>
</head>
<body>
<button id="btnKeys">Click me with Alt, Shift, Ctrl pressed</button>
<p id="messageKeys"></p>

<script>
let btnKeys = document.querySelector('#btnKeys');

btnKeys.addEventListener('click', (e) => {


let keys = [];

if (e.shiftKey) keys.push('shift');
if (e.ctrlKey) keys.push('ctrl');
if (e.altKey) keys.push('alt');
if (e.metaKey) keys.push('meta');

let msg = document.querySelector('#messageKeys');


msg.textContent = `Keys: ${keys.join('+')}`;
});
</script>
</body>
</html>
fi
fi
fi
fi
Output:

Click me with Alt, Shift, Ctrl pressed

Getting Screen Coordinates


The screenX and screenY properties of the event passed to the mouse event handler return
the screen coordinates of the location of the mouse in relation to the entire screen.

On the other hand, the clientX and clientY properties provide the horizontal and vertical coordinates
within the application’s client area at which the mouse event occurred:
See the following demo:

<!DOCTYPE html>
<html>
<head>
<title>JS Mouse Location Demo</title>
<style>
#track {
background-color: goldenrod;
height: 200px;
width: 400px;
}
</style>
</head>
<body>
<p>Move your mouse to see its location.</p>
<div id="track"></div>
<p id="log"></p>

<script>
let track = document.querySelector('#track');
track.addEventListener('mousemove', (e) => {
let log = document.querySelector('#log');
log.innerText = `
Screen X/Y: (${e.screenX}, ${e.screenY})
Client X/Y: (${e.clientX}, ${e.clientY})`
});
</script>
</body>
</html>

Output:
Move your mouse to see its location.

Screen X/Y: (666, 114)


Client X/Y: (329, 56)
Summary
• DOM Level 3 de nes nine mouse events.
• Use addEventListener() method to register a mouse event handler.
• The event.button indicates which mouse button was pressed to trigger the mouse event.
• The modi er keys: alt, shift, ctrl, and meta (Mac) can be obtained via properties of the
event object passed to the mouse event handler.
• The screenX and screenY properties return the horizontal and vertical coordinates of
the mouse pointer in screen coordinates.
• The clientX and clientY properties of the event object return horizontal and vertical
coordinates within the application’s client area at which the mouse event occurred.
fi
fi
Keyboard Events
Summary: in this tutorial, you will learn how to work with JavaScript keyboard events
including keydown, keypress, and keyup.

Introduction to JavaScript keyboard events


When you interact with the keyboard, the keyboard events are red. There are three main keyboard
events:

• keydown – res when you press a key on the keyboard and res repeatedly while you’re
holding down the key.
• keyup – res when you release a key on the keyboard.
• keypress – res when you press a character keyboard like a,b, or c, not the left arrow key,
home, or end keyboard, … The keypress also res repeatedly while you hold down the key
on the keyboard.
The keyboard events typically re on the text box, though all elements support them.

When you press a character key once on the keyboard, three keyboard events are red in the
following order:

1. keydown

2. keypress

3. keyup

Both keydown and keypress events are red before any change is made to the text box, whereas
the keyup event res after the changes have been made to the text box. If you hold down a
character key, the keydown and keypress are red repeatedly until you release the key.

When you press a non-character key, the keydown event is red rst followed by the keyup event. If
you hold down the non-character key, the keydown is red repeatedly until you release the key.

Handling keyboard events


To handle a keyboard event, you follow these steps:
• First, select the element on which the keyboard event will re. Typically, it is a text box.
• Then, use the element.addEventListener() to register an event handler.
Suppose that you have the following text box with the id message:

<input type="text" id="message">


fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi
The following illustrates how to register keyboard event listeners:

let msg = document.getDocumentById('#message');

msg.addEventListener("keydown", (event) => {


// handle keydown
});

msg.addEventListener("keypress", (event) => {


// handle keypress
});

msg.addEventListener("keyup", (event) => {


// handle keyup
});

If you press a character key, all three event handlers will be called.

The keyboard event properties


The keyboard event has two important properties: key and code. The key property returns the
character that has been pressed whereas the code property returns the physical key code.

For example, if you press the z character key, the event.key returns z and event.code returns KeyZ.

See the following example:

<!DOCTYPE html>
<html>
<head>
<title>JavaScript Keyboard Events: Key/Code</title>
</head>
<body>
<input type="text" id="message">

<script>
let textBox = document.getElementById('message');
textBox.addEventListener('keydown', (event) => {
console.log(`key=${event.key},code=${event.code}`);

});
</script>
</body>
</html>
If you type character z, you will see the following message:

key=z,code=KeyZ

How it works:
• First, select the text box with the id message by using the getElementById() method.
• Then, register a keydown event listener and log the key and code of the key that has
been pressed.

Summary
• When you press a character key on the keyboard, the keydown, keypress,
and keyup events are red sequentially. However, if you press a non-character key, only
the keydown and keyup events are red.
• The keyboard event object has two important properties: key and code properties that
allow you to detect which key has been pressed.
• The key property returns the value of the key pressed while the code represents a
physical key on the keyboard.
fi
fi
Scroll Events
Summary: in this tutorial, you will learn about JavaScript scroll events and how to handle
scroll events properly.

Introduction to the JavaScript scroll events


When you scroll a document or an element, the scroll events re. You can trigger the scroll
events in the following ways, for example:
• Using the scrollbar manually
• Using the mouse wheel
• Clicking an ID link
• Calling functions in JavaScript
To register a scroll event handler, you call the addEventListener() method on the target
element, like this:

targetElement.addEventListener('scroll', (event) => {


// handle the scroll event
});

or assign an event handler to the onscroll property of the target element:

targetElement.onscroll = (event) => {


// handle the scroll event
};

Scrolling the document


Typically, you handle the scroll events on the window object to handle the scroll of the whole
webpage.
The following shows how to attach an event handler to the scroll event of a page:

window.addEventListener('scroll',(event) => {
console.log('Scrolling...');
});

Or you can use the onscroll property on the window object:

window.onscroll = function(event) {
//
};
fi
The onscroll property of the window object is the same as document.body.onscroll and you can
use them interchangeably, for example:

document.body.onscroll = null;
console.log(window.onscroll); // null

Scroll offsets
The window object has two properties related to the scroll events: scrollX and scrollY.
The scrollX and scrollY properties return the number of pixels that the document is currently
scrolled horizontally and vertically. The scrollX and scrollY are double-precision oating-point
values so if you need integer values, you can use the Math.round() to round them off.
The scrollX and scrollY are 0 if the document hasn’t been scrolled at all.
The pageXOffset and pageYOffset are aliases of the scrollX and scrollY properties.

Scrolling an element
Like the window object, you can attach a scroll event handler to any HTML element. However, to
track the scroll offset, you use the scrollTop and scrollLeft instead of the scrollX and scrollY.

The scrollTop property sets or gets the number of pixels that the element’s content is vertically
scrolled. The scrollLeft property gets and sets the number of pixels that an element’s content is
scrolled from its left edge.

The following example shows how to handle the scroll event of the div element with the
id scrollDemo:
fl
<!DOCTYPE html>
<html>
<head>
<title>JS Scroll Events</title>
<style>
#scrollDemo {
height: 200px;
width: 200px;
over ow: auto;
background-color: #f0db4f
}

#scrollDemo p {
/* show the scrollbar */
height: 300px;
width: 300px;
}
</style>
</head>
<body>
<div id="scrollDemo">
<p>JS Scroll Event Demo</p>
</div>

<div id="control">
<button id="btnScrollLeft">Scroll Left</button>
<button id="btnScrollTop">Scroll Top</button>
</div>

<script>
let control = document.querySelector('#control');

control.addEventListener('click', function (e) {


// get the scrollDemo
let div = document.getElementById('scrollDemo');
// get the target
let target = e.target;
// handle each button's click
switch (target.id) {
case 'btnScrollLeft':
div.scrollLeft += 20;
break;

case 'btnScrollTop':
div.scrollTop += 20;
break;
}
});
</script>
</body>
</html>
fl
Output:

Scroll Left Scroll Top

The better ways to handle the scroll events


Many scroll events re while you are scrolling a page or an element. If you attach an event
listener to the scroll event, the code in the event handler needs time to execute.
This will cause an issue which is known as the scroll jank. The scroll jank effect causes a
delay so that the page doesn’t feel anchored to your nger.

Event throttling
It is much better to keep the scroll event handler lightweight and execute it every N milliseconds by
using a timer. So instead of using the following code (and you should never use it):

window.scroll = () => {
// place the scroll handling logic here
};

You should use the following code:

let scrolling = false;

window.scroll = () => {
scrolling = true;
};

setInterval(() => {
if (scrolling) {
scrolling = false;
// place the scroll handling logic here
}
},300);
fi
fi
How it works:
• First, set the scrolling ag to false. If the scroll event res set the scrolling ag
to true inside the scroll event handler.
• Then, execute the scroll event handler using the setInterval() every 300 milliseconds if
the scroll events have been red.
This way of handling the scroll event is called the event throttling that throttles an onscroll‘s
underlying operation every 300 milliseconds. The throttling slows down the rate of execution
of the scroll event handler.

Passive events
Recently, modern web browsers support passive events for the input events
like scroll, touchstart, wheel, etc. It allows the UI thread to handle the event immediately
before passing over control to your custom event handler.
In the web browsers which support the passive events, you need to add the passive ag to
any event listener that does not call preventDefault(), like this:

document.addEventListener(
'scroll',
(event) => {
// handle scroll event
},
{ passive: true }
);

Without the passive option, the code in the event handler will always be invoked before the
UI thread carries out the scrolling.
Check out which browsers are supporting passive events here.

Summary
• The scroll event res when you scroll a webpage or an element.
• For a page, the scrollX and scrollY properties return the number of pixels that the document is
currently scrolled horizontally and vertically.
• For an element, the scrollTop and scrollLeft properties set or get the number of pixels that the
element’s content is vertically scrolled and scrolled from its left edge.
• Use the event throttling technique to better handle the scroll events. In modern web browsers,
you can use passive event listeners.
fi
fl
fi
fi
fl
fl
scrollIntoView
Summary: in this tutorial, you’ll learn how to scroll an element into the view using
its scrollIntoView() method.
Suppose you have a list of elements and you want a speci c element to be highlighted and
scrolled into view.
To achieve this, you can use the element.scrollIntoView() method.
The element.scrollIntoView() accepts a boolean value or an object:

element.scrollIntoView(alignToTop);

or

element.scrollIntoView(options);

The method accepts one of the following two arguments:

alignToTop
The alignToTop is a boolean value.
If it is set to true, the method will align the top of the element to the top of the viewport or the
top of the visible area of the scrollable ancestor.
If the alignToTop is set to false, the method will align the bottom of the element to the bottom
of the viewport or the bottom of the visible area of the scrollable ancestor.
By default, the alignToTop is true.

options
The options argument is an object that gives more control over of alignment of the element in
the view. However, the web browser support may be slightly different.
The options object has the following properties:
• behavior property de nes the transition animation. The behavior property accepts two
values: auto or smooth. It defaults to auto.
• block property de nes the vertical alignment. It accepts one of four
values: start, center, endor nearest. By default, it is start.
• inline property de nes horizontal alignment. It also accepts one of four
values: start, center, endor nearest. It defaults to nearest.
fi
fi
fi
fi
JavaScript scrollIntoView() Example
Suppose that you have an HTML page with a list of the programming language as follows:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS scrollIntoView Demo</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<button class="btn">Scroll Into View</button>
<ul>
<li>C</li>
<li>Java</li>
<li>Python</li>
<li>C++</li>
<li>C#</li>
<li>Go</li>
<li>Visual Basic</li>
<li>JavaScript</li>
<li>PHP</li>
<li>SQL</li>
<li>R</li>
<li>Swift</li>
<li class="special">JavaScript</li>
<li>MATLAB</li>
<li>Assembly language</li>
<li>Ruby</li>
<li>PL/SQL</li>
<li>Classic Visual Basic</li>
<li>Perl</li>
<li>Scratch</li>
<li>Objective-C</li>
</ul>
</div>
<script src="scrollIntoView.js"></script>
</body>
</html>

Without scrolling, the JavaScript list item, which has a class called special, is not in the viewport.
When the button "Scroll Into View" is clicked, the JavaScript list item is scrolled into the view:
let btn = document.querySelector('.btn');
let el = document.querySelector('.special');

btn.addEventListener('click', function () {
el.scrollIntoView(true);
});

How it works:
• First, select the button with the btn class and list item with the special class.
• Then, attach an event listener to the click event of the button.
• Finally, scroll the JavaScript list item into the viewport by calling
the el.scrollIntoView(true) method in the click event handler.
Output:

Scroll Into Vies

Java

Python

C++

C#

GO

Visual Basic

Javascript

PHP

SQL

Swift

Javascript

MATLAB

Assembly language

Ruby

PL/SQL

Classic Visual Basic

Perl

Scratch

Objective-C
Here is the JavaScript scrollIntoView() demo.
To align the JavaScript list item to the bottom of the view, you pass false value to the scrollIntoView() method:

let btn = document.querySelector('.btn');


let el = document.querySelector('.special');

btn.addEventListener('click', function() {
el.scrollIntoView(false);
});

In this tutorial, you have learned how to use the JavaScript scrollIntoView() method to scroll
an element into the viewport.
Focus Events
Summary: in this tutorial, you will learn about the JavaScript focus events that keep track of
the elements that users focus on.

Introduction to JavaScript focus events


The focus events re when an element receives or loses focus. These are the two main
focus events:
• focus res when an element has received focus.
• blur res when an element has lost focus.
The focusin and focusout re at the same time as focus and blur, however, they bubble while
the focus and blur do not.
The following elements are focusable:
• The window gains focus when you bring it forward by using Alt+Tab or clicking on it and
loses focus when you send it back.
• Links when you use a mouse or a keyboard.
• Form elds like input text when you use a keyboard or a mouse.
• Elements with tabindex, also when you use a keyboard or a mouse.

JavaScript focus event examples


The following example shows how to handle the focus and blur events. When you move
focus to the password eld, the background changes to yellow. If you move the mouse to
the username eld, the background changes to white.
fi
fi
fi
fi
fi
fi
fi
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Focus Events</title>
</head>
<body>
<p>Move focus to the password eld to see the e ect:</p>

<form id="form">
<input type="text" placeholder="username">
<input type="password" placeholder="password">
</form>

<script>
const pwd = document.querySelector('input[type="password"]');

pwd.addEventListener('focus', (e) => {


e.target.style.backgroundColor = 'yellow';
});

pwd.addEventListener('blur', (e) => {


e.target.style.backgroundColor = '';
});
</script>
</body>
</html>

Summary
• Use the focus event to handle the state of element when it has or loses the focus.
fi
ff
hashchange Event
Summary: in this tutorial, you will learn about the JavaScript hashchange event and how to
handle it effectively.

Introduction to the JavaScript hashchange event


The URL hash is everything that follows the pound sign (#) in the URL. For example,
suppose that you have the following URL:

https://www.javascripttutorial.net/javascript-dom/javascript-hashchange/#header

The URL hash is header. If the URL hash changes to footer, like this:

https://www.javascripttutorial.net/javascript-dom/javascript-hashchange/#footer

The hashchange event res when the URL hash changes from one to another. In this
example, it changes from #header to #footer.
To attach an event listener to the hashchange event, you call the addEventListener() method
on the window object:

window.addEventListener('hashchange',() =>{
console.log('The URL has has changed');
});

To get the current URL hash, you access the hash property of the location object:

window.addEventListener('hashchange',() => {
console.log(`The current URL hash is ${location.hash}`);
});

Additionally, you can handle the hashchange event by assigning an event listener to
the onhashchange property of the window object:

window.onhashchange = () => {
// handle hashchange event here
};

Summary
• The hashchange event res when the URL hash changed.
• To register an event listener, you call the addEventListener() method or assign an event
listener to the onhashchange property of the window object.
fi
fi
Event Delegation
Summary: in this tutorial, you will learn how to use the JavaScript event delegation that adds
a single event handler to the parent element instead of having to register multiple event
handlers to the child elements.

Introduction to JavaScript Event Delegation


Suppose that you have the following menu:

<ul id="menu">
<li><a id="home">home</a></li>
<li><a id="dashboard">Dashboard</a></li>
<li><a id="report">report</a></li>
</ul>

To handle the click event of each menu item, you may add the corresponding click event handlers:

let home = document.querySelector('#home');


home.addEventListener('home',(event) => {
console.log('Home menu item was clicked');
});

let dashboard = document.querySelector('#dashboard');


dashboard.addEventListener('dashboard',(event) => {
console.log('Dashboard menu item was clicked');
});

let report = document.querySelector('#report');


report.addEventListener('report',(event) => {
console.log('Report menu item was clicked');
});

In JavaScript, if you have a large number of event handlers on a page, these event handlers
will directly impact the performance because of the following reasons:
• First, each event handler is a function which is also an object that takes up memory. The
more objects in the memory, the slower the performance.
• Second, it takes time to assign all the event handlers, which causes a delay in the
interactivity of the page.
To solve this issue, you can leverage the event bubbling.
Instead of having multiple event handlers, you can assign a single event handler to handle all
the click events:
let menu = document.querySelector('#menu');

menu.addEventListener('click', (event) => {


let target = event.target;

switch(target.id) {
case 'home':
console.log('Home menu item was clicked');
break;
case 'dashboard':
console.log('Dashboard menu item was clicked');
break;
case 'report':
console.log('Report menu item was clicked');
break;
}
});

How it works.
• When you click any <a> element inside the <ul> element with the id menu,
the click event bubbles to the parent element which is the <ul> element. So instead of
handling the click event of the individual <a> element, you can capture the click event at
the parent element.
• In the click event listener, you can access the target property which references the
element that dispatches the event. To get the id of the element that the event actually
res, you use the target.id property.
• Once having the id of the element that res the click event, you can have code that
handles the event correspondingly.
The way that we handle the too-many-event-handlers problem is called the event delegation.
The event delegation refers to the technique of levering event bubbling to handle events at a
higher level in the DOM than the element on which the event originated.

JavaScript event delegation bene ts


When it is possible, you can have a single event handler on the document that will handle all
the events of a particular type. By doing this, you gain the following bene ts:
• Less memory usage, better performance.
• Less time required to set up event handlers on the page.
• The document object is available immediately. As long as the element is rendered, it can
start functioning correctly without delay. You don’t need to wait for
the DOMContentLoaded or load events.
fi
fi
fi
fi
Summary
• Having a large number of event handlers will take up memory and degrade the
performance of a page.
• The event delegation technique utilizes the event bubbling to handle event at a higher
level in the DOM than the element on which the event originated.
dispatchEvent
Summary: in this tutorial, you’ll learn how to programmatically create and dispatch events
using Event constructor and dispatchEvent() method.
• Use the speci c event constructor such as MouseEvent and call dispatchEvent() method on
an element to generate an event from code.
• Use event.isTrusted to examine whether the event is generated from code or user actions.

Typically, events are generated by user actions such as mouse clicks and key presses. In
addition, events can be generated from code.
To generate an event programmatically, you follow these steps:
• First, create a new Event object using Event constructor.
• Then, trigger the event using element.dispatchEvent() method.

Event constructor
To create a new event, you use the Event constructor like this:

let event = new Event(type, [,options]);

The Event constructor accepts two parameters:

type
is a string that speci es the event type such as ‘click'.

options
is an object with two optional properties:
• bubbles: is a boolean value that determines if the event bubbles or not. If it is true then
the event is bubbled and vice versa.
• cancelable: is also a boolean value that speci es whether the event is cancelable
when it is true.
By default, the options object is:

{ bubbles: false, cancelable: false}

For example, the following creates a new click event with the default options object:

let clickEvent = new Event('click');


fi
fi
fi
dispatchEvent method
After creating an event, you can re it on a target element using the dispatchEvent() method like this:

element.dispatchEvent(event);

For example, the following code shows how to create the click event and re it on a button:
HTML:

<button class="btn">Test</button>

JavaScript:

let btn = document.querySelector('.btn');

btn.addEventListener('click', function () {
alert('Mouse Clicked');
});

let clickEvent = new Event('click');


btn.dispatchEvent(clickEvent);

Click this link to see the demo.

In this example, the event handler is executed as if the click event were generated by user actions.

If the event comes from the user actions, the event.isTrusted property is set to true. In case the
event is generated by code, the event.isTrusted is false. Therefore, you can examine the value
of event.isTrusted property to check the “authenticity” of the event.

The Event is the base type of UIEvent which is the base type of other speci c event types such
as MouseEvent, TouchEvent, FocusEvent, and KeyboardEvent.

It’s a good practice to use the specialized event constructor like MouseEvent instead of using the
generic Event type because these constructors provide more information speci c to the events.

For example, the MouseEvent event has many other properties such as clientX and clientY that
specify the horizontal and vertical coordinates at which the event occurred relative to the viewport:

let clickEvent = new MouseEvent("click", {


bubbles: true,
cancelable: true,
clientX: 150,
clientY: 150
});

The following link shows the full list of properties of the MouseEvent
fi
fi
fi
fi
Custom Events
Summary: in this tutorial, you will learn about the JavaScript custom events such as creating
a custom event and dispatching it.

Introduction to JavaScript custom events


The following function highlights an element by changing its background color to yellow:

function highlight(elem) {
const bgColor = 'yellow';
elem.style.backgroundColor = bgColor;
}

To execute a piece of code after highlighting the element, you may come up with a callback:

function highlight(elem, callback) {


const bgColor = 'yellow';
elem.style.backgroundColor = bgColor;

if(callback && typeof callback === 'function') {


callback(elem);
}
}
The following calls the highlight() function and adds a border to a <div> element:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS Custom Event Demo</title>
</head>
<body>
<div class="note">JS Custom Event Demo</div>
<script>
function highlight(elem, callback) {
const bgColor = 'yellow';
elem.style.backgroundColor = bgColor;

if (callback && typeof callback === 'function') {


callback(elem);
}
}

let note = document.querySelector('.note');


function addBorder(elem) {
elem.style.border = "solid 1px red";
}

highlight(note, addBorder);
</script>
</body>
</html>

To make the code more exible, you can use the custom event.

Creating JavaScript custom events


To create a custom event, you use the CustomEvent() constructor:

let event = new CustomEvent(eventType, options);

The CustomEvent() has two parameters:


• The eventType is a string that represents the name of the event.
• The options is an object has the detail property that contains any custom information
about the event.
The following example shows how to create a new custom event called highlight:

let event = new CustomEvent('highlight', {


detail: {backgroundColor: 'yellow'}
});
fl
Dispatching JavaScript custom events
After creating a custom event, you need to attach the event to a DOM element and trigger it
by using the dispatchEvent() method:

domElement.dispatchEvent(event);

JavaScript custom event example


Put it all together:

<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Custom Event</title>
</head>
<body>
<div class="note">JS Custom Event</div>
<script>
function highlight(elem) {
const bgColor = 'yellow';
elem.style.backgroundColor = bgColor;

// create the event


let event = new CustomEvent('highlight', {
detail: {
backgroundColor: bgColor
}
});
// dispatch the event
elem.dispatchEvent(event);
}

// Select the div element


let div = document.querySelector('.note');

// Add border style


function addBorder(elem) {
elem.style.border = "solid 1px red";
}

// Listen to the highlight event


div.addEventListener('highlight', function (e) {
addBorder(this);

// examine the background


console.log(e.detail);
});

// highlight div element


highlight(div);
</script>
</body>
</html>
How it works:
• First, declare the highlight() function that highlights an element and triggers the highlight event.
• Second, select the <div> element by using the querySelector() method.
• Third, listen to the highlight event. Inside the event listener, call the addBorder() function and show
the detail property in the Console.
• Finally, call the highlight() function that will trigger the highlight event.

Why using custom events


The custom events allow you to decouple the code that you want to execute after another
piece of code completes. For example, you can separate the event listeners in a separate
script. In addition, you can have multiple event listeners to the same custom event.

Summary
• Use the CustomEvent() constructor to create a custom event and dispatchEvent() to
trigger the event.
MutationObserver
Summary: in this tutorial, you will learn how to use the JavaScript MutationObserver API to
watch for changes being made to the DOM tree.

Introduction to the JavaScript MutationObserver API


The MutationObserver API allows you to monitor for changes being made to the DOM tree.
When the DOM nodes change, you can invoke a callback function to react to the changes.
The basic steps for using the MutationObserver API are:
First, de ne the callback function that will execute when the DOM changes:

function callback(mutations) {
//
}

Second, create a MutationObserver object and pass the callback into the MutationObserver() constructor:

let observer = new MutationObserver(callback);

Third, call the observe() method to start observing the DOM changes.

observer.observe(targetNode, observerOptions);

The observe() method has two parameters. The target is the root of the subtree of nodes to
monitor for changes. The observerOptions parameter contains properties that specify what
DOM changes should be reported to the observer’s callback.
Finally, stop observing the DOM changes by calling the disconnect() method:

observer.disconnect();
fi
The MutationObserver options
The second argument of the observe() method allows you to specify options to describe
the MutationObserver:

let options = {
childList: true,
attributes: true,
characterData: false,
subtree: false,
attributeFilter: ['attr1', 'attr2'],
attributeOldValue: false,
characterDataOldValue: false
};

You don’t need to use all the options. However, to make the MutationObserver works, at least
one of childList, attributes, or characterData needs to be set to true, otherwise
the observer() method will throw an error.

Observing changes to child elements


Assuming that you have the following list:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MutationObserver Demo: ChildList</title>
</head>
<body>
<ul id="language">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>TypeScript</li>
</ul>

<button id="btnStart">Start Observing</button>


<button id="btnStop">Stop Observing</button>
<button id="btnAdd">Add</button>
<button id="btnRemove">Remove the Last Child</button>

<script src="app.js"></script>
</body>
</html>
The following example illustrates how to use the childList property of the mutation options object to
monitor for the child node changes.

First, select the elements like the list and buttons using the querySelector() method. By default,
the Stop Observing button is disabled.

// selecting list
let list = document.querySelector('#language');

// selecting buttons
let btnAdd = document.querySelector('#btnAdd');
let btnRemove = document.querySelector('#btnRemove');
let btnStart = document.querySelector('#btnStart');

let btnStop = document.querySelector('#btnStop');


btnStop.disabled = true;

Second, declare a log() function that will be used as a callback for the MutationObserver:

function log(mutations) {
for (let mutation of mutations) {
if (mutation.type === 'childList') {
console.log(mutation);
}
}
}

Third, create a new MutationObserver object:

let observer = new MutationObserver(log);

Fourth, start observing the DOM changes to the child nodes of the list element when the Start
Observing button is clicked by calling the observe() method with the childList of the options object
is set to true:

btnStart.addEventListener('click', function () {
observer.observe(list, {
childList: true
});

btnStart.disabled = true;
btnStop.disabled = false;
});
Fifth, add a new list item when the add button is clicked:

let counter = 1;
btnAdd.addEventListener('click', function () {
// create a new item element
let item = document.createElement('li');
item.textContent = `Item ${counter++}`;

// append it to the child nodes of list


list.appendChild(item);
});

Sixth, remove the last child of the list when the Remove button is clicked:

btnRemove.addEventListener('click', function () {
list.lastElementChild ?
list.removeChild(list.lastElementChild) :
console.log('No more child node to remove');
});

Finally, stop observing DOM changes when the Stop Observing button is clicked by calling
the disconnect() method of the MutationObserver object:

btnStop.addEventListener('click', function () {
observer.disconnect();
// set button states
btnStart.disabled = false;
btnStop.disabled = true;
});
Put it all together:

(function () {
// selecting the list
let list = document.querySelector('#language');

// selecting the buttons


let btnAdd = document.querySelector('#btnAdd');
let btnRemove = document.querySelector('#btnRemove');
let btnStart = document.querySelector('#btnStart');

// disable the stop button


let btnStop = document.querySelector('#btnStop');
btnStop.disabled = true;

function log(mutations) {
for (let mutation of mutations) {
if (mutation.type === 'childList') {
console.log(mutation);
}
}
}

let observer = new MutationObserver(log);

btnStart.addEventListener('click', function () {
observer.observe(list, {
childList: true
});

btnStart.disabled = true;
btnStop.disabled = false;
});

btnStop.addEventListener('click', function () {
observer.disconnect();

// Set the button state


btnStart.disabled = false;
btnStop.disabled = true;
});

let counter = 1;
btnAdd.addEventListener('click', function () {
// create a new item element
let item = document.createElement('li');
item.textContent = `Item ${counter++}`;

// append it to the child nodes of list


list.appendChild(item);
});

btnRemove.addEventListener('click', function () {
list.lastElementChild ?
list.removeChild(list.lastElementChild) :
console.log('No more child node to remove');
});

})();
Output:
.HTML
.CSS
.Javascript
.Typescript

Start Observing Stop Observing Add Remove

Notice that we placed all code in an IIFE (Immediately Invoked Function Expression).

Observing for changes to attributes


To observe for changes to attributes, you use the following attributes property of the options object:

let options = {
attributes: true
}

If you want to observe the changes to one or more speci c attributes while ignoring the others, you
can use the attributeFilter property:

let options = {
attributes: true,
attributeFilter: ['class', 'style']
}

In this example, the MutationObserver will invoke the callback each time the class or style attribute
changes.

Observing for changes to a subtree


To monitor the target node and its subtree of nodes, you set the subtree property of the options object
to true:

let options = {
subtree: true
}

Observing for changes to character data


To monitor the node for changes to its textual contents, you set the characterData property of
the options object to true:

let options = {
characterData: true
}
fi
Accessing old values
To access the old values of attributes, you set the attributeOldValue property of the options object to true:

let options = {
attributes: true,
attributeOldValue: true
}

Similarly, you can access the old value of character data by setting the characterDataOldValue property of
the options object to true:

let options = {
characterData: true,
subtree: true,
characterDataOldValue: true
}

A practical example of MutationObserver


In JavaScript applications, the elements on the page are typically dynamically generated. To wait
for a dynamic element, you need to use MutationObserver.

The following waitForElement() function waits for one or more elements speci ed by a selector
using MutationObserver.

function waitForElement(selector) {
return new Promise((resolve) => {
if (document.querySelector(selector)) {
return resolve(element);
}
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
resolve(element);
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
});
}
fi
How it works.

The waitForElement() function returns a promise. The promise will be resolved once the element is
available.

First, resolve the element if it is available:

if (document.querySelector(selector)) {
return resolve(element);
}

Second, create a new MutationObserver object to observe the DOM tree if the element is not
available:

const observer = new MutationObserver(() => {


const element = document.querySelector(selector);
if (element) {
resolve(element);
observer.disconnect();
}
});

The observer object will call the resolve() function once the element is available and stop
observing the DOM tree.
Third, observe elements of the whole DOM tree:

observer.observe(document.body, {
childList: true,
subtree: true,
});

Because the waitForElement() returns a Promise, you can use the then() method like this:

waitForElement()('.a-class').then((element) => {
console.log('Element is ready');
console.log(element.textContent);
});

Or you can use await syntax:

const element = await waitForElement()('.a-class');


console.log(element.textContent);

In this tutorial, you have learned about the JavaScript MutationObserver API that monitors the
DOM changes and executes a callback every time the change occurs.
Section 8. Scripting Web Forms

Form
Summary: in this tutorial, you will learn about JavaScript form API: accessing the form,
getting values of the elements, validating form data, and submitting the form.

Form basics
To create a form in HTML, you use the <form> element:

<form action="/signup" method="post" id="signup">


</form>

The <form> element has two important attributes: action and method.
• The action attribute speci es a URL that will process the form submission. In this
example, the action is the /signup URL.
• The method attribute speci es the HTTP method to submit the form with. Usually, the
method is either post or get.
Generally, you use the get method when you want to retrieve data from the server and
the post method when you want to change data on the server.
JavaScript uses the HTMLFormElement object to represent a form.
The HTMLFormElement has the following properties that correspond to the HTML attributes:
• action – is the URL that processes the form data. It is equivalent to the action attribute
of the <form> element.
• method – is the HTTP method which is equivalent to the method attribute of
the <form> element.
The HTMLFormElement element also provides the following useful methods:
• submit() – submit the form.
• reset() – reset the form.

Referencing forms
To reference the <form> element, you can use DOM selecting methods such as getElementById():

const form = document.getElementById('subscribe');


fi
fi
An HTML document can have multiple forms. The document.forms property returns a collection of
forms (HTMLFormControlsCollection) on the document:

document.forms

To reference a form, you use an index. For example, the following statement returns the rst
form of the HTML document:

document.forms[0]

Submitting a form
Typically, a form has a submit button. When you click it, the browser sends the form data to the
server. To create a submit button, you use <input> or <button> element with the type submit:

<input type="submit" value="Subscribe">

Or

<button type="submit">Subscribe</button>

If the submit button has focus and you press the Enter key, the browser also submits the form data.

When you submit the form, the submit event is red before the request is sent to the server. This
gives you a chance to validate the form data. If the form data is invalid, you can stop submitting the
form.

To attach an event listener to the submit event, you use the addEventListener() method of the form
element as follows:

const form = document.getElementById('signup');

form.addEventListener('submit', (event) => {


// handle the form data
});

To stop the form from being submitted, you call the preventDefault() method of the event object inside
the submit event handler like this:

form.addEventListener('submit', (event) => {


// stop form submission
event.preventDefault();
});
fi
fi
Typically, you call the event.preventDefault() method if the form data is invalid. To submit the form in
JavaScript, you call the submit() method of the form object:

form.submit();

Note that the form.submit() does not re the submit event. Therefore, you should always validate the
form before calling this method.

Accessing form elds


To access form elds, you can use DOM methods
like getElementsByName(), getElementById(), querySelector(), etc.

Also, you can use the elements property of the form object. The form.elements property stores a
collection of the form elements.

JavaScript allows you to access an element by index, id, or name. Suppose that you have the
following signup form with two <input> elements:

<form action="signup.html" method="post" id="signup">


<h1>Sign Up</h1>
<div class=" eld">
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter your fullname"
/>
<small></small>
</div>
<div class=" eld">
<label for="email">Email:</label>
<input type="text" id="email" name="email" placeholder="Enter your email
address" />
<small></small>
</div>
<button type="submit">Subscribe</button>
</form>

To access the elements of the form, you get the form element rst:

const form = document.getElementById('signup');

And use index, id, or name to access the element. The following accesses the rst form element:

form.elements[0]; // by index
form.elements['name']; // by name
form.elements['name']; // by id (name & id are the same in this case)
fi
fi
fi
fi
fi
fi
fi
The following accesses the second input element:

form.elements[1]; // by index
form.elements['email']; // by name
form.elements['email']; // by id

After accessing a form eld, you can use the value property to access its value, for example:

const form = document.getElementById('signup');


const name = form.elements['name'];
const email = form.elements['email'];

// getting the element's value


let fullName = name.value;
let emailAddress = email.value;

Put it all together: signup form


The following illustrates the HTML document that has a signup form. See the live demo here.

Output:
Sign Up
Name:

Enter your full name

Please enter your name


Email:

Enter your email address

Please enter your email

Subscribe
fi
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="container">
<form action="signup.html" method="post" id="signup">
<h1>Sign Up</h1>
<div class=" eld">
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter your fullname" />
<small></small>
</div>
<div class=" eld">
<label for="email">Email:</label>
<input type="text" id="email" name="email" placeholder="Enter
your email address" />
<small></small>
</div>
<div class=" eld">
<button type="submit" class="full">Subscribe</button>
</div>
</form>
</div>
<script src="js/app.js"></script>
</body>
</html>

The HTML document references the style.css and app.js les. It uses the <small> element to
display an error message in case the <input> element has invalid data.
Submitting the form without providing any information will result in the following error:
Sign Up
Name:

Enter your full name

Please enter your name


Email:

Enter your email address

Please enter your email

Subscribe
fi
fi
fi
fi
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Form Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="container">
<form action="signup.html" method="post" id="signup">
<h1>Sign Up</h1>
<div class=" eld">
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter
your fullname" />
<small></small>
</div>
<div class=" eld">
<label for="email">Email:</label>
<input type="text" id="email" name="email" placeholder="Enter
your email address" />
<small></small>
</div>
<div class=" eld">
<button type="submit" class="full">Subscribe</button>
</div>
</form>
</div>
<script src="js/app.js"></script>
</body>
</html>

The HTML document references the style.css and app.js les. It uses the <small> element to
display an error message in case the <input> element has invalid data.
Submitting the form without providing any information will result in the following error:
fi
fi
fi
fi
Submitting the form with the name but invalid email address format will result in the following error:
The following shows the complete app.js le:

// show a message with a type of the input


function showMessage(input, message, type) {
// get the small element and set the message
const msg = input.parentNode.querySelector("small");
msg.innerText = message;
// update the class for the input
input.className = type ? "success" : "error";
return type;
}

function showError(input, message) {


return showMessage(input, message, false);
}

function showSuccess(input) {
return showMessage(input, "", true);
}

function hasValue(input, message) {


if (input.value.trim() === "") {
return showError(input, message);
}
return showSuccess(input);
}

function validateEmail(input, requiredMsg, invalidMsg) {


// check if the value is not empty
if (!hasValue(input, requiredMsg)) {
return false;
}
// validate email format
const emailRegex =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-
Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

const email = input.value.trim();


if (!emailRegex.test(email)) {
return showError(input, invalidMsg);
}
return true;
}

const form = document.querySelector("#signup");

const NAME_REQUIRED = "Please enter your name";


const EMAIL_REQUIRED = "Please enter your email";
const EMAIL_INVALID = "Please enter a correct email address format";

form.addEventListener("submit", function (event) {


// stop form submission
event.preventDefault();

// validate the form


let nameValid = hasValue(form.elements["name"], NAME_REQUIRED);
let emailValid = validateEmail(form.elements["email"], EMAIL_REQUIRED, EMAIL_INVALID);
// if valid, submit the form.
if (nameValid && emailValid) {
alert("Demo only. No form was posted.");
}
});
fi
How it works.
The showMessage() function
The showMessage() function accepts an input element, a message, and a type:

// show a message with a type of the input


function showMessage(input, message, type) {
// get the <small> element and set the message
const msg = input.parentNode.querySelector("small");
msg.innerText = message;
// update the class for the input
input.className = type ? "success" : "error";
return type;
}

The following shows the name input eld on the form:

<div class=" eld">


<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter your fullname" />
<small></small>
</div>

If the name’s value is blank, you need to get its parent rst which is the <div> with the class “ eld”.

input.parentNode

Next, you need to select the <small> element:

const msg = input.parentNode.querySelector("small");

Then, update the message:

msg.innerText = message;

After that, we change the CSS class of the input eld based on the value of the type
parameter. If the type is true, we change the class of the input to success. Otherwise, we
change the class to error.

input.className = type ? "success" : "error";

Finally, return the value of the type:

return type;
fi
fi
fi
fi
fi
The showError() and showSuccess() functions
The the showError() and showSuccess() functions call the showMessage() function.
The showError() function always returns false whereas the showSuccess() function always
returns true. Also, the showSuccess() function sets the error message to an empty string.

function showError(input, message) {


return showMessage(input, message, false);
}

function showSuccess(input) {
return showMessage(input, "", true);
}

The hasValue() function


The hasValue() function checks if an input element has a value or not and show an error message
using the showError() or showSuccess() function accordingly:

function hasValue(input, message) {


if (input.value.trim() === "") {
return showError(input, message);
}
return showSuccess(input);
}

The validateEmail() function


The validateEmail() function validates if an email eld contains a valid email address:

function validateEmail(input, requiredMsg, invalidMsg) {


// check if the value is not empty
if (!hasValue(input, requiredMsg)) {
return false;
}
// validate email format
const emailRegex =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]
{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

const email = input.value.trim();


if (!emailRegex.test(email)) {
return showError(input, invalidMsg);
}
return true;
}
fi
The validateEmail() function calls the hasValue() function to check if the eld value is empty.
If the input eld is empty, it shows the requiredMsg.
To validate the email, it uses a regular expression. If the email is invalid,
the validateEmail() function shows the invalidMsg.

The submit event handler


First, select the signup form by its id using the querySelector() method:

const form = document.querySelector("#signup");

Second, de ne some constants to store the error messages:

const NAME_REQUIRED = "Please enter your name";


const EMAIL_REQUIRED = "Please enter your email";
const EMAIL_INVALID = "Please enter a correct email address format";

Third, add the submit event listener of the signup form using the addEventListener() method:

form.addEventListener("submit", function (event) {


// stop form submission
event.preventDefault();

// validate the form


let nameValid = hasValue(form.elements["name"], NAME_REQUIRED);
let emailValid = validateEmail(form.elements["email"], EMAIL_REQUIRED,
EMAIL_INVALID);
// if valid, submit the form.
if (nameValid && emailValid) {
alert("Demo only. No form was posted.");
}
});

In the submit event handler:


1. Stop the form submission by calling the event.preventDefault() method.
2. Validate the name and email elds using the hasValue() and validateEmail() functions.
3. If both name and email are valid, show an alert. In a real-world application, you need to
call the form.submit() method to submit the form.
fi
fi
fi
fi
Summary
• Use the <form> element to create an HTML form.
• Use DOM methods such as getElementById() and querySelector() to select
a <form> element. The document.forms[index] also returns the form element by a
numerical index.
• Use form.elements to access form elements.
• The submit event res when users click the submit button on the form.
fi
Radio Button
Summary: in this tutorial, you will learn how to use JavaScript to check which radio button in
a radio group is checked.

Introduction to the JavaScript Radio Button


Radio buttons allow you to select only one of a prede ned set of mutually exclusive options.
To create a radio button, you use the <input> element with the type radio. A group of radio
buttons is called a radio group.
To form a radio group, you use a common name for all the radio buttons. For example:

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<p>Select your size:</p>
<div>
<input type="radio" name="size" value="XS" id="xs">
<label for="xs">XS</label>
</div>
<div>
<input type="radio" name="size" value="S" id="s">
<label for="s">S</label>
</div>
<div>
<input type="radio" name="size" value="M" id="m">
<label for="m">M</label>
</div>
<div>
<input type="radio" name="size" value="L" id="l">
<label for="l">L</label>
</div>
<div>
<input type="radio" name="size" value="XL" id="xl">
<label for="xl">XL</label>
</div>
<div>
<input type="radio" name="size" value="XXL" id="xxl">
<label for="xxl">XXL</label>
</div>
</body>
</html>

In this example, all the radio buttons have the same name size but different values. Because
of this, you can only select one radio button at a time.
To nd the selected radio button, you follow these steps:
fi
fi
• Select all radio buttons by using a DOM method such as querySelectorAll() method.
• Get the checked property of the radio button. If the checked property is true, the radio
button is checked; otherwise, it is unchecked.
To know which radio button is checked, you use the value attribute. For example:

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<p>Select your size:</p>
<div>
<input type="radio" name="size" value="XS" id="xs">
<label for="xs">XS</label>
</div>
<div>
<input type="radio" name="size" value="S" id="s">
<label for="s">S</label>
</div>
<div>
<input type="radio" name="size" value="M" id="m">
<label for="m">M</label>
</div>
<div>
<input type="radio" name="size" value="L" id="l">
<label for="l">L</label>
</div>
<div>
<input type="radio" name="size" value="XL" id="xl">
<label for="xl">XL</label>
</div>
<div>
<input type="radio" name="size" value="XXL" id="xxl">
<label for="xxl">XXL</label>
</div>
<p>
<button id="btn">Show Selected Value</button>
</p>

<p id="output"></p>

<script>
const btn = document.querySelector('#btn');
const radioButtons = document.querySelectorAll('input[name="size"]');
btn.addEventListener("click", () => {
let selectedSize;
for (const radioButton of radioButtons) {
if (radioButton.checked) {
selectedSize = radioButton.value;
break;
}
}
// show the output:
output.innerText = selectedSize ? `You selected ${selectedSize}` : `You haven't selected any size`;
});
</script>
</body>
</html>
Output:
Select your size:
XS
S
M
L
XL
XLL

Show Selected Value

You selected M

How it works.
First, select the button with #btn id, output element with the #output id, and all the radio buttons
with the name size:

const btn = document.querySelector('#btn');


const output = document.querySelector('#output');

const radioButtons = document.querySelectorAll('input[name="size"]');

Second, register a click event listener on the button element:

btn.addEventListener('click', () => {
});

Third, iterate over the radio buttons and get the value of the selected radio button:

let selectedSize;
for (const radioButton of radioButtons) {
if (radioButton.checked) {
selectedSize = radioButton.value;
break;
}
}
If a radio button is checked, its checked property is true. Then, we assign the value of the selected
radio button to the selectedSize variable.

Since only one radio button in a radio group can be checked at a time, the loop is terminated
immediately by the break statement.

Finally, set the message for the output element:

output.innerText = selectedSize ? `You selected ${selectedSize}` : `You haven't selected any size`;

Radio button’s change event


When you check or uncheck a radio button, it res the change event. To listen to the change
event, you use the addEventListener() method like this:

radioButton.addEventListener('change',function(e){

});

Inside the change event handler, you can access the this keyword to access the radio button.
To check if the radio button is checked, you can use the checked property:

if(this.checked) {
//
}

To get the value of the checked button, you use the value property:

if(this.checked) {
console.log(this.value);
}

It’ll look like this:

radioButton.addEventListener('change', function (e) {


if (this.checked) {
console.log(this.value);
}
});
fi
The following example dynamically generates a radio group and shows the selected value
when a radio button is checked:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Radio Button</title>
</head>

<body>
<p>Select your size:</p>
<div id="group">
</div>

<p id="output"></p>

<script>
const sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];

// generate the radio groups


const group = document.querySelector("#group");
group.innerHTML = sizes.map((size) => `<div>
<input type="radio" name="size" value="${size}" id="${size}">
<label for="${size}">${size}</label>
</div>`).join(' ');

// add an event listener for the change event


const radioButtons = document.querySelectorAll('input[name="size"]');
for(const radioButton of radioButtons){
radioButton.addEventListener('change', showSelected);
}

function showSelected(e) {
console.log(e);
if (this.checked) {
document.querySelector('#output').innerText = `You selected ${this.value}`;
}
}
</script>
</body>

</html>
Output:
Select your size:
XS
S
M
L
XL
XLL

Show Selected Value

How it works.
First, de ne an array of strings that hold the sizes. In practice, you may get these values from
a database in the back-end or from the result of an API call:

const sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];

Second, generate the radio groups from the elements of the sizes array:

const group = document.querySelector('#group');


group.innerHTML = sizes
.map(
(size) => `<div>
<input type="radio" name="size" value="${size}" id="${size}">
<label for="${size}">${size}</label>
</div>`
)
.join(' ');

In this code:
1) Select the element with id #group.
2) Generate a radio group using the map() method with template literals; each array element
is corresponding to a radio button HTML.
3) Join radio button HTML strings into an HTML string using the join() method.
4) Assign the HTML to the innerHTML of the output element.
fi
Third, select all the radio buttons with the name size and add the change event listener:

const radioButtons = document.querySelectorAll('input[name="size"]');


for (const radioButton of radioButtons) {
radioButton.addEventListener('change', showSelected);
}

Finally, de ne the change event handler:

function showSelected(e) {
if (this.checked) {
document.querySelector('#output').innerText = `You selected ${this.value}`;
}
}

Summary
• Use the <input> element with the type radio to create a radio button.
• Assign a name to multiple radio buttons to form a radio group. Only one radio button in
the group can be selected.
• If the radio button is selected, its checked property is true.
fi
Checkbox
Summary: in this tutorial, you will learn how to use JavaScript to test if a checkbox is
checked, get the values of selected checkboxes, and select/unselect all checkboxes.

Creating an HTML checkbox


To create a checkbox, you use the <input> element with the type of checkbox as follows:

<input type="checkbox" id="accept"> Accept

It’s a good practice to always associate a checkbox with a label to improve usability and
accessibility. By doing this, clicking the label also checks or unchecks the checkbox.

<label for="accept">
<input type="checkbox" id="accept" name="accept" value="yes"> Accept
</label>

Or:

<input type="checkbox" id="accept" name="accept" value="yes">


<label for="accept"> Accept </label>

Note that the for attribute’s value of the label must match the id of the checkbox.
The following works but is bad practice so you should avoid it:

<input type="checkbox" id="accept" name="accept" value="yes"> Accept

Checking if a checkbox is checked


A checkbox has two states: checked and unchecked.
To get the state of a checkbox, you follow these steps:
• First, select the checkbox using a DOM method such as getElementById() or querySelector().
• Then, access the checked property of the checkbox element. If its checked property is true,
then the checkbox is checked; otherwise, it is not.
See the following example:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Checkbox</title>
</head>
<body>
<label for="accept">
<input type="checkbox" id="accept" name="accept" value="yes"> Accept
</label>

<script>
const cb = document.querySelector('#accept');
console.log(cb.checked); // false
</script>

</body>

</html>

In this example:
First, create the HTML checkbox element:

<label for="accept">
<input type="checkbox" id="accept" name="accept" value="yes"> Accept
</label>

Second, select the checkbox with id #accept and examine the checked property:

const cb = document.querySelector('#accept');
console.log(cb.checked);

Because the checkbox is unchecked, you’ll see false in the console:

false
Consider another example:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Checkbox</title>
</head>

<body>
<label for="accept">
<input type="checkbox" id="accept" name="accept" value="yes"> Accept
</label>

<script>
const checked = document.querySelector('#accept:checked') !== null;
console.log(checked); // false
</script>

</body>
</html>

In this example, the selector #accept:checked selects the element with the id #accept and has
the attribute checked. For example, it matches the following element:

<input type="checkbox" id="accept" checked> Accept

But not this one:

<input type="checkbox" id="accept"> Accept

Therefore, if the checkbox element with the id #accept is checked, the document.querySelector() will
return it. On the console window, you’ll see the value false because the checkbox is unchecked:

false
Getting checkbox values
The following page shows a checkbox and a button. When you click the button, you’ll see the
checkbox’s value on the console window:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Checkbox</title>
</head>

<body>
<label for="accept">
<input type="checkbox" id="accept" name="accept"> Accept
</label>

<button id="btn">Submit</button>
<script>
const cb = document.querySelector('#accept');
const btn = document.querySelector('#btn');
btn.onclick = () => {
alert(cb.value);
};
</script>
</body>

</html>

When you get the value attribute of a checkbox, you always get the 'on' string whether the checkbox
is checked or not.

Output:
Accept
Submit
Getting values of multiple selected checkboxes
The following page shows three checkboxes. If you select one or more checkboxes and click
the button, it’ll show the values of the selected checkbox:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Checkboxes</title>
</head>

<body>
<p>Select your favorite colors:</p>
<label for="c1"> <input type="checkbox" name="color" value="red" id="c1">Red</
label>
<label for="c2"><input type="checkbox" name="color" value="green" id="c2">
Green</label>
<label for="c3"><input type="checkbox" name="color" value="blue" id="c3">Blue</
label>
<p>
<button id="btn">Get Selected Colors</button>
</p>

<script>
const btn = document.querySelector('#btn');
btn.addEventListener('click', (event) => {
let checkboxes = document.querySelectorAll('input[name="color"]:checked');
let values = [];
checkboxes.forEach((checkbox) => {
values.push(checkbox.value);
});
alert(values);
});
</script>

</body>

</html>

How it works.
In the HTML, we create three checkbox elements with the same name (color) but distinct values:

<label for="c1"><input type="checkbox" name="color" value="red" id="c1">Red</label>


<label for="c2"><input type="checkbox" name="color" value="green" id="c2">Green</label>
<label for="c3"><input type="checkbox" name="color" value="blue" id="c3">Blue</label>
In the JavaScript:
First, add the click event handler to the button:

const btn = document.querySelector('#btn');


btn.addEventListener('click', (event) => {
// ...
});

Second, select the selected checkboxes using the document.querySelectorAll() method inside the
click event handler:

let checkboxes = document.querySelectorAll('input[name="color"]:checked');

Third, push the values of the selected checkboxes to an array:

let values = [];


checkboxes.forEach((checkbox) => {
values.push(checkbox.value);
});

alert(values);

Demo:
Output:
Select your favourite colours:

Red Green Blue

Get Selected Colors


Check / Uncheck all checkboxes
The following page has three checkboxes and a button. When you click the button, if the
checkboxes are checked, they will be unchecked and vise versa:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Check/uncheck checkboxes</title>
</head>
<body>
<p>
<button id="btn">Check / Uncheck All</button>
</p>
<label for="c1"><input type="checkbox" name="color" value="red" id="c1"> Red</
label>
<label for="c2"><input type="checkbox" name="color" value="green" id="c2">
Green</label>
<label for="c3"> <input type="checkbox" name="color" value="blue" id="c3">Blue</
label>

<script>
function check(checked = true) {
const checkboxes = document.querySelectorAll('input[name="color"]');
checkboxes.forEach((checkbox) => {
checkbox.checked = checked;
});
}

function checkAll() {
select();
this.onclick = uncheckAll;
}

function uncheckAll() {
select(false);
this.onclick = checkAll;
}

const btn = document.querySelector('#btn');


btn.onclick = checkAll;
</script>

</body>
</html>
How it works:
First, de ne the check() function that checks or unchecks all checkboxes with the name "color":

function check(checked = true) {


const checkboxes = document.querySelectorAll('input[name="color"]');
checkboxes.forEach((checkbox) => {
checkbox.checked = checked;
});
}

When you click the button, it checked all the checkboxes. And. If you click the button again, it
should uncheck all the checkboxes. To do this switch, you need to reassign the click event
handler whenever the click event res.
Second, select the #btn button and assign the checkAll() function to the onclick property of
the button:

const btn = document.querySelector('#btn');


btn.onclick = checkAll;

Third, de ne the checkAll() function that checks all the checkboxes:

function checkAll() {
check();
this.onclick = uncheckAll;
}

Finally, de ne the uncheckAll() function that unchecks all the checkboxes:

function uncheckAll() {
check(false);
this.onclick = checkAll;
}

Demo:
Output:

Check/Uncheck All

Red Green Blue


fi
fi
fi
fi
Creating checkboxes dynamically
The following example shows how to create checkboxes dynamically using JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Checkboxes</title>
</head>
<body>
<div id="root"></div>
<script>
const colors = ["Red","Green","Blue"];
colors.forEach((color)=>{
// generate id
const id = `color-${color}`;

// create a label
const label = document.createElement('label');
label.setAttribute("for", id);

// create a checkbox
const checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.name = "color";
checkbox.value = color;
checkbox.id = id;

// place the checkbox inside a label


label.appendChild(checkbox);
// create text node
label.appendChild(document.createTextNode(color));
// add the label to the root
document.querySelector("#root").appendChild(label);
});
</script>
</body>
</html>

Output:

<div class="output-cont"><div class="output">


<iframe height="250px" src="https://www.javascripttutorial.net/sample/dom/checkbox/
checkbox-dynamic.html"></iframe>
</div></div>
How it works.
First, de ne an array that consists of three strings. In practice, you may have the array that
comes from the result of an API call:

const colors = ["Red","Green","Blue"];

Second, iterate over the array elements and:


1) Generate a unique id for each checkbox:

const id = `color-${color}`;

2) Create a label and assign the id to the for attribute:

const label = document.createElement('label');


label.setAttribute("for", id);

3) Create a checkbox:

const checkbox = document.createElement('input');


checkbox.type = "checkbox";
checkbox.name = "color";
checkbox.value = color;
checkbox.id = id;

4) Place the checkbox inside the label:

label.appendChild(checkbox);

5) Create a text node and append it to the label:

label.appendChild(document.createTextNode(color));

6) Add the label to the root element:

document.querySelector("#root").appendChild(label);
fi
The following example also dynamically generates checkboxes like the above example:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Checkboxes</title>
</head>
<body>
<div id="root"></div>
<script>
const colors = ["Red","Green","Blue"];
const html = colors.map(color => `<label for="color-${color}">
<input type="checkbox" name="color" id="color-${color}" value="${color}"> $
{color}
</label>`
).join(' ');
document.querySelector("#root").innerHTML = html;
</script>
</body>
</html>

In this example:
• First, generate a label and checkbox element using the Array map() method
and template literals.
• Second, join the HTML strings into a single HTML using the String join() method.
• Third, append the HTML to the #root element.

Summary
• Use the <input> element with the type checkbox to create a checkbox element.
• Place a checkbox inside a label element to improve the usablity and accessibility.
• Use checkbox.checked property or :check selector to test if a checkbox is checked.
• Get the value attribute to get the value of a checkbox.
select Element
Summary: in this tutorial, you will learn how to handle the <select> element in JavaScript.

Introduction to the HTML select elements


A <select> element provides you with a list of options. A <select> element allows you to select one
or multiple options.

To create a <select> element, you use the <select> and <option> elements. For example:

<select id="framework">
<option value="1">Angular</option>
<option value="2">React</option>
<option value="3">Vue.js</option>
<option value="4">Ember.js</option>
</select>

Output:

Angular 🔽

The above <select> element allows you to select a single option at a time.
To enable multiple selections, you add multiple attribute to <select> element as follows:

<select id="framework" multiple>


<option value="1">Angular</option>
<option value="2">React</option>
<option value="3">Vue.js</option>
<option value="4">Ember.js</option>
</select>

Output

Angular
React
Vue.Js
Ember.Js
The HTMLSelectElement type
To interact with <select> element in JavaScript, you use the HTMLSelectElement type.
The HTMLSelectElement type has the following useful properties:
• selectedIndex – returns the zero-based index of the selected option.
The selectedIndex is -1 if no option is selected. If the <select> element allows multiple
selections, the selectedIndex returns the value of the rst option.
• value – returns the value property of the rst selected option element if there is one.
Otherwise, it returns an empty string.
• multiple – returns true if the <select> element allows multiple selections. It is
equivalent to the multiple attribute.

The selectedIndex property


To select a <select> element, you use the DOM API like getElementById() or querySelector().
The following example illustrates how to get the index of the selected option:

<!DOCTYPE html>
<html>
<head>
<title>JavaScript Select Element Demo</title>
<link href="css/selectbox.css" rel="stylesheet">
</head>
<body>
<form>
<label for="framework">Select a JS Framework</label>
<select id="framework">
<option value="1">Angular</option>
<option value="2">React</option>
<option value="3">Vue.js</option>
<option value="4">Ember.js</option>
</select>
<button id="btn">Get the Selected Index</button>
</form>
<script>
const btn = document.querySelector('#btn');
const sb = document.querySelector('#framework')
btn.onclick = (event) => {
event.preventDefault();
// show the selected index
alert(sb.selectedIndex);
};
</script>
</body>
</html>
fi
fi
Output:
Select a JS Framework

Angular 🔽

Get the Selected Index

How it works:

• First, select the <button> and <select> elements using the querySelector() method.
• Then, attach a click event listener to the button and show the selected index using
the alert() method when the button is clicked.
The value property
The value property of the <select> element depends on the <option> element and its
HTML multiple attribute:
• If no option is selected, the value property of the select box is an empty string.
• If an option is selected and has a value attribute, the value property of the select
box is the value of the selected option.
• If an option is selected and has no value attribute, the value property of the select
box is the text of the selected option.
• If multiple options are selected, the value property of the select box is derived from
the rst selected option based on the previous two rules.
fi
See the following example:

<!DOCTYPE html>
<html>
<head>
<title>JavaScript Selected Value</title>
<link href="css/selectbox.css" rel="stylesheet">
</head>
<body>
<div id="container">
<form>
<label for="framework">Select a JS Framework:</label>
<select id="framework">
<option value="">Angular</option>
<option value="1">React</option>
<option value="2">Vue.js</option>
<option>Ember.js</option>
</select>
<button id="btn">Get the Selected Value</button>
</form>
</div>
<script>
const btn = document.querySelector('#btn');
const sb = document.querySelector('#framework')
btn.onclick = (event) => {
event.preventDefault();
alert(sb.value);
};
</script>
</body>
</html>

Output:
Select a JS Framework:

Angular 🔽

Get the Selected Value

In this example:
• If you select the rst option, the value property of the <select> is empty.
• If you select the last option, the value property of the select box is Ember.js because the selected
option has no value attribute.
• If you select the second or third option, the value property will be "1"or "2".
fi
The HTMLOptionElement type
In JavaScript, the HTMLOptionElement type represents the <option> element.

The HTMLOptionElement type has the following handy properties:

• index – the index of the option inside the collection of options.


• selected – returns true when the option is selected. You set this property to true to select an
option.
• text – returns the option’s text.
• value – returns the HTML value attribute.
The <select> element has the options property that allows you to access the collection options:

selectBox.options

For example, to access the text and value of the second option, you use the following:

const text = selectBox.options[1].text;


const value = selectBox.options[1].value;

To get the selected option of a <select> element with a single selection, you use the following code:

let selectedOption = selectBox.options[selectBox.selectedIndex];

Then you can access the text and value of the selected option via text and value properties:

const selectedText = selectedOption.text;


const selectedValue = selectedOption.value;

When a <select> element allows multiple selections, you can use the selected property to
determine which options are selected:
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Select Box</title>
<link rel="stylesheet" href="css/selectbox.css">
</head>
<body>
<div id="container">
<form>
<label for="framework">Select one or more JS Frameworks:</label>
<select id="framework" multiple>
<option value="1">Angular</option>
<option value="2">React</option>
<option value="3">Vue.js</option>
<option value="4">Ember.js</option>
</select>
<button id="btn">Get Selected Frameworks</button>
</form>
</div>
<script>
const btn = document.querySelector('#btn');
const sb = document.querySelector('#framework');

btn.onclick = (e) => {


e.preventDefault();
const selectedValues = []. lter
.call(sb.options, option => option.selected)
.map(option => option.text);
alert(selectedValues);
};
</script>
</body>
</html>

Output:
Select one or more Js Frameworks:
Angular
React
Vue.js
Ember.js

Get Selected Framworks

In this example, the sb.options is an array-like object, so it doesn’t have the lter() methods
like an Array object.
fi
fi
To borrow these methods from the Array object, you use the call() method. For example, the
following returns an array of selected options:

[]. lter.call(sb.options, option => option.selected)

And to get the text property of the options, you chain the result of the lter() method with
the map() method, like this:

.map(option => option.text);

Summary
• The <select> element allows you to select one or multiple options. Add the multiple attribute to
the <select> element to enable multiple selections.
• The HTMLSelectElement represents the <select> element. Use
the selectedIndex and value to get the index and value of the selected option.
• The HTMLOptionElement represents the <option> element. If the option is selected,
the selected property is true. The selectedText and selectedValue properties return
the text and value of the selected option.
fi
fi
Add & Remove Options
Summary: in this tutorial, you will learn how to dynamically add options to and remove
options from a select element in JavaScript.
The HTMLSelectElement type represents the <select> element. It has the add() method that
dynamically adds an option to the <select> element and the remove() method that removes
an option from the <select> element:
• add(option,existingOption) – adds a new <option> element to the <select> before an
existing option.
• remove(index) – removes an option speci ed by the index from a <select>.

Adding options
To add an option dynamically to a <select> element, you use these steps:

• First, create a new option.


• Second, add the option to the select element.
There are multiple ways to create an option dynamically and add it to a <select> in JavaScript.

1) Using the Option constructor and add() method


First, use the Option constructor to create a new option with the speci ed option text and value:

let newOption = new Option('Option Text','Option Value');

Then, call the add() method of the HTMLSelectElement element:

const select = document.querySelector('select');


select.add(newOption,unde ned);

The add() method accepts two arguments. The rst argument is the new option and the second one
is an existing option.

In this example, we pass unde ned in the second argument, the method add() method will add the
new option to the end of the options list.
fi
fi
fi
fi
fi
2) Using the DOM methods
First, construct a new option using DOM methods:

// create option using DOM


const newOption = document.createElement('option');
const optionText = document.createTextNode('Option Text');
// set option text
newOption.appendChild(optionText);
// and option value
newOption.setAttribute('value','Option Value');

Second, add the new option to the select element using the appendChild() method:

const select = document.querySelector('select');


select.appendChild(newOption);

Removing Options
There are also multiple ways to dynamically remove options from a select element.
The rst way is to use the remove() method of the HTMLSelectElement type. The following
illustrates how to remove the rst option:

select.remove(0);

The second way to remove an option is to reference the option by its index using
the options collection and set its value to null:

select.options[0] = null;

The third way is to use the removeChild() method and remove a speci ed option. The following code
removes the rst element of a the selectBox:

// remove the rst element:


select.removeChild(selectBox.options[0]);

To remove all options of a select element, you use the following code:

function removeAll(selectBox) {
while (selectBox.options.length > 0) {
select.remove(0);
}
}
fi
fi
fi
fi
fi
When you remove the rst option, the select element moves another option as the rst option.
The removeAll() function repeatedly removes the rst option in the select element, therefore, it
removes all the options.

Put it all together


We’ll build a application that allows users to add a new option from the value of an input text
and remove one or more selected options.
Here’s the project’s structure:

├── css
| └── style.css
├── js
| └── app.js
└── index.html

The index.html:

<!DOCTYPE html>
<html>

<head>
<title>JavaScript Selected Value</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div id="container">
<form>
<label for="framework">Framework:</label>
<input type="text" id="framework" placeholder="Enter a framework"
autocomplete="o ">

<button id="btnAdd">Add</button>

<label for="list">Framework List:</label>


<select id="list" name="list" multiple>

</select>
<button id="btnRemove">Remove Selected Framework</button>
</form>
</div>
<script src="js/app.js"></script>
</body>

</html>
ff
fi
fi
fi
js/app.js

const btnAdd = document.querySelector('#btnAdd');


const btnRemove = document.querySelector('#btnRemove');
const listbox = document.querySelector('#list');
const framework = document.querySelector('#framework');

btnAdd.onclick = (e) => {


e.preventDefault();

// validate the option


if (framework.value == '') {
alert('Please enter the name.');
return;
}
// create a new option
const option = new Option(framework.value, framework.value);
// add it to the list
listbox.add(option, unde ned);

// reset the value of the input


framework.value = '';
framework.focus();
};

// remove selected option


btnRemove.onclick = (e) => {
e.preventDefault();

// save the selected options


let selected = [];

for (let i = 0; i < listbox.options.length; i++) {


selected[i] = listbox.options[i].selected;
}

// remove all selected option


let index = listbox.options.length;
while (index--) {
if (selected[index]) {
listbox.remove(index);
}
}
};

The style can be found here.


fi
Output:
Framework:

Enter a framework

Add

Framework List:

Remove Selected Framework

How it works:
First, use the querySelector() method to select elements including the input text, button, and
selection box:

const btnAdd = document.querySelector('#btnAdd');


const btnRemove = document.querySelector('#btnRemove');
const listbox = document.querySelector('#list');
const framework = document.querySelector('#framework');

Second, attach the click event listener to the btnAdd button.


If the value of the input text is blank, we show an alert to inform the users that the name is
required. Otherwise, we create a new option and add it to the selection box. After adding the
option, we reset the entered text of the input text and set the focus to it.
btnAdd.addEventListener('click', (e) => {
e.preventDefault();

// validate the option


if (framework.value.trim() === '') {
alert('Please enter the name.');
return;
}
// create a new option
const option = new Option(framework.value, framework.value);

// add it to the list


listbox.add(option, unde ned);

// reset the value of the input


framework.value = '';
framework.focus();
});

Third, register a click event listener to the btnRemove button. In the event listener, we save
the selected options in an array and remove each of them.

btnRemove.addEventListener('click', (e) => {


e.preventDefault();

// save the selected options


let selected = [];

for (let i = 0; i < listbox.options.length; i++) {


selected[i] = listbox.options[i].selected;
}

// remove all selected option


let index = listbox.options.length;
while (index--) {
if (selected[index]) {
listbox.remove(index);
}
}
});

Summary
• JavaScript uses the HTMLSelectElement type to represent the <select> element.
• Use the add() method of the HTMLSelectElement to add an option to the <select> element.
• Use the remove() method of the HTMLSelectElement to remove an option from
the <select> element.
fi
Removing Items from a Select Element Conditionally
Summary: in this tutorial, you’ll learn how to use JavaScript to remove items from a select element
based on a condition.

JavaScript uses the HTMLSelectElement class to represent the <select> element. To remove an option
from a select element, you use the remove() method of the HTMLSelectElement object.

Suppose the <select> element has three <option> elements with the corresponding index 0, 1, and 2:

For example:

Value Text Index


A Item A 0
B Item B 1
C Item C 2

When you call the remove() method to remove one element, the index will change immediately.

For example, if you remove the second element (B) with index 1, the index of the third element (C)
will become 1:

Value Text Index


A Item A 0
B Item C 1

A common mistake is to iterate over the options of a <select> element and remove the
element inside the loop without being aware that the indices have been adjusted.
For example, the following attempts to remove items with the values B and C. However, it
only removes the item B but not C.

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<label for="list">Alphabet</label>
<select id="list">
<option value="A">Item A</option>
<option value="B">Item B</option>
<option value="C">Item C</option>
</select>
<script>
const select = document.querySelector('#list')
for (let i = 0; i < select.options.length; i++) {
const value = select.options[i].value;
if (value === 'B' || value === 'C') {
select.remove(i);
// index of C will become 1 but the value of i is 2
// therefore C will be not removed
}
}
</script>
</body>
</html>
Output:
Alphabet Item A 🔽

To remove item C, you need to decrease the index after removing item B. The following
example will work properly:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo</title>
</head>

<body>
<label for="list">Alphabet</label>
<select id="list">
<option value="A">Item A</option>
<option value="B">Item B</option>
<option value="C">Item C</option>
</select>
<script>
const select = document.querySelector('#list')
let indices = []
for (let i = 0; i < select.options.length; i++) {
const value = select.options[i].value;
if (value === 'B' || value === 'C') {
select.remove(i);
// decrease i by one because the index has been
// adjusted
i--
}
}
</script>
</body>

</html>

Output:
Alphabet Item A 🔽
A practical example
The following example illustrates how to delete items from a list where the item text ends with
the string js.
Here’s the project structure:

├── css
| └── style.css
├── js
| └── app.js
└── index.html

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<title>Demo</title>
</head>
<body>
<main>
<label for="framework">Framework:</label>
<select id="framework" multiple>
<option value="1">Angular</option>
<option value="2">React</option>
<option value="3">Vue.js</option>
<option value="4">Ember.js</option>
<option value="5">Svelte</option>
<option value="6">Next.js</option>
</select>
<p>Click the Remove button to remove framework ended with js like Vue.js</p>
<button class="btn">Remove</button>
</main>
<script src="js/app.js"></script>
</body>
</html>
app.js

const select = document.querySelector('#framework');


const btn = document.querySelector('.btn');

btn.addEventListener('click', () => {
for (let i = 0; i < select.options.length; i++) {
const text = select.options[i].text;
if (text.endsWith('js')) {
select.remove(i);
i--;
}
}
});

Output:

Framework:

Angular
React
Svelte

Click the Remove button to remove framework ended


with js like Vue.js

Remove
Handling change event
The change event occurs when the element has completed changing.
To attach an event handler to the change event of an element, you can either call
the addEventListener() method:

element.addEventListener('change', function(){
// handle change
});

or use the onchange attribute of the element. For example:

<input type="text" onchange="changeHandler()">

However, it is a good practice to use the addEventListener() method.

Using JavaScript change event for input elements


The change event of an <input> element res when the <input> element loses focus. The change event
does not re when you’re tying.

The following example shows the value of the input text when it loses focus.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript change Event for Input Element</title>
</head>
<body>
<label for="message">Message:</label>
<input type="text" class="input" id="message" name="message">
<button>Submit</button>
<p id="result"></p>
<script>
let input = document.querySelector('.input');
let result = document.querySelector('#result');
input.addEventListener('change', function () {
result.textContent = this.value;
});
</script>
</body>
</html>

Output:
Submit
fi
fi
Message:

In this example, if you type some text on the <input> element and move focus to the button,
the change event res to show the entered text.

Note that if you want to handle every change of the value, you use the input event instead.

Using JavaScript change event for radio buttons


A radio button res the change event after you select it.
The following example shows how to handle the change event of the radio buttons:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript change Event for Radio Buttons</title>
</head>
<body>
<span>Status:</span>
<input type="radio" id="pending" name="status">
<label for="pending">Pending</label>
<input type="radio" id="resolved" name="status">
<label for="resolved">Resolved</label>
<input type="radio" id="rejected" name="status">
<label for="rejected">Rejected</label>
<p id="result"></p>

<script>
let result = document.querySelector('#result');
document.body.addEventListener('change', function (e) {
let target = e.target;
let message;
switch (target.id) {
case 'pending':
message = 'The Pending radio button changed';
break;
case 'resolved':
message = 'The Resolved radio button changed';
break;
case 'rejected':
message = 'The Rejected radio button changed';
break;
}
result.textContent = message;
});
</script>
</body>
</html>
fi
fi
Output:
Status: Pending Resolved Rejected

How it works:
• First, register an event handler to the change event of the body. When a radio button is
clicked, its change event is bubbled to the body. This technique is called event delegation.
• Then, show a corresponding message based on which radio button is selected.

Using JavaScript change event for checkboxes


Similar to radio buttons, checkboxes re the change event after selection, whether checked
or unchecked. For example:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript change Event for Checkboxes</title>
</head>
<body>
<label for="status">Web Technology:</label>
<input type="checkbox" id="html"> HTML
<input type="checkbox" id="css"> CSS
<input type="checkbox" id="js"> JavaScript
<p id="result"></p>

<script>
let result = document.querySelector('#result');

document.body.addEventListener('change', function (e) {


let target = e.target;
let message;

switch (target.id) {
case 'html':
message = 'The HTML checkbox changed';
break;
case 'css':
message = 'The CSS checkbox changed';
break;
case 'js':
message = 'The JavaScript checkbox changed';
break;
}
result.textContent = message;
});
</script>
</body>
</html>
fi
Output:
Web Technology: HTML CSS Javascript

Using JavaScript change event for the select element


The <select> element res the change event once the selection has completed.
The following example shows how to handle the change event of the <select> element.
The <p> element with the id result will display the selected item:

<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript change Event for Select element</title>
</head>
<body>
<select id="lang">
<option value="">Select a language</option>
<option value="JavaScript">JavaScript</option>
<option value="TypeScript">TypeScript</option>
<option value="PHP">PHP</option>
<option value="Python">Python</option>
<option value="Java">Java</option>
</select>
<p id="result"></p>
<script>
let select = document.querySelector('#lang');
let result = document.querySelector('#result');
select.addEventListener('change', function () {
result.textContent = this.value;
});
</script>
</body>
</html>

Output:
Select a language 🔽

How it works:
• First, select the <select> element by its id (lang);
• Then, show the selected value in the <p> element.
Summary
• The <input> element res the change event once it loses focus.
• The radio button, checkbox, and select elements re the change event after they have
been selected.
fi
fi
fi
Handling input event
Summary: in this tutorial, you’ll learn about the JavaScript input event that res whenever
the value of the <input>, <select>And <textarea> changes.

Introduction to the JavaScript input event


The input event res every time whenever the value of the <input>, <select>, or <textarea> element
changes.

Unlike the change event that only res when the value is committed, the input event res whenever
the value changes.

For example, if you’re typing on the <input> element, the element re the input event continuously.
However, the change event only res when the <input> element loses focus.

The following example illustrates the input event of the <input> element:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript input Event Demo</title>
</head>
<body>
<label for="message">Message</label>
<input placeholder="Enter some text" id="message" name="message">
<p id="result"></p>
<script>
const message = document.querySelector('#message');
const result = document.querySelector('#result');
message.addEventListener('input', function () {
result.textContent = this.value;
});
</script>
</body>
</html>

Output:

Message Enter some text

How it works:
• First, select the <input> element with the id message and the <p> element with the id result.
• Then, attach an event handler to the input event of the <input> element. Inside the input event
handler, update the textContent property of the <p> element.
fi
fi
fi
fi
fi
fi

You might also like