如何基于嵌套的ul列表创建嵌套选择菜单?

时间:2017-03-04 21:58:20

标签: javascript jquery html

我想根据嵌套的HTML ul列表创建一个“嵌套”选择菜单。例如,向用户呈现类别的选择菜单,然后选择该根类别的选项将打开具有子类别的另一个选择菜单。 (如果子类别具有子类别,则循环继续。我希望能够基于ul列表打开任意数量的子类别子菜单。)

例如,在页面上给出此代码:

<ul id="select-menu-layout" style="display: none">
  <li>A option
    <ul>
      <li>a1 name</li>
      <li>a2 name</li>
      <li>a3 name</li>
    </ul>
  </li>
  <li>B option
    <ul>
      <li>b1 name</li>
      <li>b2 name
        <ul>
          <li>b21 choice</li>
          <li>b22 choice</li>
          <li>b23 choice</li>
        </ul>
      </li>
      <li>b3 name</li>
    </ul>
  </li>
  <li>C name</li>
</ul>

<!-- select menus will be shown in the container below -->
<div class="select-menu-container"></div>

在上面的示例中,最初会显示一个选择菜单:

<select>
  <option>A option</option>
  <option>B option</option>
  <option>C option</option>
</select>

选择“B选项”将显示第二个选择菜单(基于上面的HTML列表):

<select>
  <option>b1 name</option>
  <option>b2 name</option>
  <option>b3 name</option>
</select>

选择“b2名称”将显示第三个选择菜单:

<select>
  <option>b21 choice</option>
  <option>b22 choice</option>
  <option>b23 choice</option>
</select>

我假设你需要javascript / jQuery才能做到这一点?我正在考虑这段代码(尽管我可能非常错误):

<div class="select-menu-container"></div>

<script>
function addSelectMenu(node){
  $(".select-menu-container").append("<select style='display: none'></select>")
  node.each(function(){
    var name = $(this).val()
     $("select:last").append("<option>" + name + "</option>")
  })
}

$("ul").each(function(){
  addSelectMenu($(this))
})
</script>

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

为了在一系列具有嵌套可折叠列表的行为的select元素中转换ul / li列表,可能的解决方案可以基于递归方法。

每个选择都必须链接到上一个选择才能切换可见性。

摘录:

function createSelectFromUl(ele, parentLink) {
    var txtParentNode = parentLink || '';
    var options = ele.map(function (idx, ele) {
        var txt = $(ele).contents().filter(function (idx, ele) {
            if (ele.nodeType == Node.TEXT_NODE) {
                return true;
            }
        }).text().trim();
        return $('<option/>', {text: txt})
    });
    if (ele.children('ul').length == 0) {
        return [$('<select/>', {parentNode: txtParentNode}).append(options.toArray())];
    }
    var retVal = [$('<select/>', {parentNode: txtParentNode}).append(options.toArray())];
    ele.children('ul').each(function (idx, ele) {
        txtParentNode = $(ele.parentNode).contents().filter(function (idx, ele) {
            if (ele.nodeType == Node.TEXT_NODE) {
                return true;
            }
        }).text().trim();
        var childSelects = createSelectFromUl($(ele).children('li'), txtParentNode);

        $.merge(retVal, childSelects);
    });
    return retVal;
}
$(function () {
    var seleEles = createSelectFromUl($('#select-menu-layout > li'));
    $('.select-menu-container').append(seleEles);
    $('.select-menu-container select:gt(0)').hide();

    $('.select-menu-container select').on('change', function (e) {
        var txtParentNode = $(this).val();
        $(this).nextAll().hide();
        $('.select-menu-container select[parentNode="' + txtParentNode + '"]').toggle();
    }).trigger('change');

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<ul id="select-menu-layout" style="display: none">
    <li>A option
        <ul>
            <li>a1 name</li>
            <li>a2 name</li>
            <li>a3 name</li>
        </ul>
    </li>
    <li>B option
        <ul>
            <li>b1 name</li>
            <li>b2 name
                <ul>
                    <li>b21 choice</li>
                    <li>b22 choice</li>
                    <li>b23 choice</li>
                </ul>
            </li>
            <li>b3 name</li>
        </ul>
    </li>
    <li>C name</li>
</ul>

<div class="select-menu-container"></div>