I'm trying to go through all of the elements in the document and pull the ones with a target class name. Importantly, I'm needing to do it without the use of document.getElementsByClassName(className)
/ document.querySelectorAll
, etc. — that's the point of this learning exercise.
Here's the javascript:
var getElementsByClassName = function(className){
var rootElem = document.body;
var collectionResult = [];
if (rootElem.getAttribute("class") == className) {
collectionResult.push(rootElem);
};
var nextTier = function(collectionResult, rootElem) {
var thisTier = rootElem.children;
for (i=0; i<thisTier.length; i++) {
var classes = thisTier[i].getAttribute("class");
if (classes != undefined && classes.includes(className)) {
collectionResult.push(thisTier[i]);
};
var childrenArray = thisTier[i].children;
if (childrenArray.length > 0) {
nextTier(collectionresult, childrenArray)
};
};
};
nextTier(collectionResult, rootElem);
return collectionResult;
};
Here's the section of the HTML structure I'm having trouble with:
<p>
<div class="somediv">
<div class="innerdiv">
<span class="targetClassName">yay</span>
</div>
</div>
</p>
The code works for the rest of the page with any number of non-nested elements. But as soon as var childrenArray = thisTier[i].children
get to the div.somediv
element, it has childrenArray == undefined
rather than pulling the div.innerdiv
element.
Am I misunderstanding how element.children
works?
You seem to be overcomplicating things.
function getElementsByClassName(className, root) {
if(!root) root = document.documentElement;
return [].reduce.call(root.children, function(arr, child) {
if(child.classList.contains(className)) arr.push(child);
return arr.concat(getElementsByClassName(className, child))
}, []);
}
function getElementsByClassName(className, root) {
if(!root) root = document.documentElement;
return [].reduce.call(root.children, function(arr, child) {
if(child.classList.contains(className)) arr.push(child);
return arr.concat(getElementsByClassName(className, child))
}, []);
}
console.log(getElementsByClassName("targetClassName"));
<div class="somediv targetClassName">
<div class="innerdiv">
<span class="targetClassName">yay1</span>
</div>
</div>
<div class="somediv targetClassName">
<div class="innerdiv targetClassName">
<span class="targetClassName">yay2</span>
</div>
</div>
<div class="somediv">
<div class="innerdiv">
<span class="targetClassName">yay3</span>
</div>
</div>