Saturday, April 29, 2023

Best Free JavaScript DOM Manipulation Libraries

Best Free JavaScript DOM Manipulation Libraries

The term DOM is short for Document Object Model and we use this term to refer to the structure of a webpage in the form of a tree. Each element on the webpage represent a node on the tree.

Manipulation of DOM means the manipulation of those elements to achieve a specific goal. DOM manipulation requires you to access those elements and then modifying them using a variety of methods and properties. You can make different types of changes to the DOM. This includes changing its text content, classes, styles and so on.

It is also possible to create new elements or insert child elements at different places in the DOM tree. Quite a few DOM manipulation tutorials on this topic on Tuts+ discuss how to do all this natively with JavaScript.

However, you can also manipulate DOM easily using different libraries. In this tutorial, I will give you a brief overview of some of the most popular free DOM manipulation libraries. We will also discuss the advantages and disadvantages of using these libraries.

jQuery

jQuery is one of the earliest and most popular DOM manipulation libraries. It was originally released in 2006. An era which was mired with browser incompatibility issues. The library quickly became popular among developers. One of the reasons for its huge popularity is its free and open-source nature with a permissive MIT license.

It was being used on around 77% of the top 10 million websites even in August 2022. It is by far the most popular DOM manipulation library out there.

Browser incompatibility is no longer as big an issue as its was earlier. However, jQuery can still be useful in certain situations. One of its advantages is mentioned in its tagline: "write less, do more". This library allows you to accomplish a lot with relatively little code compared to native JavaScript.

The jQuery library will help you in three key areas—DOM traversal and manipulation, event handling, and AJAX. The library can also be extended with third-party plugins to provide additional functionality. You can even write some code of your own and use it as a plugin.

One issue with jQuery could be its size which comes at 30kB when minified and gzipped. This isn't a lot by itself but can add up quickly. You might want to consider using other libraries mentioned in the post to take advantage of new developments in the JavaScript space.

Sizzle

It is possible that you probably already know about Sizzle if you have spent some time learning jQuery. The Sizzle library is basically a standalone selector engine while jQuery is a much larger library that provides additional functionality. jQuery simply uses Sizzle as its selector engine internally. However, you can also use Sizzle all by itself if you don't plan on using any features of jQuery itself.

One of the biggest selling points of Sizzle is that it offers compatibility as far as Internet Explorer 7. The library supports almost every CSS3 selector except those which require keeping track of the element state such as :hover, or :active

The library API is made up of three parts. The Public API which you can use to select elements, the Extension API which modifies the selector engine, and the Internal API which is used internally by Sizzle.

Umbrella JS

The Umbrella JS library is a powerful and lightweight alternative to jQuery. It weighs less than 2.5kb once minified and gzipped. This makes it over 10 times smaller than jQuery. The API of the library is strongly influenced by jQuery and offers a lot of methods with similar names and functionality.

The three primary uses of the library are in DOM traversal using methods like filter() and find(), DOM manipulation including changing the classes and attributes, and event handling such as clicks, form submissions and input value changes. It also supports event delegation.

Umbrella JS also offers some additional DOM manipulation features such as a more powerful append() method and event handling methods like handle() which works like on() but also prevents the default action.

The library is thoroughly tested on the development and well as deployment versions to make sure you don't get any unexpected results while using the library in production.

The primary focus of Umbrella JS is on providing a light-weight library that focuses on DOM manipulation. Therefore, it lacks additional features available in jQuery.

Zepto

Zepto is another lightweight jQuery alternative that tries to mimic the functionality and features of the latter as closely as possible. The library weighs around 9.6kb once minified and gzipped.

Browser support in Zepto goes back as far as Internet Explorer 10. The library will work in every modern browser and browser-like environment. Zepto is modular by design and allows you to choose which module you want to include in a particular build.

Some modules like the core Zepto module, the event handling module, the AJAX support module, and the form handling module are included in a build by default. Others can be added optionally, like the module for integrating animation support.

Bliss

The Bliss.js library is also an excellent alternative for anyone who is looking for a lightweight DOM manipulation library. The library has two variants. The full version which adds $() and $$() global methods among other things. There is also a shy version which only adds a single global Bliss variable. The former is ideal when you have control over the development environment while the latter is great for maximum compatibility with third-party libraries.

One important distinction between Bliss and other DOM manipulation libraries is that it is simply a collection of helper methods with easy to use syntax for people who don't prefer using the native DOM API. This means that the library doesn't handle bugs or lack of support for certain APIs. However, the aim is to only use features that are supported across modern browsers and have polyfills available to extend support.

The library works in conjunction with polyfill.io to only load polyfills if they are actually needed by the current browser. This means that the library loads in the most optimum way possible.

Advantages of Using a DOM Manipulation Library

It is certainly true that DOM manipulation is a lot easier today with native JavaScript than about a decade or so ago. However, using a DOM manipulation library can certainly provide some advantages even today.

Write Less Code

The most common advantage is the simplification of the syntax and the brevity of the code. Using DOM manipulation libraries still provides the advantage of allowing you to write less code to do the same thing.

Browser Compatibility

Compatibility is no longer as big an issue as it was in the past. However, some minor differences can arise every now and then. A good DOM manipulation library will take care of those discrepancies for you.

Efficiency

Doing things natively will generally give you a performance boost instead of using a library. However, this is only true if you are following the best practices yourself. A well-written library will be constantly improved by the community. This means that there is a possibility that they might implement a functionality more efficiently than you do.

Disadvantages of Using a DOM Manipulation Library

If you are planning to use a DOM manipulation library, it is also important for you to know its potential downsides to make an informed decision.

Added Page Weight

Including a new library in your project will increase the total page-weight. This can result in slightly higher page load times. You can also experience performance issues if the library you are using isn't written optimally.

Extra Syntax to Learn

Any DOM manipulation library that you use will have its own syntax that you need to use. This means that you will have to spend some additional time to thoroughly learn how to get things done with the library.

Missing Features

Different DOM manipulation libraries are developed with different goals in mind. Therefore, it is possible that they might not have implemented all the features that you would like to use.

Final Thoughts

In this tutorial, we learned about some of the most popular, free, and open-source DOM manipulation libraries that you can use in your next project. The most popular among them all is jQuery which comes with a lot of additional features besides DOM manipulation. jQuery also offers great browser support.

The huge size of jQuery can be a deterrent for some people. Zepto can be a great alternative in this case as it tries to mimic jQuery as closely as possible. You can also consider using Umbrella JS if you are strictly interested in just DOM manipulation.


JavaScript DOM Manipulation Cheat Sheet

JavaScript DOM Manipulation Cheat Sheet

DOM manipulation can be done using basic JavaScript. When interactive web applications are designed and created, DOM elements must be modified with user interaction. And, DOM manipulation is the process of modifying the document object model, along with its content.

Creating DOM Elements

Create an Element From Scratch With createElement()

This is one of the most widely used operations, where a new DOM element gets created during user interaction. The createElement method can be used to create a new element based on the tag name.

The attribute passed into the createElement method can be in lower or uppercase. The method converts the tag name to lowercase, before creating the new element. 

1
// creating div

2
var element = document.createElement('div');
3
4
// creating paragraph element

5
var element = document.createElement('p');
6
7
// creating image element

8
var element = document.createElement('img');
9
10
// creating anchor element

11
var element = document.createElement('a');

Import an Element With importNode()

You can import a node from another document. For this, importNode method is used.

1
const importedNode = iframe.contentWindow.document.getElementById("myNode");
2
3
// if all the descendants of the imported node have to be copied

4
// deep = true

5
// if all the descendants of the imported node don't have to be copied

6
// deep = false

7
const deep = true
8
const element = document.importNode(importedNode, deep);

Clone an Element With cloneNode()

Likewise, you can clone an existing element, and create a new one.

A drawback in using this method could be duplication of element IDs. Ensure that the id of the newly created element is modified.

1
let p = document.getElementById("paragraph");
2
// if all the descendants of the imported node have to be copied

3
// deep = true

4
// if all the descendants of the imported node don't have to be copied

5
// deep = false

6
const deep = true
7
let duplicateParagraph = p.cloneNode(deep);

Attaching the New Element to the Document

Once the element is created or imported, it will not be attached to the document directly. The newly created element will be stored in a reference, and it would float around aimlessly. This is why another method has to be called, too append the newly created element to the document.

And, there are a few methods to attach an element to the document.

Method Description
append() appends a DOMString object, or a Node object to the parent element
appendChild() appends only Node objects to the parent element
insertBefore() inserts a new element before the parent element
prepend() inserts the new element before all the other child elements in the parent
1
<div id="parent">
2
  <p>Parent</p>

3
</div>

4
<button onclick="addChild()">Add Child</button>

5
6
<script>
7
  function addChild() {
8
    const parent = document.getElementById("parent"); // selecting parent

9
    const child = document.createElement("p"); // creating child

10
    child.innerHTML = "First Child"; // adding some content

11
    
12
    const child2 = document.createElement("p"); // creating child

13
    child2.innerHTML = "Second Child"; // adding some content

14
    
15
    // appending child to parent

16
    parent.append(child);
17
    parent.appendChild(child2);
18
    
19
    const grandparent = document.createElement("p"); // creating ancestor

20
    grandparent.innerHTML = "Grand Parent"; // adding some content

21
22
    // appending before parent

23
    parent.insertBefore(grandparent);
24
  }
25
</script>

Selecting Elements

Before you modify element attributes, you must ensure that the element gets selected correctly. There are many ways to select an element, based on its properties. Let's walk through few useful, and commonly used methods for selecting elements.

Query Methods

The query methods let you use a CSS selector to find elements in your document.

querySelector(selector)

Returns the first element to match a specified selector. If there are no matching elements, null is returned. 

querySelectorAll(selector)

Returns all elements that meet the selector, null if there are no matching elements.

1
const element = document.querySelector(selectors)
2
const element = document.querySelectorAll(selectors)

The selectors should be a valid CSS selector string. Example selectors are given below:

  • #main: the element with the id main
  • .login: elements with the class name login
  • form.login input[type='button']: all button inputs within a form with class name login

Getter Methods

getElementById(id)

Returns an element with the given ID. For this method to work efficiently, you must provide unique element IDs. If there are no matching elements, the method returns null.

getElementByClassName(classname)

Returns all elements with the given class name. If multiple class names are mentioned, only elements with all the class names will be returned. Elements returned will be a part of the live HTMLCollection. If code modifies a class name—the outcome of this method will be affected. This is why care needs to be taken while using this method inside an iteration.

getElementsByTagName(tagname)

Returns all elements with a given tag name. This method searches through the entire root node. Elements returned by this method are a part of the live HTMLCollection. Removing and adding elements to the DOM tree will automatically modify the result of this method.

1
  <body>
2
    <p id="para" class="test_class">Some text here</p>

3
    .
4
    .
5
  </body>

6
  
7
  const elem = document.getElementById("para");
8
  const element_by_classname = document.getElementsByClassName("test_class");
9
  const element_by_tagname = document.getElementsByTagName("p"); 

DOM Tree Traversal

We can also traverse a DOM tree, using a node's child and sibling elements. 

Method Description
parentNode() returns the parent node of an element
parentElement() returns the parent element of an element, without it's text and comment nodes
childNodes() returns all the child nodes of an element
firstChild() returns the first child of an element
lastChild() returns the last child of an element
children() returns a collection of child elements without text, and comment nodes
previousSibling() returns the previous sibling node of an element
nextSibling() returns the next sibling node of an element
1
<div id='parent'>
2
    <p id='first_child'>First Child</p>

3
    <p id='middle_child'>Middle Child</p>

4
    <p id='last_child'>Last Child</p>

5
</div>

6
7
const middle_child = document.getElementById('middle_child')
8
9
const parent = middle_child.parentNode() //parent

10
parent.lastChild() //last_child

11
parent.firstChild() //first_child

12
middle_child.previousSibling() //first_child

13
middle_child.nextSibling() //last_child

14
parent.children() // ['first_child', 'middle_child', 'last_child']

DOM Events

Interactivity of JavaScript comes from the DOM event listeners. The event listeners are called whenever there is a mouse movement, or key stroke. The listeners have to be connected to a node or element. This is why the method is called an 'event listener'. The method listens if an event occurred or not.

Information about the event are held inside an object, called the event object. When an event listener is called, the event object tracks the target, event type and all associated properties. 

There are several different types of events:

  • Keyboard Events: these capture a user's interaction with the keyboard. Details of the key pressed are stored in the key property. The keyboard events are fired in stages: keyDown, keyUp and keyPress. keyPress is fired only when there is a character involved, and not a modifier. (Modifiers are keys like tab, and caps lock on).
  • JavaScript Events: these can be used to manipulate the DOM. The goal of these events is to make the page as dynamic as possible. Whenever the user scrolls, clicks a button or performs an action - these events will be fired. Functions registered to events like onScroll, onClick, onFocus and onLoad are called event handlers.
  • Mouse Events: these can be used to capture a user's interaction with the mouse. Events are fired on click, mouseUp, mouseDown, mouseOver and mouseOut

.addEventListener(eventType, handlerFunction)

The addEventListener method is the recommended solution for registering DOM events. 

  • It allows users to add multiple event handlers for a single event.
  • It helps users to control when an event can be activated, or removed. 
  • It works on all event target types, ranging from SVG elements to traditional HTML content.
1
document.addEventListener("click", (event) => console.log(event))

.removeEventListener(eventType, handlerFunction)

As mentioned above, we have the freedom to activate and deactivate event listeners from anywhere in the code. The removeEventListener method is used to stop the document from listening to events. Just like the addEventListener function, we need to pass two arguments into the removeEventListener method.

1
eventTarget.addEventListener("event", eventHandlerFunction);
2
3
eventTarget.removeEventListener("event", eventHandlerFunction);

Remove DOM Elements

Remove Child Elements With removeChild()

Just like creation, elements may need to be removed from the document too. For this, the removeChild method can be used. The removeChild method returns the deleted node's reference. The removeChild method has to be called from its parent or else, an error will be thrown.

1
// selecting parent and child

2
const parent = document.getElementById("parent");
3
const child = document.getElementById("child");
4
5
// removing child from parent

6
parent.removeChild(child);

Replacing Elements with replaceChild()

Another method for removing DOM elements, is replacing them with newer child elements. 

1
// selecting parent

2
const parent = document.getElementById("parent");
3
// selecting oldElement

4
const oldElement = document.getElementById("child");
5
// creating newElement which is newChild

6
const newElement = document.createElement("newChild");
7
8
function replace() {
9
  newElement.innerHTML = "This is a new child"
10
  parent.replaceChild(newElement, oldElement);
11
}

Conclusion

We have come to the end of our JavaScript DOM manipulation cheatsheet. These are essential methods when you want to make dynamic changes in the DOM.


Friday, April 28, 2023

Insert, Replace or Remove Child Elements in JavaScript

Insert, Replace or Remove Child Elements in JavaScript

There are quite a few situations where we need to work with child elements on a webpage. One such example would be a to-do list where you might want to insert new tasks or remove old tasks form the list. Another example would be an app that keeps track of the stocks a user has purchased.

In this tutorial, we will learn about some important methods that you can use to easily insert, remove or replace child elements in JavaScript.

Inserting Child Elements

A child element can be inserted at the beginning, at the end or somewhere in between all other children of a parent. In this section, I will show you how to insert a child element at any of those desired locations with ease.

Insert a Child Element at the End

Generally when you have to insert child elements, they have to be added at the end of the list after all other children. The appendChild() method works best in this case. This method returns the newly appended node as its value.

If the child that you want to append already exists in the document, then this method will move it from its current position and place it at the new position.

We will start with the following list of fruits:

1
<ol>
2
  <li>Papaya</li>
3
  <li>Mango</li>
4
  <li>Banana</li>
5
  <li>Apple</li>
6
  <li>Guava</li>
7
</ol>

We will use the appendChild() method to add a new fruit to the bottom of the list. After that, we will move the fruit at the top of the list to bottom by using the same method.

1
let fruit_list = document.querySelector("ol");
2
let first_fruit = document.querySelector("li");
3
let new_fruit = document.createElement("li");
4
5
new_fruit.textContent = "Lichi";
6
7
// "Lichi" is added at the bottom.

8
fruit_list.appendChild(new_fruit);
9
10
// "Papaya" is moved to the bottom.

11
fruit_list.appendChild(first_fruit);

As I mentioned earlier, using appendChild() to append an existing node will move the node to its original location to the new position. That's exactly what happens with the first fruit on our list as it is moved to the bottom. The final HTML will look like this:

1
<ol>
2
    <li>Mango</li>
3
    <li>Banana</li>
4
    <li>Apple</li>
5
    <li>Guava</li>
6
    <li>Lichi</li>
7
    <li>Papaya</li>
8
</ol>

Inserting a Child Element Before or After a Particular Node

What if you don't want to add elements to the end of the list but before or after a particular element? For example, you might want to add Lichi to the list before or after Banana.

Adding a child element before a particular node is easy with the help of the insertBefore() method. It accepts two parameters. The first one is the child node that you want to insert. The second one is the node before which you want to insert the child node.

It is important to remember that this method requires both the parameters to work. However, you can set the value of second parameter to null to add the new node at the end of the list.

Let's use this method to insert a node before the third list element, Banana. The JavaScript will look something like this:

1
let fruit_list = document.querySelector("ol");
2
let third_fruit = document.querySelectorAll("li")[2];
3
let new_fruit = document.createElement("li");
4
5
new_fruit.textContent = "Lichi";
6
7
// Adds "Lichi" before "Banana"

8
fruit_list.insertBefore(new_fruit, third_fruit);

Using the following line will add Lichi at the end of the list.

1
fruit_list.insertBefore(new_fruit, null);

There is no method similar to insertBefore() that you can use to insert a child element after a particular node. However, we can emulate the same behavior with the help of the nextSibling property of a DOM Node.

1
let fruit_list = document.querySelector("ol");
2
let third_fruit = document.querySelectorAll("li")[2];
3
let new_fruit = document.createElement("li");
4
5
new_fruit.textContent = "Lichi";
6
7
fruit_list.insertBefore(new_fruit, third_fruit.nextSibling);
8
/*

9
<ol>

10
  <li>Papaya</li>

11
  <li>Mango</li>

12
  <li>Banana</li><li>Lichi</li>

13
  <li>Apple</li>

14
  <li>Guava</li>

15
</ol>

16
*/

One important thing to remember here is that browsers insert text nodes into your documents to represent whitespace. As a result, using the nextSibling property will usually give you back this node. You can use the nextElementSibling property if you want to refer to the actual element node.

1
let fruit_list = document.querySelector("ol");
2
let third_fruit = document.querySelectorAll("li")[2];
3
let new_fruit = document.createElement("li");
4
5
new_fruit.textContent = "Lichi";
6
7
// #text "\n  "

8
console.log(third_fruit.nextSibling);
9
10
// <li>

11
console.log(third_fruit.nextElementSibling);
12
13
fruit_list.insertBefore(new_fruit, third_fruit.nextElementSibling);
14
/*

15
<ol>

16
  <li>Papaya</li>

17
  <li>Mango</li>

18
  <li>Banana</li>

19
  <li>Lichi</li><li>Apple</li>

20
  <li>Guava</li>

21
</ol>

22
*/

Insert a Child Element at the Beginning

We can also use the insertBefore() method to insert a child element as the first child of the parent. This requires the use of the firstChild property. We use the child node returned by the firstChild property as the second parameter to the insertBefore() method and our new node is inserted before the original first child which will now become the second child.

Here is an example:

1
let fruit_list = document.querySelector("ol");
2
let new_fruit = document.createElement("li");
3
4
new_fruit.textContent = "Lichi";
5
6
fruit_list.insertBefore(new_fruit, fruit_list.firstChild);
7
/*

8
<ol>

9
    <li>Lichi</li>

10
    <li>Papaya</li>

11
    <li>Mango</li>

12
    <li>Banana</li>

13
    <li>Apple</li>

14
    <li>Guava</li>

15
</ol>

16
*/

Replace Child Elements

You can use the replaceChild() method if you want to replace a child node with a new node within a parent. This method also accepts two parameters. The first parameter is the replacement node while the second parameter is the old node that you want to replace.

1
let fruit_list = document.querySelector("ol");
2
let third_fruit = document.querySelectorAll("li")[2];
3
let new_fruit = document.createElement("li");
4
5
new_fruit.textContent = "Lichi";
6
7
fruit_list.replaceChild(new_fruit, third_fruit);
8
/*

9
<ol>

10
  <li>Papaya</li>

11
  <li>Mango</li>

12
  <li>Lichi</li>

13
  <li>Apple</li>

14
  <li>Guava</li>

15
</ol>

16
*/

Let's say the replacement node already exists somewhere within the DOM. In this case, it will be first removed from its original location before being used as a replacement.

1
let fruit_list = document.querySelector("ol");
2
let first_fruit = document.querySelector("li");
3
let last_fruit = document.querySelector("ol").lastChild;
4
5
fruit_list.replaceChild(first_fruit, last_fruit);
6
/*

7
<ol>

8
  <li>Mango</li>

9
  <li>Banana</li>

10
  <li>Apple</li>

11
  <li>Guava</li>

12
  <li>Papaya</li>

13
</ol>

14
*/

Remove Child Elements

Removal of child elements from a DOM node is also relatively easy due to the removeChild() method. This method accepts a single parameter which refers to the child node that you want to remove. The return value of this method is the removed node.

Let's use this method to remove a fruit from our list that has been eaten by someone.

1
let fruit_list = document.querySelector("ol");
2
let third_fruit = document.querySelectorAll("li")[2];
3
4
fruit_list.removeChild(third_fruit);
5
/*

6
<ol>

7
  <li>Papaya</li>

8
  <li>Mango</li>

9
  <li>Apple</li>

10
  <li>Guava</li>

11
</ol>

12
*/

As long as you have a reference to the removed child in your code, you can add it back to the DOM as shown below or reuse it in a different way. Otherwise, the removed element will be erased form the memory after a short time.

The following code will add the banana at the end of our list.

1
let fruit_list = document.querySelector("ol");
2
let third_fruit = document.querySelectorAll("li")[2];
3
4
fruit_list.removeChild(third_fruit);
5
fruit_list.appendChild(third_fruit);
6
7
/*

8
<ol>

9
  <li>Papaya</li>

10
  <li>Mango</li>

11
  <li>Apple</li>

12
  <li>Guava</li>

13
  <li>Banana</li>

14
</ol>

Final Thoughts

In this tutorial, we learned how to insert, replace or remove child elements of a parent using pure JavaScript. JavaScript provides the replaceChild() and removeChild() methods to easily do replacements and removals. Insertions are also very easy with the help of the insertBefore() method but you have to get a bit clever with your approach if you want to use the method to insert your element after a particular child or as the first child.