Creating a nested list using an array of objects

I have an SQL dataset that will change frequently, and I need to regularly create nested unordered lists. I converted the SQL data into an array of objects, but I was fixated on the logic to create an unordered list.

I tried to make a recursive function, but I do not experience this enough, therefore

The data contains the following fields:

ID Category Name ParentID 

Thus, each category has an identifier and a ParentID (which corresponds to the identifier of another category). All root categories have the same dummy ParentID.

The javascript object has the same properties. Here is an example:

 var Categories = [ new Category(1, 'Root', 0), new Category(2, 'Cat1', 1), new Category(3, 'Cat2', 2), new Category(4, 'Cat3', 5), new Category(5, 'Cat4', 1), new Category(6, 'Cat5', 5), new Category(7, 'Cat6', 5), new Category(8, 'Cat7', 1), new Category(9, 'Cat8', 2), new Category(10, 'Cat9', 1), new Category(11, 'Cat10', 10), new Category(12, 'Cat11', 1), new Category(13, 'Cat12', 8) ] 

I need to use this array of objects to make an unordered list that will look like this:

 <ul> <li>Cat1 <ul> <li>Cat2</li> <li>Cat8</li> </ul> <li>Cat4 <ul> <li>Cat3</li> <li>Cat5</li> <li>Cat6</li> </ul> </li> <li>Cat7 <ul> <li>Cat12</li> </ul> </li> <li>Cat8</li> <li>Cat9 <ul> <li>Cat10</li> </ul> </li> <li>Cat11</li> </ul> 

At present, my deepest data is 3 levels, but I would like to be able to script to do any number of levels.

jQuery is suitable for this.

+6
source share
4 answers

Here is a cool approach. Depth is unlimited. The only requirement is that the parent must exist before the child is added.

 // create class // parent is optional Category var Category = function (id, name, parent) { this.id = id; this.name = name; this.parent = null; this.children = []; if (parent) { parent.add(this); } }; Category.prototype.root = function() { if (this.parent) return this.parent.root(); return this; } // find by id Category.prototype.find = function (id) { if (this.id == id) return this; var found; for (var i = 0, il = this.children.length; i < il; i++) { if (found = this.children[i].find(id)) return found; } return null; }; // create relationship Category.prototype.add = function (cat) { cat.parent = this; this.children.push(cat); }; // render list for item Category.prototype.renderList = function ($parentElem) { var $nameElem = $('<li>' + this.name + '</li>').appendTo($parentElem); if (this.children.length) { this.renderChildren($('<ul />').appendTo($nameElem)) } } // create child elements and add them to the parent Category.prototype.renderChildren = function ($parentElem) { for (var i = 0, il = this.children.length; i < il; i++) { this.children[i].renderList($parentElem); } } function createCategory(id, name, parentId) { rootCat.find(parentId).add(new Category(id, name)); } // add items var rootCat = new Category(1, 'root'); createCategory(2, 'Cat1', 1); createCategory(3, 'Cat2', 2); createCategory(4, 'Cat3', 3); createCategory(14, 'Cat3.5', 4); createCategory(5, 'Cat4', 1); createCategory(6, 'Cat5', 5); createCategory(7, 'Cat6', 5); createCategory(8, 'Cat7', 1); createCategory(9, 'Cat8', 2); createCategory(10, 'Cat9', 1); createCategory(11, 'Cat10', 10); createCategory(12, 'Cat11', 1); createCategory(13, 'Cat12', 8); // render rootCat.renderChildren($('#cats')); 

jsFiddle

+3
source

Demo : http://jsfiddle.net/4JpsW/

 function Category(id, categoryName, parentId){ this.id = id; this.categoryName = categoryName; this.parentId = parentId; } var categories = [ new Category(1, 'Root', 0), new Category(2, 'Cat1', 1), new Category(3, 'Cat2', 2), new Category(4, 'Cat3', 5), new Category(5, 'Cat4', 1), new Category(6, 'Cat5', 5), new Category(7, 'Cat6', 5), new Category(8, 'Cat7', 1), new Category(9, 'Cat8', 2), new Category(10, 'Cat9', 1), new Category(11, 'Cat10', 10), new Category(12, 'Cat11', 1), new Category(13, 'Cat12', 8) ]; categories.sort(function(a,b){ return a.parentId < b.parentId ? -1 : (a.parentId > b.parentId ? 1 : 0); }); var root = document.createElement('ul'), currentParentId=1, currentParentUl=root; for(var i=1; i < categories.length; ++i){ if(categories[i].parentId !== currentParentId){ currentParentId = categories[i].parentId; currentParentUl = document.createElement('ul'); root.getElementsByClassName('category_'+currentParentId)[0] .appendChild(currentParentUl); } currentParentUl.innerHTML += '<li class="category_'+categories[i].id+'">'+categories[i].categoryName+'</li>'; } document.body.appendChild(root); 

Note 1 Like the @DanielGimenez code, the depth is unlimited and the parent must exist before the child is added.

Note 2 My code uses the native functions sort and getElementsByClassName to do the most expensive part (sorting and searching) for better performance.

Note 3 I used classes instead of ids to avoid conflicts with other parts of your page. But if this is not a problem, using ids will increase speed.

Here you can compare the performance: http://jsperf.com/creating-a-nested-list-with-an-object-array

+2
source

Short and dirty jQuery. This destroys the array. Not so effective, but it is not. http://jsfiddle.net/4JpsW/

 function drawList(cat) { r = $('<div></div>').attr('data-id', '1'); r.append($('<ul></ul>')); $('body').append(r) while (cat.length > 0) { if (cat[0].parent == 0) { cat.splice(0, 1); continue; } var i = 0; while ($('*[data-id=' + cat[i].parent + ']').length == 0) { i++; } elem = $('<li></li>') .attr('data-id', cat[i].id) .text(cat[i].name); parent_elem = $('*[data-id=' + cat[i].parent + ']') if (parent_elem.find('>ul').length == 0) parent_elem.append($('<ul></ul>')); parent_elem.find('>ul').append(elem); cat.splice(i, 1); } } 
0
source

This is what I use, with it you can have multiple root parents.

Js

  function loadCatList() { var li_str = ''; db.transaction(function (tx) { tx.executeSql('SELECT * FROM categories c,categories_description cd WHERE c.categories_id = cd.categories_id ORDER BY categories_id', [], function (tx, results) { var len = results.rows.length, i; var categories=[]; for (i = 0; i < len; i++) { var r = results.rows.item(i); categories[r.categories_id] = r; var catID = r.categories_id; } generate_tree_list=function(array, parent, level){ var has_children = false; for(key in array) { var value=array[key]; if (value['parent_id'] == parent) { if (has_children === false) { has_children = true; if(level === 0){ li_str += '<ul>'; }else{ li_str += '<ul>'; } level++; } li_str += '<li id="'+ value['categories_id'] +'"><a href="productsList.html?cPath='+ value['categories_id'] +'" data-ajax="false"><h3>' + value['categories_name'] + '</h3><p>' + value['categories_image'] + '</p></a>' generate_tree_list(array, key, level); li_str += '</li>'; } } if (has_children === true) li_str += '</ul>'; } generate_tree_list(categories,0,0); $('#parents').html(li_str); }); }); } 

HTML

 <div id="catItems"><script>loadCatList();</script> <div id="parents"></div> 
0
source

Source: https://habr.com/ru/post/950312/


All Articles