I have to dynamically create simple UL/LI menu structure with random number of items for all 7 levels. I need this for testing CSS styling.
Now, I wrote jQuery code for this purposes:
jQuery(document).ready(function($){
var menu = [];
var number = 5 + Math.floor(Math.random() * 5);
for (var i = 1; i <= number; i++) {
if ( Math.round(Math.random()) == 1 ) {
var submenu1 = [];
for ( var a = 1; a <= (4 + Math.floor(Math.random() * 5)); a++ ) {
if ( Math.round(Math.random()) == 1 ) {
var submenu2 = [];
for ( var b = 1; b <= (3 + Math.floor(Math.random() * 5)); b++ ) {
if ( Math.round(Math.random()) == 1 ) {
var submenu3 = [];
for ( var c = 1; c <= (3 + Math.floor(Math.random() * 4)); c++ ) {
if ( Math.round(Math.random()) == 1 ) {
var submenu4 = [];
for ( var d = 1; d <= (3 + Math.floor(Math.random() * 3)); d++ ) {
if ( Math.round(Math.random()) == 1 ) {
var submenu5 = [];
for ( var e = 1; e <= (3 + Math.floor(Math.random() * 2)); e++ ) {
if ( Math.round(Math.random()) == 1 ) {
var submenu6 = [];
for ( var f = 1; f <= (3 + Math.floor(Math.random() * 1)); f++ ) {
submenu6.push('<li class="item"><a href="#">Item '+f+'</a></li>');
}
parent6 = "parent";
subitems6 = '<ul class="submenu">'+submenu6.join('')+'</ul>';
} else {
parent6 = subitems6 = "";
}
submenu5.push('<li class="item"><a href="#">Item '+e+'</a>'+subitems6+'</li>');
}
parent5 = "parent";
subitems5 = '<ul class="submenu">'+submenu5.join('')+'</ul>';
} else {
parent5 = subitems5 = "";
}
submenu4.push('<li class="item '+parent5+'"><a href="#">Item '+d+'</a>'+subitems5+'</li>');
}
parent4 = "parent";
subitems4 = '<ul class="submenu">'+submenu4.join('')+'</ul>';
} else {
parent4 = subitems4 = "";
}
submenu3.push('<li class="item '+parent4+'"><a href="#">Item '+c+'</a>'+subitems4+'</li>');
}
parent3 = "parent";
subitems3 = '<ul class="submenu">'+submenu3.join('')+'</ul>';
} else {
parent3 = subitems3 = "";
}
submenu2.push('<li class="item '+parent3+'"><a href="#">Item '+b+'</a>'+subitems3+'</li>');
}
parent2 = "parent";
subitems2 = '<ul class="submenu">'+submenu2.join('')+'</ul>';
} else {
parent2 = subitems2 = "";
}
submenu1.push('<li class="item '+parent2+'"><a href="#">Item '+a+'</a>'+subitems2+'</li>');
}
parent1 = "parent";
subitems1 = '<ul class="submenu">'+submenu1.join('')+'</ul>';
} else {
parent1 = subitems1 = "";
}
menu.push('<li class="item '+parent1+'"><a href="#">Item '+i+'</a>'+subitems1+'</li>');
}
$("#topnav").html('<ul class="menu">'+menu.join('')+'</ul>');
});
My question is: is there some better (shorter) solution to achieve this goal?
btw, JSFiddle for this case is here http://jsfiddle.net/urosevic/Fy5jr/ where you can see how that code works. So, I'll love to learn how to optimize that JS code.
Thank you!
Here is the example with recursive creation of elements:
function createBranch(currentNode) {
var numberOfParents = currentNode.parents("li").length;
//if we don't reach deepest level - we can add submenu
if(numberOfParents < MAX_NESTING_LEVEL-1) {
//decide, should we create submenu for current <li>
if (Math.round(Math.random()) == 1) {
//create <ul> submenu
var ul = $("<ul />", {
class: "submenu"
});
currentNode.append(ul);
//adding children <li> to submenu
var childNumber = getRandomInt(MIN_CHILD_NUMBER, MAX_CHILD_NUMBER);
for(var i = 0; i < childNumber; i++) {
var li = createLeaf(i);
ul.append(li);
//using recursion: submenu creation for current <li>
createBranch(li);
}
}
}
return currentNode;
}
Here are two functions that could use recursion for different purposes:
/**could generate empty (nothing will be added to "#topnav")*/
function randomMenu() {
var generated = createBranch($("#topnav"));
generated.find("ul").parent("li").addClass("parent");
generated.children("ul").removeClass("submenu").addClass("menu");
}
and
function menuWithConstantNumberOfRootListItems(rootListItemsNumber){
var root = $("<ul/>", {class:"menu"});
//generate root <ul> with needed quantity of <li>
for(var i = 0; i < rootListItemsNumber; i++) {
var rootLeaf = createLeaf(i);
root.append(rootLeaf);
createBranch(rootLeaf);
}
root.find("ul").parent("li").addClass("parent");
$("#topnav").append(root);
}
There are additional functions (getRandomInt
and createLeaf
) and variables (MAX_NESTING_LEVEL
, MIN_CHILD_NUMBER
and MAX_CHILD_NUMBER
), you can check their usage in the DEMO.