Reputation: 10571
The following almost works but if i remove the <a>
the json breaks with an empty node name:" "
and also i believe i am creating an array while i need the json in the format below. Here it is a jsFiddle too (see below the result for the output i am looking for).
What I am trying to do is to generate an object I can read from a nested list in order to generate a mind map (D3) like this
HTML
<div id="tree">
<ul class="sortable">
<li><a href="http://google.com">flare</a>
<ul class="sortable">
<li>analytics
<ul class="sortable">
<li><a href="http://google.com">cluster</a>
<ul class="sortable">
<li><a href="http://google.com">AgglomerativeCluster</a></li>
<li><a href="http://google.com">CommunityStructure</a></li>
<li><a href="http://google.com">HierarchicalCluster</a></li>
<li><a href="http://google.com">MergeEdge</a></li>
</ul>
</li>
<li><a href="http://google.com">graph</a>
<ul class="sortable">
<li><a href="http://google.com">BetweennessCentrality</a></li>
<li><a href="http://google.com">LinkDistance</a></li>
<li><a href="http://google.com">MaxFlowMinCut</a></li>
<li><a href="http://google.com">ShortestPaths</a></li>
<li><a href="http://google.com">SpanningTree</a></li>
</ul>
</li>
<li><a href="http://google.com">optimization</a>
<ul class="sortable">
<li><a href="http://google.com">AspectRatioBanker</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><a href="http://google.com">Pippo</a></li>
<li><a href="http://google.com">buonanotte</a></li>
<li><a href="http://google.com">Avantieri</a></li>
</ul>
</div>
<div id="d" style="margin-top: 40px; padding-top: 20px;">Output:<br><br><pre></pre></div>
<div id="d" style="margin-top: 40px; padding-top: 20px;">Output:<br><br><pre></pre></div>
<div id="json_results" style="margin-top: 40px; padding-top: 20px;">
Needs to become:
<pre style="padding-top: 20px;">
var root = JSON.parse( ' {
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster","url":"http://google.com"},
{"name": "CommunityStructure"},
{"name": "HierarchicalCluster"},
{"name": "MergeEdge"}
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality" },
{"name": "LinkDistance" },
{"name": "MaxFlowMinCut" },
{"name": "ShortestPaths" },
{"name": "SpanningTree" }
]
},
{
"name": "optimization",
"children": [
{"name": "AspectRatioBanker" }
]
}
]
},
{"name": "Pippo"},
{"name": "buonanotte" },
{"name": "Avantieri"}
]
} ') ;
</pre>
</div>
JS
$(document).ready(function () {
var out = [];
function processOneLi(node) {
var aNode = node.children("a:first");
var retVal = {
"name": aNode.text(),
"url": aNode.attr("href")
};
node.find("> .sortable > li").each(function() {
if (!retVal.hasOwnProperty("children")) {
retVal.children = [];
}
retVal.children.push(processOneLi($(this)));
});
return retVal;
}
$("#tree > ul > li").each(function() {
out.push(processOneLi($(this)));
});
$('#d pre').text(JSON.stringify(out, null, 2));
});
The json should become:
var root = JSON.parse( ' {
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster","url":"http://google.com"},
{"name": "CommunityStructure"},
{"name": "HierarchicalCluster"},
{"name": "MergeEdge"}
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality" },
{"name": "LinkDistance" },
{"name": "MaxFlowMinCut" },
{"name": "ShortestPaths" },
{"name": "SpanningTree" }
]
},
{
"name": "optimization",
"children": [
{"name": "AspectRatioBanker" }
]
}
]
},
{"name": "Pippo"},
{"name": "buonanotte" },
{"name": "Avantieri"}
]
} ') ;
but this is what i get instead:
[
{
"name": "flare",
"url": "http://google.com",
"children": [
{
"name": "",
"children": [
{
"name": "cluster",
"url": "http://google.com",
"children": [
{
"name": "AgglomerativeCluster",
"url": "http://google.com"
},
{
"name": "CommunityStructure",
"url": "http://google.com"
},
{
"name": "HierarchicalCluster",
"url": "http://google.com"
},
{
"name": "MergeEdge",
"url": "http://google.com"
}
]
},
{
"name": "graph",
"url": "http://google.com",
"children": [
{
"name": "BetweennessCentrality",
"url": "http://google.com"
},
{
"name": "LinkDistance",
"url": "http://google.com"
},
{
"name": "MaxFlowMinCut",
"url": "http://google.com"
},
{
"name": "ShortestPaths",
"url": "http://google.com"
},
{
"name": "SpanningTree",
"url": "http://google.com"
}
]
},
{
"name": "optimization",
"url": "http://google.com",
"children": [
{
"name": "AspectRatioBanker",
"url": "http://google.com"
}
]
}
]
}
]
},
{
"name": "Pippo",
"url": "http://google.com"
},
{
"name": "buonanotte",
"url": "http://google.com"
},
{
"name": "Avantieri",
"url": "http://google.com"
}
]
Here it is the jsFiddle (see below the result for the output i am looking for)
Upvotes: 0
Views: 208
Reputation: 338228
A small recursive function will do:
function listToObject(list) {
return $(list).first().children("li").map(function () {
var $this = $(this), $name = $this.children("a").first();
return {
// see http://stackoverflow.com/a/8851526
name: $name.text() || $this.clone().children().remove().end().text().trim(),
url: $name.attr("href"),
children: listToObject($this.children("ul"))
};
}).toArray();
}
var output = listToObject($("#tree > ul"));
console.log(output);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="tree">
<ul class="sortable">
<li><a href="http://google.com">flare</a>
<ul class="sortable">
<li>analytics
<ul class="sortable">
<li><a href="http://google.com">cluster</a>
<ul class="sortable">
<li><a href="http://google.com">AgglomerativeCluster</a></li>
<li><a href="http://google.com">CommunityStructure</a></li>
<li><a href="http://google.com">HierarchicalCluster</a></li>
<li><a href="http://google.com">MergeEdge</a></li>
</ul>
</li>
<li><a href="http://google.com">graph</a>
<ul class="sortable">
<li><a href="http://google.com">BetweennessCentrality</a></li>
<li><a href="http://google.com">LinkDistance</a></li>
<li><a href="http://google.com">MaxFlowMinCut</a></li>
<li><a href="http://google.com">ShortestPaths</a></li>
<li><a href="http://google.com">SpanningTree</a></li>
</ul>
</li>
<li><a href="http://google.com">optimization</a>
<ul class="sortable">
<li><a href="http://google.com">AspectRatioBanker</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><a href="http://google.com">Pippo</a></li>
<li><a href="http://google.com">buonanotte</a></li>
<li><a href="http://google.com">Avantieri</a></li>
</ul>
</div>
The output is a bit stricter than what you have asked for. Each object has a url
and children
, even if empty. This will actually make handling easier in the end.
Upvotes: 1
Reputation: 1407
I found your problem, there was one li element that didn't have element which you were looking for.
This will get you the results you're looking
$(document).ready(function () {
var out = [];
function processOneLi(node) {
var aNode = node.children("a:first");
var retVal = {};
if (aNode.text()) {
retVal = {
"name": aNode.text(),
"url": aNode.attr("href")
};
} else {
retVal = { "name": node.clone().children().remove().end().text().replace(/\r?\n|\r/g, " ") };
}
node.find("> .sortable > li").each(function() {
if (!retVal.hasOwnProperty("children")) {
retVal.children = [];
}
retVal.children.push(processOneLi($(this)));
});
return retVal;
}
$("#tree > ul > li").each(function() {
out.push(processOneLi($(this)));
});
$('#d pre').text(JSON.stringify(out, null, 2));
});
Upvotes: 0
Reputation: 782
Your problem is that Pippo, buonanotte and Avantieri are siblings of flare, instead of being nested under flare.
I think I got to the result you expected in this fiddle: http://jsfiddle.net/k7vSg/122/
HTML:
<div id="tree">
<ul class="sortable">
<li><a href="http://google.com">flare</a>
<ul class="sortable">
<li>analytics
<ul class="sortable">
<li><a href="http://google.com">cluster</a>
<ul class="sortable">
<li><a href="http://google.com">AgglomerativeCluster</a></li>
<li><a href="http://google.com">CommunityStructure</a></li>
<li><a href="http://google.com">HierarchicalCluster</a></li>
<li><a href="http://google.com">MergeEdge</a></li>
</ul>
</li>
<li><a href="http://google.com">graph</a>
<ul class="sortable">
<li><a href="http://google.com">BetweennessCentrality</a></li>
<li><a href="http://google.com">LinkDistance</a></li>
<li><a href="http://google.com">MaxFlowMinCut</a></li>
<li><a href="http://google.com">ShortestPaths</a></li>
<li><a href="http://google.com">SpanningTree</a></li>
</ul>
</li>
<li><a href="http://google.com">optimization</a>
<ul class="sortable">
<li><a href="http://google.com">AspectRatioBanker</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="http://google.com">Pippo</a></li>
<li><a href="http://google.com">buonanotte</a></li>
<li><a href="http://google.com">Avantieri</a></li>
</ul>
</li>
</ul>
</div>
<div id="d" style="margin-top: 40px; padding-top: 20px;">Output:<br><br><pre></pre></div>
<div id="json_results" style="margin-top: 40px; padding-top: 20px;">
Needs to become:
<pre style="padding-top: 20px;">
var root = JSON.parse( ' {
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster","url":"http://google.com"},
{"name": "CommunityStructure"},
{"name": "HierarchicalCluster"},
{"name": "MergeEdge"}
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality" },
{"name": "LinkDistance" },
{"name": "MaxFlowMinCut" },
{"name": "ShortestPaths" },
{"name": "SpanningTree" }
]
},
{
"name": "optimization",
"children": [
{"name": "AspectRatioBanker" }
]
}
]
},
{"name": "Pippo"},
{"name": "buonanotte" },
{"name": "Avantieri"}
]
} ') ;
</pre>
</div>
JS:
$(document).ready(function () {
var out = [];
function processOneLi(node) {
var aNode = node.children("a:first");
var retVal = {
"name": aNode.text(),
"url": aNode.attr("href")
};
node.find("> .sortable > li").each(function() {
if (!retVal.hasOwnProperty("children")) {
retVal.children = [];
}
retVal.children.push(processOneLi($(this)));
});
return retVal;
}
$("#tree > ul > li").each(function() {
out.push(processOneLi($(this)));
});
$('#d pre').text(JSON.stringify(out[0], null, 2));
});
Upvotes: 0