# DOM in Depth

The Document Object Model, or DOM for short, is a powerful tool that allows web developers to dynamically add, remove, and modify elements on a web page.

It's like having a magic wand to change a website's appearance and functionality with just a few lines of code. This article will explore using the DOM to add and remove elements, modify existing elements, and attach event listeners.

In the last module on DOM, we learned how to access the DOM elements. So, in this module, with the help of knowledge from the last class, we will learn how to add or remove elements from DOM.

### Adding and Removing elements from DOM:

### Adding an element:

To add an element to the Document Object Model (DOM), we must first create the element.

We can create a new HTML element using the JavaScript method `document.createElement()`.

This method takes the name of an HTML tag as an argument and returns a new `Node` object of the `Element` type.

```jsx
let element = document.createElement(htmlTag);
```

The above code will create an HTML element of the specified parameters.

Consider the HTML document without any div element. We can create a new div element using the \*\*`document.createElement()`\*\*method and then use the `appendChild()` method to add the created div element to the DOM tree.

This can be demonstrated with the help of the following example.

```jsx
<!DOCTYPE html>
<html>
<head>
    <title>JS CreateElement Demo</title>
</head>
<body>

</body>
</html>
```

Now, we will use the `document.createElement()` to create a new `<div>` element as shown below:

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

After creating the div element, we can add HTML content to it using the `innerHTML` property. Let's modify our previous example accordingly:

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

Next, we can attach the newly created div element to the document using the `appendChild()` method.

```jsx
document.body.appendChild(div);
```

In the code snippet above, the `appendChild()` method has been applied to the `body` element because the intention is to add the newly created `div` element to the body of the document.

joining all the above code, the combined HTML code becomes:

```jsx
<!DOCTYPE html>
<html>
<head>
    <title>JS CreateElement Demo</title>
</head>
<body>
    <script>
        let div = document.createElement('div');
        div.innerHTML = '<p>CreateElement example</p>';
        document.body.appendChild(div);
    </script>
</body>
</html
```

Let’s discuss in detail about **appendChild()** method:

The `appendChild()` method is a part of the `Node` interface in JavaScript, which enables you to add a new node to the end of the child nodes list of a specific parent node.

The syntax of the `appendChild()` method is as follows:

```jsx
parentNode.appendChild(childNode);
```

The `appendChild()` method is used to add a child node to a parent node. The new child node is specified as the `childNode` parameter in the method. The `appendChild()` method returns the appended child.

If the `childNode` parameter references an existing node in the document, the `appendChild()` method will move the `childNode` from its current position to the new position specified in the method.

Consider the example shown below:

Suppose you have given the following HTML document:

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

Now, we want to add the list items i.e., &lt;li&gt; elements to this list , now see the code below:

```jsx
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'));
```

How the code works:

1. The `createMenuItem()` function creates a new list item element with a specified name using the `createElement()` method.
    
2. The `querySelector()` method is used to select the `<ul>` element with the id `menu`.
    
3. The `createMenuItem()` function is called to create a new menu item and the `appendChild()` method is used to append the menu item to the `<ul>` element.
    

**Output:**

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

### Removing an element:

The `removeChild()` method can be used to remove a child element from a node. The syntax for the `removeChild()` method is as follows:

```jsx
let childNode = parentNode.removeChild(childNode);
```

The `removeChild()` method removes the specified child node from its parent node in the DOM tree. The `childNode` parameter specifies the child node that you want to remove from the `parentNode`. If the `childNode` is not a child of the `parentNode`, the method throws an exception.

The `removeChild()` method returns the removed child node from the DOM tree but still keeps it in the memory for future use.

If you don't need to keep the removed child node in the memory, you can use the following syntax instead:

```jsx
parentNode.removeChild(childNode);
```

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

Consider the following example, which demonstrates how to remove a child element from a node using the `removeChild()` method:

Suppose we have an HTML markup with a list element as shown below:

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

Now, consider that you want to remove the last child element:

```jsx
let menu = document.getElementById('menu');
menu.removeChild(menu.lastElementChild);
```

The code removes the last element of an unordered list using the `removeChild()` method. Here is how it works:

* First, the `ul` element with the id `menu` is obtained using the `getElementById()` method.
    
* Then, the `removeChild()` method is used to remove the last element of the `ul` element. The `menu.lastElementChild` property returns the last child element of the `menu`, which is then passed as an argument to the `removeChild()` method. This removes the last child element from the `menu` element.
    

If you want to remove all child elements of an element, you can follow the steps given below:

* First, get the first node of the element using the `firstChild` property.
    
* Then, use a loop to repeatedly remove the child node until there are no child nodes left.
    

The following code shows how to remove all list items of the `menu` element:

```jsx
let menu = document.getElementById('menu');
while (menu.firstChild) {
    menu.removeChild(menu.firstChild);
}
```

Now let's explore how we can modify an element's attributes in our HTML document.

### Modifying element’s attributes:

**Let’s first discuss the connection between HTML attributes and DOM properties:**

When a web browser loads an HTML page, it creates corresponding DOM objects based on the DOM nodes of the document.

For instance, if the page includes the following `input` element:

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

When a web browser loads an HTML page, it generates corresponding DOM objects based on the DOM nodes of the document.

For example, an `input` element on a page will generate an `HTMLInputElement` object. The `input` element has two attributes: `type` with the value `text`, and `id` with the value `username`.

After the web browser loads an HTML page, it creates the corresponding DOM objects based on the DOM nodes present in the document.

* The `input.type` with the value `text`.
    
* The [`input.id`](http://input.id) with the value `username`.
    

To access both standard and non-standard attributes, you can use the following methods:

* `element.getAttribute(name)` to get the value of the attribute.
    
* `element.setAttribute(name, value)` to set the value of the attribute.
    
* `element.hasAttribute(name)` to check for the existence of the attribute.
    
* `element.removeAttribute(name)` to remove the attribute.
    

### getAttribute()

To obtain the value of a particular attribute of an element, you can use the `getAttribute()` method of the element.

This method needs to be called on the element, and the name of the attribute whose value is to be retrieved should be passed as an argument to the method.

```jsx
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

When the specified attribute exists on the element, the `getAttribute()` method returns a string representing the value of the attribute. However, if the attribute does not exist on the element, the method returns `null`.

Consider the example below:

```jsx
<!DOCTYPE html>
<html>
<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>
```

**Output:**

```jsx
_blank
```

To retrieve the target attribute of the link element with the id "js", follow these two steps:

1. Use the `querySelector()` method to select the link element.
    
2. Call the `getAttribute()` method to obtain the target attribute of the selected link element.
    

### setAttribute() method:

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

```jsx
element.setAttribute(name, value);
```

### Parameters

When using the `setAttribute()` method on an HTML element, the `name` parameter specifies the name of the attribute whose value is being set. If the attribute name is in uppercase, it will be automatically converted to lowercase. The `value` parameter specifies the value to be assigned to the attribute. If a non-string value is passed to the method, it will be automatically converted to a string.

### Return value

After setting an attribute on an element using the `setAttribute()` method, it doesn't return any value, and its return value is `undefined`. If the attribute is already present on the element, the `setAttribute()` method updates the value of the attribute; otherwise, it creates a new attribute with the given `name` and `value`.

It's common practice to use `querySelector()` or `getElementById()` to select an element before calling the `setAttribute()` method on it.

Consider the example shown below:

```jsx
<!DOCTYPE html>
<html>
<body>
    <button id="btnSend">Send</button>

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

Output:

```jsx
<button id="btnSend" name="send">Send</button>
```

To set the value of the `name` attribute to `send` on the button element with the id `btnSend`, follow these two steps:

1. Use the `querySelector()` method to select the button element with the id `btnSend`.
    
2. Call the `setAttribute()` method on the selected button element, and set the `name` attribute to `send`.
    

### hasAttribute() method:

To determine whether an element has a particular attribute, you can use the `hasAttribute()` method.

```jsx
let result = element.hasAttribute(name);
```

### Parameters

The `hasAttribute()` method accepts an argument that specifies the name of the attribute that you want to check.

### Return value

The `hasAttribute()` method returns a Boolean value that indicates whether an element has the specified attribute or not. If the element contains the attribute, the `hasAttribute()` method returns `true`; otherwise, it returns `false`.

### removeAttribute() method:

You can use the `removeAttribute()` method to delete an attribute with a specific name from an element.

```jsx
element.removeAttribute(name);
```

### Parameters

To remove an attribute from an element, you can use the `removeAttribute()` method and pass the name of the attribute as an argument. If the attribute doesn't exist, the `removeAttribute()` method won't throw an error.

### Return value

After removing an attribute from an element using the `removeAttribute()` method, it doesn't return any value, and its return value is `undefined`.

These are the various ways to modify the attributes of an element. Now, let's move on to learning about EventListeners.

### Event Listeners:

An event is an action that takes place in a web browser and triggers a response that you can react to.

For instance, when users click a button on a web page, you may want to respond to this `click` event by showing a dialog box.

Each event can have an associated event handler, which is a code block that executes when the event occurs.

An event handler is also referred to as an event listener since it listens for the event and performs a task when the event occurs.

### Event Flow:

For understanding Event flow consider the HTML document given below:

```jsx
<!DOCTYPE html>
<html>
<body>
    <div id="container">
        <button id='btn'>Click Me!</button>
    </div>
</body>
```

Clicking a button triggers not only the button but also its container, the `div` , and the entire webpage.

Event flow describes the sequence in which events are received on the page, starting from the element where the event occurs and then propagated through the DOM tree.

There are two primary event models: event bubbling and event capturing.

### Event Bubbling:

Under the event bubbling model, an event begins at the most specific element and moves upward towards the least specific element (such as the `document` or `window`). When you click a button, the `click` event takes place in the following order:

1. The button
    
2. The `div` with the id `container`
    
3. The `body` element
    
4. The `html` element
    
5. The `document` object
    

The `click` event initially occurs on the button that was clicked, then propagates up the DOM tree, triggering on each node along the way until it reaches the `document` object.

Consider the following picture shown below:

### Event Capturing:

The event-capturing model is characterized by the event starting at the least specific element and then flowing down toward the most specific element.

For instance, when you click on a button, the `click` event will occur in the following order:

1. document
    
2. html
    
3. body
    
4. div with the id container
    
5. button.
    

Consider the following picture below:

As we learned previously, an event executes a block of code known as an event handler or event listener.

An event can have one or multiple event handlers, and all of them will be executed when the event is triggered.

There are several ways to handle events, including:

### HTML Event Handler Attributes:

Usually, event handlers are named with an "on" prefix, such as "onclick" for the click event.

To link an event handler with an HTML element, you can use an HTML attribute with the event handler's name.

Here's an example:

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

In the previous example, the `onclick` attribute is set to call the `showAlert()` function defined in the JavaScript code.

Using this method, you can keep the HTML code clean and put all the event handling code in the JavaScript code.

It's a best practice to separate the behavior from the content by keeping the event handling code separate from the HTML code.

```jsx
<script>function showAlert() {
        alert('Clicked!');
    }
</script><input type="button" value="Save" onclick="showAlert()">
```

When the button is clicked in the above example, it triggers the execution of the `showAlert()` function.

**Disadvantages** **of using HTML event handler attributes:**

Using HTML event handler attributes to assign event handlers is generally considered a bad practice and should be avoided due to the following reasons:

Firstly, it can make the code more difficult to maintain and extend since the event handler code is mixed with the HTML code.

Secondly, it can cause timing issues. If the element is fully loaded before the JavaScript code, users can start interacting with the element on the webpage, which can result in errors.

Therefore, there are alternative methods for assigning event handlers that should be used instead.

### addEventListener() method:

`addEventListener()` - registers an event handler

syntax:

```jsx
element.addEventListener(event, function, useCapture)
```

The `addEventListener()` method requires three arguments:

* an event, a function, and an optional boolean value for `useCapture`.
    
* The event argument is a string that specifies the name of the event. The function argument is a required parameter and defines the JavaScript code that responds to the event.
    
* The `useCapture` parameter is optional, and its default value is false. It determines whether the event is executed in the capturing or bubbling phase. When set to true, the handler executes in the capturing phase, and when set to false, the handler executes in the bubbling phase.
    

To add an event listener to the button element with the ID property "btn" and execute a function on click, we can use the `addEventListener()` method.

Here's an example code snippet:

```jsx
let btn = document.querySelector('#btn');
btn.addEventListener('click',function(event) {
    alert(event.type); // click
});
```

The code example above shows how to add multiple event handlers to a single event. In this example, there is a button with an ID of `myButton`. Three event handlers are added to handle the click event of this button. Each event handler is defined as a separate function.

First, the `handleFirstClick` function is added to the button as an event listener. Then, the `handleSecondClick` function is added using the `addEventListener` method with the third argument as `true`, which means the event handler executes in the capturing phase.

Finally, the `handleThirdClick` function is added using the `addEventListener` method with the third argument as `false`, which means the event handler executes in the bubbling phase.

When the button is clicked, all three event handlers will be executed in the order of capturing phase, a target phase, and a bubbling phase.

```jsx
let btn = document.querySelector('#btn');
btn.addEventListener('click',function(event) {
    alert(event.type); // click
});

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

### **Activity 2**

**State True or False:**

* `addEventListener()` method has four arguments i.e. event, callback, value, useCapture.
    
* An event refers to a particular action that occurs within a web browser and leads to a response that can be responded to.
    
* In the event-capturing model, events typically begin from the most specific element and then propagate downwards towards the least specific element.
    

### removeEventListener() method:

The `removeEventListener()` method is used to remove an event listener that was previously added using the `addEventListener()` method.

The arguments passed to `removeEventListener()` must match the arguments that were passed to `addEventListener()`.

**Consider the following example:**

```jsx
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);
```

The code above demonstrates the use of the `removeEventListener()` method to remove an event handler previously added using the `addEventListener()` method. It is important to note that the same arguments must be passed to `removeEventListener()` as were passed to `addEventListener()`. Additionally, anonymous functions cannot be used as arguments in `removeEventListener()`.

**There are various different events to which user can listen and add handlers:**

| Event Performed | Event Handler | Description |
| --- | --- | --- |
| click | onclick | An event occurs when the user clicks on an element with a mouse. |
| mouseover | onmouseover | An event occurs when the cursor of the mouse comes over an element. |
| mouseout | onmouseout | An event occurs when the cursor of the mouse leaves an element. |
| mousedown | onmousedown | An event occurs when the user presses the mouse button over an element. |
| mouseup | onmouseup | An event occurs when the user releases the mouse button over an element. |
| mousemove | onmousemove | An event occurs when the mouse moves over an element. |
| Keydown & Keyup | onkeydown & onkeyup | An event occurs when the user presses and releases a key. |
| focus | onfocus | An event occurs when the user focuses on an element. |
| submit | onsubmit | An event occurs when the user submits a form. |
| blur | onblur | An event occurs when the focus is away from a form element. |
| change | onchange | An event occurs when the user modifies or changes the value of a form element. |
| load | onload | An event occurs when the browser finishes loading the page. |
| unload | onunload | An event occurs when the visitor leaves the current webpage and the browser unloads it. |
| resize | onresize | An event occurs when the visitor resizes the window of the browser. |

**onclick, onmouseover, onfocus, onkeydown:**

```jsx
<html>
<head> Javascript Events </head>
<body>

//onclick
<form>
<input type="button" onclick="clickevent()" value="Who's this?"/>
</form>

//mouseover
<p onmouseover="mouseoverevent()"> Keep cursor over me</p>

//focus
<h2> Enter something here</h2>
<input type="text" id="input1" onfocus="focusevent()"/>

//keydown
<h2> Enter something here</h2>
<input type="text" id="input1" onkeydown="keydownevent()"/>

<script>

	//onclick
	function clickevent()
	{
		document.write("This is JavaTpoint");
	}

	//mouseover
	function mouseoverevent()  
  {  
        alert("This is JavaTpoint");  
  }

	//focus
	function focusevent()
	{
		document.getElementById("input1").style.background=" aqua";
	}

	//keydown
	function keydownevent()
	{
		document.getElementById("input1");
		alert("Pressed a key");
	}

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

Now that we have learned about events and their handling, let's move on to modifying CSS.

We can start by learning how to set inline styles.

### Setting Inline Styles:

The style property of an element is used to set its inline style.

```jsx
element.style
```

The `style` property retrieves a read-only `CSSStyleDeclaration` object that contains a collection of CSS properties. To set a CSS property, such as color, for an element and make it appear red, you can use the following code:

```jsx
element.style.color = 'red';
```

In case the CSS property contains hyphens (-) like -webkit-text-stroke, you can access it using the array-like notation (\[\]):

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

You can completely override the existing inline style by setting the `cssText` property of the `style` object. Here's an example:

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

Or the `setAttribute()` method can be used:

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

After setting the inline style of an element, you can modify one or more CSS properties:

```jsx
element.style.color = 'blue';
```

If you don't want to replace all the existing CSS properties with a new one, you can append the new CSS property to the `cssText` property using string concatenation. Here's an example:

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

Here, the operator "+=" is used to concatenate the new style string with the existing one.

### Manipulating CSS Classes:

The `className` property is used to retrieve the CSS classes of an element and returns them as a string separated by spaces.

```jsx
element.className
```

Consider an unordered list (ul) element as follows:

```jsx
<ul id="menu" class="vertical main"><li>Homepage</li><li>Services</li><li>About</li><li>Contact</li></ul>
```

The below code demonstrates how to get the classes of the `**ul**` element on the Console window:

```jsx
let menu = document.querySelector('#menu');
console.log(menu.className);
```

**Output:**

```jsx
vertical main
```

The following code can be used to assign a class to an element:

```jsx
element.className += newClassName;
```

The `+=` operator adds the `newClassName` to the existing class list of the element.

The `classList` property of an element is read-only and it returns a collection of CSS classes that can be modified to add, remove, or toggle classes of the element.

```jsx
const classes = element.classList;
```

The `classList` property of an element returns a read-only `DOMTokenList` object that represents the classes in the element's `class` attribute.

Despite being read-only, you can still modify the classes using various methods. Let's look at some examples to understand these methods.

Consider the following HTML snippet as an example:

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

To get the classes of an element, we can use the `classList` property of the element as follows:

```jsx
let div = document.querySelector('#content');
for (let cssClass of div.classList) {
    console.log(cssClass);
}
```

**Output:**

```jsx
main
red
```

How it works:

* In the code above, we first select the `div` element with the `content` id using the `querySelector()` method.
    
* We then iterate over the elements of its `classList` and display the classes in the Console window.
    

**Adding one or more classes to the class list of an element:**

To include one or more CSS classes in the class list of an element, you can use the `add()` method of the `classList`.

For instance, the code below adds the `info` class to the class list of the `div` element with the id `content`:

```jsx
let div = document.querySelector('#content');
div.classList.add('info');
```

You can use the `add()` method of the `classList` property to add one or more CSS classes to an element.

```jsx
let div = document.querySelector('#content');
div.classList.add('info','visible','block');
```

**Removing element’s classes:**

You can remove a CSS class from the class list of an element by using the `remove()` method, which is a part of `classList`.

```jsx
let div = document.querySelector('#content');
div.classList.remove('visible');
```

Similar to the `add()` method, you can remove multiple classes at once using the `remove()` method.

```jsx
let div = document.querySelector('#content');
div.classList.remove('block','red');
```
