Reputation: 11755
This is problem I was asked and am wondering how to do or whether it's a trick question. I've only been working with JavaScript for a short while, so I'm not too sure.
Assume you have a web page with lots of content. Without using any library or getElementsByClassName, traverse the DOM and find all elements which have a particular class name.
Sample HTML
<body>
<div>
<div class='myTarget'>
Target exists here
</div>
</div>
<div>
<table>
<tbody>
<tr> <td class='myTarget'> Target exists here </td> </tr>
</tbody>
</table>
</div>
<div>
<span class='myTarget notSameAsTarget'>Stuff<span>
</div>
</body>
My first thought is that this should be a recursive function and should start at the root document.documentElement
JS:
var root = document.documentElement;
var targetClass = 'myTarget';
var elementsWithTargetClass = []; // store in array
function traverse(element, targetClassName){
// get class of current element
var currentClass = element.className;
// add to array if class matches
if(currentClass.trim() === targetClassName)
elementsWithTargetClass.push(element);
// recursive call
if(element.children){
traverse(element, targetClassName);
}
}
Any suggestions on what I'm missing?
// recursive call - updated
if(element.children){
for(var child in element.children)
traverse(element.children[child], targetClassName);
}
Upvotes: 2
Views: 1354
Reputation: 36438
Taking into account elements with multiple classes, and starting with body
:
var targetClass = 'myTarget';
var elementsWithTargetClass = []; // store in array
var re = new RegExp("\\b" + targetClass + "\\b");
traverse(document.body);
for ( var j = 0; j < elementsWithTargetClass.length; ++j )
elementsWithTargetClass[j].style.fontWeight = "bold";
function traverse(element, targetClassName){
// get class of current element
var currentClass = element.className;
if (currentClass.match(re))
// add to array if class matches
// if(currentClass.trim() === targetClassName)
elementsWithTargetClass.push(element);
// recursive call
if(element.children){
for ( var i = 0; i < element.children.length; ++i )
traverse(element.children[i]);
}
}
<div>
<ul>
<li class="myTarget">this</li>
<li class="myTarget andAnotherClass">also this</li>
<li>not this</li>
</ul>
</div>
Upvotes: 2
Reputation: 14649
var root = document.documentElement;
var targetClass = 'myTarget';
var elementsWithTargetClass = []; // store in array
pre_order(root);
function pre_order(node) {
if(node.className == targetClass)
elementsWithTargetClass.push(node);
for(var i=0; i < node.childNodes.length; i++)
pre_order(node.childNodes[i]);
}
console.log(elementsWithTargetClass);
Upvotes: 1
Reputation: 33409
Use document.querySelector
. This is not getElementsByClassName()
, nor a library. ;)
document.querySelector('.myTarget')
Upvotes: 2
Reputation: 646
Your recursive call to traverse() passes the same element that was initially passed in, so it's just doing the exact same thing over and over until the stack overflows (hey!). You need to call traverse for each of the children of element rather than passing element back in.
Upvotes: 8
Reputation: 3575
You are getting into to many recursions which makes the call stack grow to high. Try chaning your recursive function into a loop. This should not give you any problems.
Upvotes: 1