patternjavascriptMinor
Creating lists and sublists dynamically
Viewed 0 times
sublistsdynamicallycreatinglistsand
Problem
I'm working on a simple little one page website for giving a presentation and I have some working code now, but I'm thinking there has to be a more elegant way of doing this. I would describe myself, at best, as a "dabbler" in JavaScript at this point; I'm much more comfortable with statically-typed languages and am doing this as a learning exercise.
Here's my JSFiddle showing what I am doing.
In my "real" site, the
The segment of this that makes me the most uneasy is this:
I don't like how I am having to add
In case it isn't obvious from the fiddle, the page should show a list of main points, and, if they exist, subpoints under each main point. I'm basically trying to mimic PowerPoint.
Any criticisms of this code would be gladly accepted; I know this probably isn't idiomatic JavaScript.
Here's my JSFiddle showing what I am doing.
In my "real" site, the
PageContent object is coming from an AJAX POST response (via an instance of node.js). I've included all of that code to make it easier to understand what is going on (any suggestions on how to restructure that server-side code would also be appreciated). If I have the time, I'll probably read these "points" from a config file or something else, but for now, a switch statement fits my needs.The segment of this that makes me the most uneasy is this:
$('#pageContent').append('' + mp.main);
if (mp.subPoints.length > 0){
$('li#'+i).append('');
$.each(mp.subPoints, function(index, sp){
$('li#'+i+' ul').append('' + sp + '');
});
$('li#'+i).append('');
}
$('#pageContent').append('');I don't like how I am having to add
id values to my list items so I can then append my subpoints to the correct parent. Is there a less hacky-feeling way to go about this?In case it isn't obvious from the fiddle, the page should show a list of main points, and, if they exist, subpoints under each main point. I'm basically trying to mimic PowerPoint.
Any criticisms of this code would be gladly accepted; I know this probably isn't idiomatic JavaScript.
Solution
This will depend on your content and how you prepare it, but I'd suggest a very generic solution that'll work for any level of nested points. Now, arbitrary nesting doesn't appear to be required in your case, but, hey, nice to have.
Suppose your JSON content is structured like so:
You'll note that you can just keep nesting the points indefinitely.
To render this as HTML, you can use a recursive function. Like this:
And call it like so:
The point is that since the structure is recursive, it can nest to any depth, but the code is simpler.
Here's a jsfiddle. This is quite a different approach, and Daniel Cook's answer is probably more immediately applicable to you current code, but I thought it worth to point out.
You could also extend it to add the "1", "1.1", "1.2" (and so on) numbers to the titles.
Suppose your JSON content is structured like so:
var points = [
{title: "Point", children: [
{title: "Point"},
{title: "Point"},
{title: "Point"},
{title: "Point", children: [
{title: "Point"},
{title: "Point"},
{title: "Point", children: [
// more...?
]}
]}
]}
]You'll note that you can just keep nesting the points indefinitely.
To render this as HTML, you can use a recursive function. Like this:
function buildList(parentElement, items) {
var i, l, list, li;
if( !items || !items.length ) { return; } // return here if there are no items to render
list = $("").appendTo(parentElement); // create a list element within the parent element
for(i = 0, l = items.length ; i ").text(items[i].title); // make a list item element
buildList(li, items[i].children); // add its subpoints
list.append(li);
}
}And call it like so:
buildList($("#pageContent").empty(), points);The point is that since the structure is recursive, it can nest to any depth, but the code is simpler.
Here's a jsfiddle. This is quite a different approach, and Daniel Cook's answer is probably more immediately applicable to you current code, but I thought it worth to point out.
You could also extend it to add the "1", "1.1", "1.2" (and so on) numbers to the titles.
Code Snippets
var points = [
{title: "Point", children: [
{title: "Point"},
{title: "Point"},
{title: "Point"},
{title: "Point", children: [
{title: "Point"},
{title: "Point"},
{title: "Point", children: [
// more...?
]}
]}
]}
]function buildList(parentElement, items) {
var i, l, list, li;
if( !items || !items.length ) { return; } // return here if there are no items to render
list = $("<ul></ul>").appendTo(parentElement); // create a list element within the parent element
for(i = 0, l = items.length ; i < l ; i++) {
li = $("<li></li>").text(items[i].title); // make a list item element
buildList(li, items[i].children); // add its subpoints
list.append(li);
}
}buildList($("#pageContent").empty(), points);Context
StackExchange Code Review Q#34002, answer score: 3
Revisions (0)
No revisions yet.