问题
...images
......|vertical
......|horizontal
...Jquery
......|UI
......|include
...quickfox
Array to process: I have folder structure Like above.And it is stored in array dirs. see below
var dirs = [
"images",
"images/vertical",
"images/horizontal",
"Jquery",
"Jquery/UI",
"Jquery/include",
"quickfox"
];
Objective: How Can I make nested ul li as below.
<ul id="categorymenu">
<li>images </li>
<ul>
<li>vertical</li>
<li>horizontal</li>
</ul>
<li>Jquery</li>
<ul>
<li>UI</li>
<li>include</li>
</ul>
<li>quickfox</li>
</ul>
UPDATE: XML STRUCTURE
<directory name="images">
<file path="BBB.gif" width="500" height="282">BBB.gif</file>
<file path="AAA.jpg" width="964" height="525">AAA.jpg</file>
<directory name="images/vertical">
<file path="CCC.jpg" width="964" height="525">CCC.jpg</file>
</directory>
<directory name="images/horizontal">
<file path="DDD.jpg" width="964" height="525">DDD.jpg</file>
</directory>
</directory>
This is where I make array from xml ..
$(document).ready(function () {
//------ READ XML -----------
$.ajax({
type: "GET",
url: "___deck.xml",
dataType: "xml",
success: function (data) {
my_xml = data;
xmlDirParser(my_xml);
}
});
//------ Get Files on List Change -----------
$("#dirlist").change(function () {
var folder = $(this).find('option:selected').text();
xmlFileParser(folder, my_xml);
});
});
function xmlDirParser(my_xml) {
$(my_xml).find('directory').each(function () {
var dirname = $(this).attr('name');
// $('#dirlist').append('<option value="1">'+dirname+'</option>');
//This is where I get dirs array
});
}
回答1:
ORIGINAL ANSWER
If you change your data structure to multi dimensional arrays/objects can use a recursive function to loop through infinite nesting levels as follows:
var dirs = [{
name: "images",
subdir: [{
name: "vertical"
}, {
name: "horizontal"
}]
}, {
name: "Jquery",
subdir: [{
name: "UI", subdir: [{name:'Nested 1',subdir: [{name:'Nested 2',subdir: [{name:'Nested 3'}]}]}]
}, {
name: "include"
}]
}, {
name: "quickfox"
}];
function createList( array){
var html='<ul>';
$.each( array, function(k, item){
html+='<li>'+item.name;
if( item.subdir){
html+=createList(item.subdir);
}
html+='</li>';
});
html+='</ul>';
return html;
}
$('body').html( createList( dirs))
DEMO: http://jsfiddle.net/AA6yb/1
REVISED ANSWER
Based on updated information that xml already has nesting, issue is how to parse xml not flat array.
Following recursively loops through all directories in xml that are children
. By using find()
you sinply created a flat array since find()
looks for all descendents
function createList($xml) {
var html = '';
$xml.children('directory').each(function () {
var $dir = $(this);
var name= $dir.attr('name');
html += '<li class="dir">' + parseName($dir.attr('name'));
if ($dir.children().length) {
html += '<ul>';
$dir.children('file').each(function () {
html += '<li class="file">' + $(this).attr('path') + '</li>';
});
/* recursively loop through children directories of this directory*/
if( $dir.children('directory').length){
html+=createList($dir);
}
html += '</ul>';
}
});
html += '</li>';
return html;
}
function parseName( name){
if( name.indexOf('/')>-1){
return name.split('/').pop();
}else{
return name;
}
}
$('#directory_list').html(createList($(xmlData)))
HTML
<ul id="directory_list"></ul>
DEMO: http://jsfiddle.net/AA6yb/2/
回答2:
Structure of your array is not useful for creating elements, you can create an object based on the array and use this object instead.
var o = {};
// Creating an object based on the array elements
$.each(dirs, function (_, value) {
if (value.indexOf('/') === -1) {
o[value] = [];
} else {
var arr = value.split('/');
o[arr[0]].push(arr[1]);
}
});
// Creating elements
var html = '<ul id="categorymenu">';
for (key in o) {
html += '<li>' + key + '</li>';
if (o[key].length) {
html += '<ul><li>' + o[key].join('</li><li>') + '</li></ul>';
}
}
html += '</ul>';
http://jsfiddle.net/5DuDp/
Update:
I didn't notice that the intended markup is invalid, an ul
element should only have li
child elements, you should add the descendant ul
element to the li
element:
for (key in o) {
html += '<li>' + key ;
if (o[key].length) {
html += '<ul><li>' + o[key].join('</li><li>') + '</li></ul>';
}
html += '</li>';
}
html += '</ul>';
http://jsfiddle.net/642pr/
回答3:
If you must have this data structure you can use this:
$(function () {
var dirs = [
"images",
"images/vertical",
"images/horizontal",
"Jquery",
"Jquery/UI",
"Jquery/include",
"quickfox"];
var rootList = $("<ul id='categorymenu'>").appendTo("body");
var elements = {};
$.each(dirs, function () {
var parent = elements[this.substr(0, this.lastIndexOf("/"))];
var list = parent ? parent.next("ul") : rootList;
var textMenu= parent ? this.split("/")[1] : this;
if (!list.length) {
list = $("<ul>").insertAfter(parent);
}
var item = $("<li>").appendTo(list);
$("<a>").text(textMenu).appendTo(item);
elements[this] = item;
});
});
Here is a fiddle: http://jsfiddle.net/K8SZk/3/
来源:https://stackoverflow.com/questions/15851418/generate-jquery-multilevel-menu-list-with-ul-li