Birju Shah Birju Shah - 15 days ago 5
Javascript Question

Creating div based tree layout from json data

I am trying to generate div based tree layout dynamically using this array data.

[{
name: "Asset Cost Allocation",
children:[
{
name:"Child 1",
children: [{
name:"Child 1-1",
children:[
{
name:"Child 1-1-1"
}
]
},{
name:"child 1-2"
}]
},
{
name: "Child 2",
children:[{
name:"Child 2-1",
children:[{
name:"Child 2-1-1"
}]
}]
},
{
name: "Child 3",
children:[
{
name:"Child 3-1"
}
]
}
]
}]


I am iterating the json data and creting tree based html using the code below

var branch = {};
var depth = 0;
var rootNode = true;
var pointerBranch;
function renderTree(){
for(var i=0; i< window.data.length; i++){
if(window.data[i].children){
renderRootNode(depth,i,window.data[i]);
}
}
}
function renderRootNode(depth,i,node){
if(rootNode){
$('#wrapper').append("<span class='label'>"+node.name+"</span");
$('#wrapper').append("<div class='branch' id="+i+"-"+depth+"></div>");
pointerBranch = '#'+i+"-"+depth;
rootNode = false;
}else{
branch['branch-'+i+'-'+depth] = true;
$(pointerBranch).append("<div class='entry'><span class='label'>"+node.name+"</span><div class='branch' id="+i+"-"+depth+"></div></div>");
pointerBranch = '#'+i+"-"+depth;
}
depth++;
if(node.children){
for(var a=0;a<node.children.length;a++){
if(node.children[a].children){
renderRootNode(depth,a,node.children[a]);
if(a === node.children.length - 1){
depth -= 2;
pointerBranch = '#'+i+"-"+depth;
}
}else{
$(pointerBranch).append("<div class='entry'><span class='label'>"+node.children[a].name+"</span></div>");
if(a === node.children.length - 1){
depth -= 2;
pointerBranch = '#'+i+"-"+depth;
}
}
}
}
}

renderTree();


The issue is I am not able to name the div's properly and so the appending logic goes wrong. Can anyone suggest what needs to be changed.

I am also attaching jsfiddle for reference https://jsfiddle.net/birju112/2wL512bs/1/

Answer

I suggest you the following node-rendering function. It is a recursive one like yours but it does not use external variable that "simplify" its logic. All DOM structure is created in variables and then it is added to the page. The big difference is that the current element (refers to your pointerBranch variable) is passed as an argument.

function renderNode( node, element, index, depth )
{
    var nodeTitle = $("<span/>").addClass( "label" ).text( node.name );
    var branch = $("<div/>").addClass( "branch" ).attr( "id", index + "-" + depth );

    if( node.children )
    {
        for( var j = 0 ; j < node.children.length ; j++ )
        {
            var entry = $("<div/>").addClass( "entry" );

            renderNode( node.children[j], entry, j, depth + 1 );
            branch.append( entry );
        }
    }

    element.append( nodeTitle ).append( branch );
}

So the call in the renderTree function will be:

renderNode( window.data[i], $("#wrapper"), i, 0 );