Writing a .parents() function using Vanilla JS
Tags: javascript, webdev, writing, tutorial
Published: 2020-08-10 03:53:03

<h3>Intro</h3>
Moving away from the super useful and powerful Jquery in order to use more modern frameworks (such as React, Vue and Ember JS), the thing i miss the most about jquery was its super simple DOM manipulation that we don't have with Vanilla JS. 

My top favorite built in functions were the .parents() function and the .on() event handlers (the $ elm saved so many charactersof code!). These 2 functions single handedly reduced Vanilla JS code by a factor of 10x at least. The .on() function in jquery let us bind an event handler such as click to any number of elements as easy as: 
```Javascript
$('p').on("click", function() {
    //execute anything when any of the p tags on the page are clicked
}
```

That was super cool and useful. Now with Vanila JS we know we must loop through the collection of p tags and bind click events to each item in that collection (as they are treated as an array).
The code is much more complex:

```Javascript
const p = document.querySelectorAll('p')
for(item of p) {
    p.onclick = () => { //ES6
        //execute actions when p tags are clicked
}
}
```
As we can see its doable but adds easily 3-4 lines of extra code (even using ES6)

But for the magical .parents() function, Javascript does not even provide us a long or short way to achieve what jquery did. So let's see what we need to design in order to simulate the .parents() behaviour. In the end it'll add almost 20 lines of extra code as opposed to just writing .parents() but we'll have a readily available function that we can reuse whenever we want! Its gonna be a little long but stick around I promise you won't regret it.

```Javascript
function getParents(el, parentSelector) {
    if (parentSelector === undefined) {
        parentSelector = document;
    }
    var parents = [];
    var p = el.parentNode;
    while (p !== parentSelector) {
        var o = p;
        parents.push(o);
        p = o.parentNode;
    }
    parents.push(parentSelector);
    return parents;
}
```
<h3>Explainging the Code</h3>
Let's understand this code. The first line initiates the function and passes two parameters, the actual element which we are at and an optional parent selector to stop our parent search at. 

The second line says if we dont provide a parent selector then set the parent selector as the root-most element, which is the document itself (above the html tag). 

Then we create a parent array and stuff all of the parent elements of our element. We then have a while loop that dictates that while the current parent node is not our provided parent selector (or document) then assign that node to a variable o and push o into the parents array. 
So every iteration where that parent node is not the provided parent selector, we add that node to an array. Eventually our provided parent selector will be the current parent node as it goes up and compares to every parent node all the way up the DOM. 
Once there is a match, the while loop will stop, the array will finally push our provided parent selector and thus the highest parent node will be at the end of the array. Finally we return the array parents and we are done.

Now how do we actually make use of our custom built function to use like .parents() in jquery? Simple. We call the function on the element we want and pass as arguments our element and a max parent selector like so:

```Javascript
//parentDiv is our max parent selector
const button = document.querySelector('button')
const parentDiv = document.querySelector('.parentdiv')

//here we call our getParents function
const parents = getParents(button, parentDiv)
//and here the magic happens, since our parent node is always the last one
parents[parents.length-1] 
```
Since our parent selector is always the last one we can refer to it simply by using our parents array and retrieving the last element in the array by doing parents.length-1 (will get the last element in the array).

We can then do
```Javascript
parents[parents.length-1].querySelector('p').innerHTML //finds a p tag's inner html contents inside our parents element, just like in jquery
```
<h3>Comparing Jquery to Vanilla JS</h3>
Finally lets see the comparision between our custom built Vanilla JS solution and jquery's solution:
```Javascript
//jquery
var mytxt = $('button').parents('.parent1').find('p').html() //will get us the html content of a p element inside the parent div of our button - super useful DOM manipulation

//Vanilla JS
const parents = getParents(button, parent1)//assuming button and parent1 are already assigned 
const mytxt = parents[parents.length-1].querySelector('p').innerHTML
```
And now we have our desired result inside the mytxt const using Vanilla JS instead of Jquery!


<h3>Final Thoughts</h3>

Sure the Vanilla JS solution required quite some extensive code but ultimately its not that bad and well worth to use if we reuse the function across our app. 


Thanks for taking interest in my post and reading up to the end. I hope you will find this useful and that it helps you in your future coding projects!