0

I'm attempting to build a set of HTML elements from a JSON object. I've managed to successfully construct the object from HTML elements, but the recursive rebuild keeps failing on me. Anyone have a good solution?

My JSON:

{
    "0": {
        "id": "text-1",
        "tag": "div",
        "style": {
            "left": "92px",
            "top": "37px",
            "z-index": "3",
            "height": "19px",
            "width": "98px",
            "font-weight": "bold",
            "font-style": "italic",
            "font-size": "16px",
            "color": "rgb(255, 255, 255)"
        },
        "data": {},
        "children": {
            "0": {
                "tag": "span",
                "style": {},
                "data": {},
                "html": "This is a test.",
                "text": "This is a test."
            }
        }
    },
    "1": {
        "id": "image-1",
        "tag": "div",
        "style": {
            "width": "100px",
            "height": "133px",
            "left": "91px",
            "top": "8px",
            "z-index": "1"
        },
        "data": {},
        "children": {
            "0": {
                "tag": "img",
                "style": {},
                "data": {},
                "html": "",
                "text": "",
                "src": "http://img2.etsystatic.com/000/0/6490841/il_570xN.351801334.jpg"
            }
        }
    },
    "2": {
        "id": "video-1",
        "tag": "div",
        "style": {
            "width": "100px",
            "height": "50px",
            "left": "5px",
            "top": "85px",
            "z-index": "2"
        },
        "data": {},
        "children": {
            "0": {
                "tag": "a",
                "style": {
                    "background-image": "url(http://placehold.it/100x50&text=Video)",
                    "height": "100%",
                    "width": "100%",
                    "display": "block",
                    "background-position": "0% 0%",
                    "background-repeat": "no-repeat no-repeat"
                },
                "data": {},
                "html": "",
                "text": ""
            }
        }
    }
}
5
  • 5
    Umm... You haven't shown your actual recursive code, so no way for us to answer you. On top of that, you've managed to recreate XML in an even more bloated fashion than simply serializing XML itself using a serialization format known for being more svelt than XML (JSON). If this is from an AJAX request, why not just use the responseXML parameter, grab the root node, and then just attach it into your HTML document where you want it? Commented Jul 23, 2012 at 16:12
  • 2
    You should really use Arrays instead of integer-numbered-property objects... Commented Jul 23, 2012 at 16:23
  • What is that fancy "html" property? Commented Jul 23, 2012 at 16:24
  • I think it would be more natural that you will pass an array of objects, instead of assigning each tag to property with integer numbered index Commented Jul 23, 2012 at 16:24
  • Please post some of the recursive code. Commented Jul 23, 2012 at 16:42

2 Answers 2

1

I've played a little and came up with this: http://jsfiddle.net/tfBRN/10/

considering that I have no idea for what is the data property and how html and text properties are related to each other, this code could be improved.

-edit-

I've assumed that the elements and children are given in array and not as numbered properties. And I've used jQuery to create elements, add properties and insert into DOM, but of course this can be performed using native DOM methods.

var domArray = [
    {
        "id": "text-1",
        "tag": "div",
        "style": {
            "left": "92px",
            "top": "37px",
            "z-index": "3",
            "height": "19px",
            "width": "98px",
            "font-weight": "bold",
            "font-style": "italic",
            "font-size": "16px",
            "color": "rgb(100, 100, 100)"
        },
        "data": {},
        "children": [
            {
                "tag": "span",
                "style": {},
                "data": {},
                "html": "This is a test.",
                "text": "This is a test."
            }
        ]
    },
    {
        "id": "image-1",
        "tag": "div",
        "style": {
            "width": "100px",
            "height": "133px",
            "left": "91px",
            "top": "8px",
            "z-index": "1"
        },
        "data": {},
        "children": [
            {
                "tag": "img",
                "style": {},
                "data": {},
                "html": "",
                "text": "",
                "src": "http://img2.etsystatic.com/000/0/6490841/il_570xN.351801334.jpg"
            }
        ]
    },
    {
        "id": "video-1",
        "tag": "div",
        "style": {
            "width": "100px",
            "height": "50px",
            "left": "5px",
            "top": "85px",
            "z-index": "2"
        },
        "data": {},
        "children": [
            {
                "tag": "a",
                "style": {
                    "background-image": "url(http://placehold.it/100x50&text=Video)",
                    "height": "100%",
                    "width": "100%",
                    "display": "block",
                    "background-position": "0% 0%",
                    "background-repeat": "no-repeat no-repeat"
                },
                "data": {},
                "html": "",
                "text": ""
            }
        ]
    }
];

$(document).ready(function(){
    for(var i=0;i<domArray.length;i++) {
        createDOMStructure(domArray[i]);
    }
});

function createDOMStructure(obj, parent) {
    if(parent == undefined) {
        parent = $("body"); // or any other element that would be the parent container of all structure
    }
    
    var element = $("<" + obj.tag + ">");
    delete obj.tag;
    
    if(obj.children) {
        for(var i=0;i<obj.children.length;i++) {
            createDOMStructure(obj.children[i], element);
        }
        delete obj.children;
    }
    
    element.css(obj.style);
    delete obj.style;
    
    element.text(obj.text);
    delete obj.text;

    for(var prop in obj) {
        element.attr(prop, obj[prop]);
    }
    
    $(element).appendTo(parent);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

Sign up to request clarification or add additional context in comments.

3 Comments

I'll work on updating the object to produce arrays instead of numbered indexes, but I think you've just about nailed it. The 'data' property is used to store various bits of data relevant to functions that will be run against the elements. 'html' and 'text' are pretty much interchangeable, now that I have all of the attributes mapped out. Forgot to remove the 'html' property after ironing out this bit. Marking your solution as the answer. Thank you :)
I've updated the object to reflect the structure suggested in your fiddle, and am able to log the correctly built elements in my console. However, 'parent' is assigned to Window, despite having been assigned to $("#container"). Any thoughts on why that is?
Solved the issue by removing the conditional and explicitly assigning the var. Thanks again for the great solution :)
0

Take a look at my solutions on GitHub:

https://github.com/mlromramse/JsonDecorator

That piece of node app uses HandleBars to perform the recursion. It was made for a different problem but should be applicable for this as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.