Question

I've found an angular directive which takes an object like below and turns it into an expandable tree:

$scope.dataForTheTree =
[
    { "name" : "Joe", "age" : "21", "children" : [
        { "name" : "Smith", "age" : "42", "children" : [] },
        { "name" : "Gary", "age" : "21", "children" : [
            { "name" : "Jenifer", "age" : "23", "children" : [
                { "name" : "Dani", "age" : "32", "children" : [] },
                { "name" : "Max", "age" : "34", "children" : [] }
            ]}
        ]}
    ]},
    { "name" : "Albert", "age" : "33", "children" : [] },
    { "name" : "Ron", "age" : "29", "children" : [] }
];

I think this is JSON since the properties are text elements but I've tried the directive with properties and not string and it still works. So name instead of "name". I was given this piece of code which loops through an XML and returns an object which looks like this:

    {
        homesite: { //I need to remove the properties homesite, subsite1, subsite2, etc
                  url: url,
                  title: title,
                  children: { //the child objects need to be wrapped in an array [{},{}...]
                             {
                              subsite1: url: url,
                                        title: title,
                                        children:{}
                             }{
                              subsite2: url: url,
                                        title: title,
                                        children:{}
                             }
                            }
                   }
    }

It's basically a map of my site and each child element are sub-sites and their information.

This is the function I've used to parse my XML and create the site map:

    var map = {}; //init the map
    var web = $(xData.responseXML).find("Web").map(function () {
        return $(this).attr('Url');
    });
    var webTitle = $(xData.responseXML).find("Web").map(function () {
        return $(this).attr('Title');
    });  

    // create map
    //goes through the XML to get each site address
          var item = web[i], 
    //goes through XML to get each site Title
           title = webTitle[i], 
    //Breaks down URL to identify subsites
           parts = item.split('/'), 
    //Always top level site
           domain = parts.splice(0, 3).join('/'),
           current;  

    //Checks if the map object is empty, sets collection properties
    if ($.isEmptyObject(map)) map = {url:domain, title:title ,children:[]};
            current = map[domain].children;

    for (var index in parts) {
        var part = parts[index];
        if (!current[part]) {
            current[part] = {url:domain+'/'+parts.slice(0,index+1).join('/'), title:title, children:{}};
        }
        current = current[part].children;
    }
}
siteMap = [map]

Problem: I'm having a really hard time figuring out how to modify it to return an object structure like the directive needs it to be. All the information is there but the structure isn't. For example the child are in contained in objects instead of arrays, the sites are all contained within properties (ex. site1:{} ) as oppose to (ex. [{title:site1, children:[{}]}] )

This is what the XML looks like:

<Webs xmlns="http://schemas.microsoft.com/sharepoint/soap/">
   <Web Title="Site1_Name" Url="http://Server_Name/sites/Site_Name" />
   <Web Title="Site2_Name" Url="http://Server_Name/sites/Site_Name/Subsite_1" />
   <Web Title="Site3_Name" Url="http://Server_Name/sites/Site_Name/Subsite_1/Subsite_2" />
   .
   .
   .
</Webs>
Was it helpful?

Solution

You'll have to write a recursive function that converts your format to the target format. Something like this:

function getNodeFromSite(site) {
    var node = { url: site.url, title: site.title };
    if (site.children) {
        node.children = [];
        for (var childName in site.children) {
            var child = site.children[childName];
            node.children.push(getNodeFromSite(child));
        }
    }
    return node; 
}

var tree = [];
for (var siteName in data) {
    var site = data[siteName];
    tree.push(getNodeFromSite(site));
}

Fiddle demo

Input:

var data = {
    homesite: {
        url: "http://www.mysite.com",
        title: "Home",
        children: {
            subsite: {
                url: "http://www.mysite.com/subsite",
                title: "Sub-site",
                children: { }
            }
        }
    }
};

Result:

[{
  "url":"http://www.mysite.com",
  "title":"Home",
  "children":[
     {
        "url":"http://www.mysite.com/subsite",
        "title":"Sub-site",
        "children":[

        ]
     }
  ]
}]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top