JS: How to automate going up "parentNode" as many times as needed

724 Views Asked by At

Let's say I have a div that's called Z.Zthat is a sub-sub-sub... child of adivcalledBwhich is a child of adivcalledA`.

All the block from B to Z are set to display=none (A is visible).

If I click on a anchor that links to the block Z, I want it to be displayed.

For that I need to set the display of block Zblock, but also its parent's display* to block, and its parents and all the way up to block B....

I don't want to "hard" code all the possible level because I could have 2, 4 or 10 levels. So I would like to find a way to do it automatically.

I simplified a bit the example above as I have to set the display=block every 2 "generations" (cf in my code the parentNode.parentNode)

So far this is my code (with 2 level down the rabbit hole!) and not automation:

function indexLink(link_to_anchor) {
    var x = document.getElementById(link_to_anchor);
    if (x.parentNode.parentNode.getAttribute("class") == "divcodebox") {
        if (x.parentNode.parentNode.parentNode.parentNode.getAttribute("class") == "divcodebox") {
            x.parentNode.parentNode.parentNode.parentNode.style.display = "block";
        }
        x.parentNode.parentNode.style.display = "block";
    }
    x.style.display = "block";
}

Using indexLink() recursively :

function indexLink(link_to_anchor) {
    var x = document.getElementById(link_to_anchor);
    x.style.display = "block";
    if (x.parentNode.parentNode.getAttribute("class") == "divcodebox") {
        x.parentNode.parentNode.style.display = "block";
        indexLink(x)
    }
}
3

There are 3 best solutions below

2
Pointy On BEST ANSWER

How about a simple for loop?

    var x = document.getElementById(link_to_anchor);
    for (parent = x.parentNode; parent; parent = parent.parentNode) {
      // do whatever
    }

You can of course keep a counter to check how many steps you've traversed, etc. The .parentNode reference from the document level will be null, so that ends the iteration. (You can break out of the loop early too.)

0
Michel Vorwieger On
function recursiveApply(from, to, fn) {
    let current = from;

    while(current !== to) {
        fn(current);
        current = current.parentElement;
    }
}

and then use it like:

var a = document.getElementById("1");
var b = document.getElementById("2");

recursiveApply(a, b, function(element) {
    // do stuff with the element
    console.log(element)
});
0
Lain On

This is just to show how your recursive function should look like based on your code and not a finished example.

;function indexLink(element){
    //REM: Change the parameter to the actual element instead of its id
    //var x = document.getElementById(link_to_anchor);

    //REM: Check if the element exists and the style does not equal block
    //REM: If the styles are set by class you need to change this to computed style
    if(element && element.style.display !== 'block'){
        //REM: Set the display to block
        element.style.display = 'block';

        //REM: Repeating the same logic for the parentNode
        indexLink(element.parentNode)
    }
};