I am having some difficulties with this problem. I want to render some html elements given a tree structure. For example this javascript tree object:
let htmlTree = {
id: "a",
children: [{
id: "b",
children: []
}, {
id: "c",
children: [{
id: "d",
children: []
}]
}]
};
Should output a string like this:
<a>
<b>
</b>
<c>
<d></d>
</c>
</a>
What I tried doing was a breadth first traversal (iterative) of the tree object but was having some issues actually knowing when to apply the close tag of the element for the nested cases. Any help is appreciated, i've been stumped on this all day :(
I am having some difficulties with this problem. I want to render some html elements given a tree structure. For example this javascript tree object:
let htmlTree = {
id: "a",
children: [{
id: "b",
children: []
}, {
id: "c",
children: [{
id: "d",
children: []
}]
}]
};
Should output a string like this:
<a>
<b>
</b>
<c>
<d></d>
</c>
</a>
What I tried doing was a breadth first traversal (iterative) of the tree object but was having some issues actually knowing when to apply the close tag of the element for the nested cases. Any help is appreciated, i've been stumped on this all day :(
Share Improve this question asked Aug 3, 2015 at 4:12 thunderousNinjathunderousNinja 3,5209 gold badges39 silver badges49 bronze badges 2- And why not try a depth first traversal? The solution is pletely natural. – BaseZen Commented Aug 3, 2015 at 4:14
- Do you need the line breaks in the result? – markasoftware Commented Aug 3, 2015 at 4:14
4 Answers
Reset to default 2I know you already have an answer for this, but I thought this was valid to add to the discussion. You can have the Javascript dom functions do the heavy lifting for you. This might be valuable in more plex scenarios.
function create_node(obj){
var node = document.createElement(obj.id);
for (var i in obj.children) {
node.appendChild(create_node(obj.children[i]));
}
return node;
}
console.log(create_node({id:'root',children:[htmlTree]}).innerHTML);
JSFiddle: http://jsfiddle/trex005/8gxe7z3b/
note : to get the full HTML, I wrapped it in a parent node to use innerHTML since there is no cross browser way of getting the outterHTML.
This'll make the string without line breaks...and I'm using var
instead of let
for more patibility
var outputStr='';
function checkChildren(parentObj){
outputStr+='<'+parentObj.id+'>';
if(parentObj.children.length>0)
parentObj.children.forEach(checkChildren);
outputStr+='</'+parentObj.id+'>';
}
checkChildren(htmlTree);
And it is easy to modify if you do need it to have the line breaks. Here's a working jsfiddle
Try this
var treeRendrer = function(treeObj,parent){
if(treeObj && treeObj.hasOwnProperty("id")){
parent.appendChild(document.createElement(treeObj["id"]))
}
if(treeObj && treeObj.hasOwnProperty("children")){
treeObj.children.forEach(function(childObj){
treeRendrer(childObj, parent.firstChild)
});
}
}
I spent a lot of time doing something like this and in my efforts I built a really efficient framework which uses a object-orient approach, little more plex but it allows for very quick development, with an API like interface.
- Declare a JSON object in a very simple syntax as shown in the code
- Declare a object-specific create method (Form.prototype.create) and specify how to build the object.
- Then simply call the Build()-function and pass the JSON object as the argument. example --- Build(signin)
//CODE
<!DOCTYPE html>
<html>
<head>
<script>
//SIMPLE JSON SYNTAX
var signin = [
{"container":{"element": "aside", "attributes": {"id":"overlay","class":"overlay1","onclick":"Destroy(event);"}}},
{"form":{"element": "form", "attributes": {"id":"form"}}},
{"msg":{"element": "mark", "attributes": {"id":"form-msg"}}},
{"ipt1":{"element": "input", "attributes": {"type":"email","placeholder":"email","name":"email"}}},
{"ipt2":{"element": "input", "attributes": {"type":"password","placeholder":"password","name":"password"}}},
{"ipt3":{"element": "input", "attributes": {"type":"button","value":"Sign In","class":"form-btn btn-blue", "data-url":"/core/signin.php","onclick":"Submit(this);"}}},
{"ipt4":{"element": "input", "attributes": {"type":"button","value":"Account Recovery","class":"form-btn btn-black","data-form":"recover","onclick":"Build(recover)"}}}
];
//MAIN BUILD FUNCTION
function Build(obj){
//CREATE NEW FORM OBJECT WITH DYNAMIC PROP AND VALUES
var form = Form.new(obj);
//CREATE HTML ELEMENTS AND APPEND ITS ATTRIBUTES
form.assemble();
//DEFINE HOW YOU WANT THE OBJECT TO BE ASSEMBLED
form.create();
}
//DYNAMIC FORM CONSTRUCTOR
function Form(){
for(var i=0; i < arguments.length; i++){
var key = Object.keys(arguments[i]);
this[key] = arguments[i][key];
}
}
//FORM OBJECT CONSTRUCTOR METHOD (CREATE)
Form.prototype.create = function(){
var inpts = Object.keys(this).splice(3);
var container = document.body.appendChild(this.container);
var form = container.appendChild(this.form);
container.appendChild(this.msg);
for(i=0; i < inpts.length; i++){
form.appendChild(this[inpts[i]]);
}
}
//GLOBAL FUNCTION METHOD (NEW)
Function.prototype.new = function (args) {
var Fake = Object.create(this.prototype);
this.apply(Fake, args);
return Fake;
};
//GLOBAL OBJECT METHOD (ASSEMBLE)
Object.prototype.assemble = function(){
for(key in this){
if(this.hasOwnProperty(key)){
var element = document.createElement(this[key].element);
var attributes = this[key].attributes;
for(prop in attributes){
if(attributes.hasOwnProperty(prop)){
element.setAttribute(prop, attributes[prop]);
this[key] = element;
}
}
}
}
}
</script>
</head>
<body></body>
</html>