使用ul li生成JQuery多级菜单列表

3
...images
......|vertical
......|horizontal
...Jquery
......|UI
......|include
...quickfox

需要处理的数组: 我有一个文件夹结构,就像上面那样。它存储在名为dirs的数组中。请看下面的内容。

var dirs = [ 
        "images",
        "images/vertical",
        "images/horizontal",
        "Jquery",
        "Jquery/UI",
        "Jquery/include",
        "quickfox"
        ];

目标:如何制作以下嵌套的ul li。

<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>

更新:XML结构

<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>

这是我从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
    });
}
3个回答

4

您的数组结构不适合创建元素,您可以基于该数组创建一个对象并使用该对象。

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/

更新:

我没有注意到预期的标记是无效的,一个 ul 元素只应该有 li 子元素,您应该将后代 ul 元素添加到 li 元素中:

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/


你的代码运行良好,但是 function (_, value) 中的 _ 是什么意思? - exexzian
2
@Bingo 这是索引,_ 在 JavaScript 中是一个有效的标识符,请将其视为 iindex - Ram

1
如果您将数据结构更改为多维数组/对象,则可以使用递归函数来循环遍历无限嵌套级别,如下所示:
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))

演示: http://jsfiddle.net/AA6yb/1

修订答案

根据更新的信息,xml已经有了嵌套,问题是如何解析不是平面数组的xml。

以下递归循环遍历xml中所有children目录。通过使用find(),您只创建了一个平面数组,因为find()会查找所有后代。

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>

演示:http://jsfiddle.net/AA6yb/2/


感谢 @charlietfl。1- 如何将问题中的变量dirs转换为多维数组,因为这些条目来自xml。 2-我们如何添加缩进以使代码更美观。 - django
你是在服务器端解析XML还是在JavaScript AJAX请求中解析?如果是JavaScript,请提供XML示例。 - charlietfl
我已经在问题中添加了XML和JavaScript。 - django
通过显示一个平面数组,使问题变得更加困难了。你的xml已经有了嵌套,不需要转换为平面数组。问题在于你正在忽略xml的嵌套,使用find('directory')而不是children('directory'),如果存在该目录的子项,则递归循环遍历该目录的子项。 - charlietfl
你能推荐正确的代码吗?使用 children('directory')。 - django
这段代码似乎在找不到子文件夹的情况下创建了空的<ul></ul>。请检查http://jsfiddle.net/bababalcksheep/TX2d8/的输出源代码。 - django

1
如果你必须使用这个数据结构,可以使用以下代码:
$(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;
    });
});

这里有一个代码片段:http://jsfiddle.net/K8SZk/3/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接