2017-03-04 73 views
0

我想创建一个基于嵌套HTML ul列表的“嵌套”选择菜单。例如,向用户呈现类别的选择菜单,然后选择该根类别的选项将打开具有子类别的另一个选择菜单。 (如果子类别具有子类别,则循环继续,我希望能够打开基于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

为了将一系列选择元素中的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>

+1

你是绝对令人难以置信!该解决方案完美运作。代码看起来很棒,你让我的新手很容易理解。非常感谢!! :) – sjsc