How to insert a div after another div in Javascript
Tags: javascript, opensource, 100daysofcode
Published: 2020-02-23 08:01:45

Hello everyone! I've been trying to make sense of what I'm learning to be frank. Because honestly, this topic started out innocent but it grew to be what I'd described to be advanced, at least for me.

Upon first reading the title, I would have thought it was easy enough to do. However, it actually took me quite a while to understand it. Now, I'm going to attempt to explain it.

When I initially googled the above, it took me to this [Stackoverflow question](https://stackoverflow.com/questions/4793604/how-to-insert-an-element-after-another-element-in-javascript-without-using-a-lib). 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kl3y1cder3mb61q4genl.png)

As you can see, the first function they recommended was insertBefore(). Initially I thought, okay sure, I'm pretty sure they have insertAfter() but don't ask me why I did not attempt to do it through that function.

(Also, as a side note, I'm not sure if "function" is the right terminology for Javascript. It could be method. This is an excuse, I'm sorry!)

Anyways, there is in fact, an insertAfter() function in Javascript. [Here it is](https://www.w3schools.com/jquery/html_insertafter.asp). So this post could be entirely misleading. It may not be best practice, but I treated this as a learning point.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jttdcld9de4dujb7kwzi.png)

This will be the desired outcome. The idea of the structure is that there is a bigger, encapsulating div (dark blue, pictured above) with all the little todo items inside. 

So it's this structure.

```html
<div>
<div>
</div>
<div>
</div>
<div>
</div>
</div>
```

Convey the above structure in code and we have this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pjc52l0e0d0cco212i54.png)

Do keep in mind that the todolist items will be 100% added via Javascript. This includes the element, alongside the attributes like the classes. The above are just the title and the input fields.

So, back to the question at hand. How are we going to add todo items inside this list?

Let's take a look at how insertBefore() works. Going to this [website](https://www.w3schools.com/jsref/met_node_insertbefore.asp), you see this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2b9t7mg7fgd26yet5ri4.png)

Here's the syntax for usage.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2b97awzsjkk0jcwuflu8.png)

As you can see, the definition states that it will insert a node as a child, which is perfect for our situation.

Also, I came across this [solution](https://stackoverflow.com/a/4793630).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7re9ie0zuefdppk857ku.png)

The first code in that link shows a lot of similarities to how insertBefore() works. However, the slight catch is that we have a "referenceNode" created.

We want to add a node after the latest node. So, what this "referenceNode" does is to keep track of the latest node.

This is what I have in my code currently.

```javascript
var referenceNode = document.getElementsByClassName('category-title')[0];
```

Let's take a step back. Our main div is "category-panel". If we were to count the number of child divs inside the main div, "category-title" would be the first and the latest. So it makes sense to have the "referenceNode" as the "category-title" div.

Remember how I said we were going to add the todo items through Javascript? So how do I keep track of the items?

I use an array. For now.

```javascript
var todoList = ["Do laundry", "Hello", "It's me"];
```

So, the plan is to loop through this array and display each item when the page reloads.

Currently, this is what I have.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/h4sxnoyopz3oxsa2py8e.png)

From the code above, I checked first if the todo list is empty. I made the "category-title" div as the reference node when looping the array for the first time.

However, where it gets interesting is when there is already one todo item displayed. For that we would have to change the reference node. This makes every latest todo item to be displayed the reference node.

How do we check which is the latest todo item?

Well, for every todo item, I have added a class attribute called "category-item". So I get all elements with said class name and count the length, which is the number of elements with said class name. 

```javascript
document.getElementsByClassName("category-item")[childrenCount-1];
```

To access the latest, I used an all-familiar array syntax, except I did "childrenCount - 1". We are always starting from 0 so it makes sense to subtract one off the length to access the real index.

So then, what's up with this?

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qoiq6tcyg2vs40t8pcnz.png)

This is the same code that insertBefore() works with. What's different is that we are centering the code around the reference node.

```javascript
referenceNode.parentNode
```

Remember the definition of insertBefore()? Well, since we are using the reference node, which is a child node, this is how we access its parentNode.

```javascript
.insertBefore(divNode, referenceNode.nextSibling);
```

Remember that insertBefore() needs to know the parent node,  the new child node and also the reference child node to put other elements before it.

```javascript
referenceNode.nextSibling
```

This means we are refering to the "about-to-be" or "future" next node. This is going to be a null node but insertBefore() accounts for that. Through this code, insertBefore() now knows all 3 requirements. This is a workaround in my opinion. But it works.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hbd5a8smj8awmgyav9q6.png)

With this implementation, you could interpret insertBefore() as "inserting a node as a child right before a non-existing child". Technically it does not exist but this function accounts for null nodes. So, it works.

*NOTE: Just a slight disclaimer, I could have done this multiple different ways but I'd just like to emphasize that I encountered this situation and tried the first solution. Just wanted to get that out of the way.

So, that is how it works. It's an information overload for me initially but I hope my post sheds a little bit of light on it. 

Thanks!