I worked on some code to show the classes that were being used on some div’s for a presentation. I wanted to be able to have the text of the class attribute show in the final container to give an idea of how the layout ended up looking and why it looked that way.
This is basically a problem of finding all the last nodes in every branch of a tree. The div’s in my case were not all the same depth from the top container
<div id="top">
<div>
<div></div>
<div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div>
<div>
<div></div>
<div></div>
</div>
<div>
<div>
<div></div>
<div></div>
</div>
<div></div>
</div>
<div></div>
</div>
</div>
The way the code works is you recursively call a function that looks at all the children nodes of a node. Then you pass the children to the same function. You check to see if the node you are on has no more children and when that’s true you know you have reached the bottom of a branch in your markup tree. In my example I was using jQuery.children() but the base DOM has a similar ChildNodes function.
function ShowLowestDivStyle(parent) {
var children = parent.children();
if (children.length > 0) {
children.each(function (index) {
ShowLowestDivStyle($(children[index]));
});
}
else {
//This branch lets us use the last node
parent.text(parent.attr('class'));
}
}
However afterward I wanted to see if I could do the same thing with a closed from solution. My idea is to create a loop where each time we take a list of current nodes and check if they have children. If not we perform some sort of action on them. Else we get rid of our current node list and then promote our list of children to current nodes. This loop would walk down a tree one level of depth at a time.
function WorkingWithChildren(rootNode){
var depth = 0;
var currentNodes = $();
currentNodes = rootNode.children('div');
//Find all the end nodes in each branch
while (currentNodes.length > 0) {
//Get the next set of child nodes
var nextNodes = currentNodes.children('div');
//Perform actions on childless nodes
currentNodes.each(function () {
//Convert DOM node to jQuery node
var jNode = $(this);
if(jNode.children('div').length == 0){
jNode.text(depth);
jNode.attr('style', 'margin-left:' + depth + '0px;');
}
});
//Update the list of current nodes
currentNodes = nextNodes;
depth++;
}
}
If you run the script you should see each div gets indented by its level of depth and contains its level in the tree.
