generate Jquery Multilevel menu list with ul li

烈酒焚心 提交于 2021-02-07 19:51:34

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!