Write a function getByClassNameHierarchy() in javaScript that takes a path of class names and returns the last element of that path.
Example
Input: <div class="a" id="a-1"> <div class="b" id="b-1"> <div class="c" id="c-1"/> <div class="c" id="c-2"/> </div> <div class="c" id="c-3"/> </div> getByClassNameHierarchy("a>b>c"); Output: [<div class="c" id="c-1"></div>, <div class="c" id="c-2"></div>]
This function is the extended version of getElementByClassName().
Using the following approach we can solve this.
- Split the input path in an array of classes.
- Use an index tracker to track the current class at different levels.
- Recursively traverse the DOM from the root and in each functional call add the following checks,
- If the element is null then return (terminate further calls).
- If the current class is the last of the path and it is present in the element, add it to the result as we have reached to required path and return (terminate further calls).
- In the end, traverse all the children of the current element and if the element has the current class, recursively traverse its child with the next class (increase the index tracker by one), else traverse the child with the first class (index tracker as zero) and keep on finding the path.
For the DOM traversal, we will be using a helper function.
function getByClassNameHierarchy(element, classNames) { // get all the classnames const classList = classNames.split('>'); // pass the array as a reference const result = []; // traverse the dom from the root traverseDOM(element, classList, 0, result); // return the result return result; } // helper function function traverseDOM(element, classNames, index, result){ // if the element is not present if(!element) { return; } // get the current class name const targetClass = classNames[index]; // if the last class of the classNames // and the element contains the class. // add the element to the result if(index === classNames.length - 1 && element.classList.contains(targetClass)) { result.push(element); return; } // iterate each children of the element for(const child of element.children) { // if the child has the class // recursively traverse and search for the next class in the child // thus increase the index by one if(element.classList.contains(targetClass)) { traverseDOM(child, classNames, index + 1, result); } // else start the search from the scratch in the child else { traverseDOM(child, classNames, 0, result); } } }
Input: <div class="a" id="root"> <div class="b" id="b-1"> <div class="c" id="c-1"> </div> <div class="c" id="c-2"> </div> </div> <div class="b" id="b-2"> <div class="c" id="c-3"> </div> </div> </div> console.log(getByClassNameHierarchy(document.getElementById('root'), 'a>b>c')); Output: [ <div class="c" id="c-1"></div>, <div class="c" id="c-2"></div>, <div class="c" id="c-3"></div> ]