I have some JSON data (simple array of objects) .
var input= [
{
"cat": "some",
"id": "0"
},
{
"cat": "some",
"id": "1"
},
{
"cat": "some/category",
"id": "2"
},
{
"cat": "some/category/sub",
"id": "3"
},
{
"cat": "some/other",
"id": "4"
},
{
"cat": "some/thing/different",
"id": "5"
},
{
"cat": "some/thing/different",
"id": "6"
},
{
"cat": "yet/another",
"id": "7"
}
]
I wanted to generate nested html list out of it based on categories:
My first step was to create empty nested object using the function:
createNestedObject = function(base, names) {
var = 0;
var results = [];
while (i < names.length) {
base = base[names[i]] = base[names[i]] || {};
results.push(i++);
}
return results;
}
Next i populated it with data using by spliting "cat" strings and pushing "ids" in loop (ex. some.category.sub.ids.push(7)) The final result was:
var output =
{
"some": {
"ids": [
"0",
"1"
],
"category": {
"ids": [
"2"
],
"sub": {
"ids": [
"3"
]
}
},
"other": {
"ids": [
"4"
]
},
"thing": {
"different": {
"ids": [
"5",
"6"
]
}
},
"yet": {
"another": {
"ids": [
"7"
]
}
}
}
}
However, the structure somewhat problematic because i don't know the key names and the nesting depth in advance. How to generate nested html list out of "output" or "input" data presented here?
How about this?
JS
function ToHTML(input){
var html = '<ul>';
for(var key in input){
if(input[key] instanceof Array){
for(var i = 0; i < input[key].length; i++){
html += '<li>' + input[key][i] + '</li>';
}
}else{
html += '<li>' + key + ToHTML(input[key]) + '</li>';
}
}
html += '</ul>';
return html;
}
function ToNestedObject(input){
var i, y, len = input.length, parts, partsLen, obj = {}, prev;
for(i = 0; i < len; i++){
parts = input[i].cat.split('/');
partsLen = parts.length;
prev = obj;
for(y = 0; y < partsLen; y++){
prev[parts[y]] = prev[parts[y]] || {};
prev = prev[parts[y]];
}
if(!prev.ids){
prev.ids = [];
}
prev.ids.push(input[i].id);
}
return obj;
}
var input= [
{
"cat": "some",
"id": "0"
},
{
"cat": "some",
"id": "1"
},
{
"cat": "some/category",
"id": "2"
},
{
"cat": "some/category/sub",
"id": "3"
},
{
"cat": "some/other",
"id": "4"
},
{
"cat": "some/thing/different",
"id": "5"
},
{
"cat": "some/thing/different",
"id": "6"
},
{
"cat": "yet/another",
"id": "7"
}
];
document.getElementById('test').innerHTML = ToHTML(ToNestedObject(input));
HTML
<div id='test'></div>
The array is converted into object tree
function buildTreeObject ( input ) {
var obj = {}, n ;
input.forEach( function( v ){
var keys = v.cat.split('/'),
n = obj ;
keys.forEach( function( k ){
if ( !n[k]) {
n[k] = {};
}
n = n[k];
});
n[ v.id ] = v.id ;
});
return obj;
}
and we need a function to build html
function buildHtml( obj , ul ) {
for (i in obj) {
var li = document.createElement('li');
li.innerHTML = i;
ul.appendChild( li );
if ( typeof(obj[i])== "object" ) {
childUl = document.createElement('ul');
li.appendChild( childUl );
buildHtml(obj[i], childUl );
}
}
}
and make html use of input
( ie ur array )
var ul = document.createElement('ul'),
tree = buildTreeObject( input ) ;
buildHtml( tree ,ul );
var div = document.createElement('div');
div.appendChild( ul );
console.log( div.innerHTML );
Which prints desired ul li list
You can see result in http://jsfiddle.net/r3RWL/
Since you added jquery under tags, I have written solution to your problem in jQuery. Here is the code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<div id="someDiv">
</div>
<script>
function prepareNestedStructure(input) {
var output = {},
catLevels,
currentCat;
$.each(input, function(index, catObject) {
catLevels = catObject.cat.split('/');
currentCat = output;
$.each(catLevels, function(index, name) {
if(!currentCat[name])
currentCat[name] = {};
currentCat = currentCat[name];
});
currentCat[catObject.id] = catObject.id;
});
return output;
}
function fillList(parentListEl, node) {
$.each(node, function(key, value) {
parentListEl.append('<li>' + key + '</li>');
if(jQuery.type(value) === 'object') {
var childEl = $('<ul></ul>');
parentListEl.append(childEl);
fillList(childEl, value);
}
});
}
var input= [
{
"cat": "some",
"id": "0"
},
{
"cat": "some",
"id": "1"
},
{
"cat": "some/category",
"id": "2"
},
{
"cat": "some/category/sub",
"id": "3"
},
{
"cat": "some/other",
"id": "4"
},
{
"cat": "some/thing/different",
"id": "5"
},
{
"cat": "some/thing/different",
"id": "6"
},
{
"cat": "yet/another",
"id": "7"
}
];
var output = prepareNestedStructure(input);
var ulDomElement = $('<ul></ul>');
fillList(ulDomElement, output);
$('#someDiv').append(ulDomElement);
</script>
</body>
</html>
what about this?
transform_deeply_nested_object = (dno) ->
result = ""
for key, value of dno
if value instanceof Array
result += "<ul>"
for elem in value
result += "<li>" + elem + "</li>\n"
result += "</ul>"
else
result += "<ul><li>" + key + "</li>"
result += transform_deeply_nested_object value
result += "</ul>"
Attention: Not tested!
Attention: This requires all leafs to be elements of an array always.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.