0

我在 SO 上看到过一些 帖子,它们希望获取链接列表并将它们变成下拉列表。我已经采用了这些示例,并且没有太多运气将它们应用到我的标记中,这有点不同。<optgroup>我需要将带有标签的单选按钮的嵌套列表转换为带有标题的下拉列表,删除嵌套的单选输入和标签。

基本上,我使用的单选按钮列表非常失控,一个干净的下拉列表会更好的可用性和屏幕空间。一旦我处理了转换,计划是隐藏原始单选按钮集,然后将用户下拉选择映射到相应的单选按钮,以便在提交表单时进行处理。但首先我需要生成下拉列表。. .

这是起始标记的简化示例:

<ul>
    <li>
        <label><input type="radio">USA</label>
        <ul class="children">
            <li>
                <label><input type="radio" >Northeast</label>
                <ul class="children">
                    <li>
                        <label><input itype="radio">Mid-Atlantic</label>
                    </li>
                    <li>
                        <label><input type="radio">New England</label>
                    </li>
                </ul>
            </li>
            <li>
                <label><input type="radio">South</label>
            </li>
            <li>
                <label><input type="radio">West</label>
            </li>
        </ul>
    </li>
    <li>
        <label><input type="radio" checked="checked">No Venue Region</label>
    </li>
</ul>

我试图将以上内容转换为以下内容:

<select>
    <optgroup label="USA">
        <optgroup>Northeast</option>
            <option>Mid-Atlantic</option>
            <option>New England</option>
        <optgroup>
        <option>South</option>
        <option>West</option>
    </optgroup>
    <option>No Region</option>
</select>

您可能会注意到第一个示例中的顶层<ul>也有一个与之关联的单选按钮——但这不是我们所希望的,因为我们希望用户在他们的选择中尽可能精确。这些应该是标题,但不幸的是我无法控制生成的内容。

我喜欢的解决方案类型是使用一个函数将现有标记处理成一个新实体,然后我可以在隐藏原始标记后附加到父 DOM 元素。

在这个SO 线程中,@Enki 提供了一个使用这种方法的解决方案,但我无法应用它,因为我无法完全理解它是如何迭代所有元素的。他的解决方案是这样的:

function sitemapCycle(){
        if(typeof(sitemapNode)==="undefined") sitemapNode= $("#sitemap");
        if($(this).find("ul").length)
        {
            sitemapNode= $(sitemapNode).append('<optgroup label="'+$(this).children().first().text()+'" />').children().last();
            $(this).find("ul li").each(sitemapCycle);
            sitemapNode= $(sitemapNode).parent();
        }
        else
        {
             $(sitemapNode).append('<option value="'+$(this).children().attr("href")+'">'+$(this).text()+'</option>');
        }
    }
    var sitemapNode;
    $("#sitemap").removeAttr("id").after('<select id="sitemap" />').children().each(sitemapCycle).parent().remove();

我能得到的最接近的,它不使用@Enki 的方法,不创建 optgroup 顶级并且真正不完整的是

$(function() {
    $('#venue-regionchecklist').each(function() {
            $(this).find('label').each(function() {
                var cnt = $(this).contents();
                $(this).replaceWith(cnt);
            });
        var $select = $('<select />');
        $(this).find('li').each(function() {
            var $option = $('<option />');
             $(this).html($(this).html());
            $option.attr('id', $(this).attr('id')).html($(this).html());
            $select.append($option);
        });
        $(this).replaceWith($select);
    });
});

如果有人想试一试,这里是一个未简化的广播列表示例。我很想知道您将如何解决此类问题。

4

1 回答 1

1

队友的欢呼声!

我相信递归在这里会有所帮助:

function buildDropDownFromUL(CurrentUL, level) {
   var dropDownHTML = "";
   CurrentUL.children("li").each(function () { // Cycle through all LI elements
      if ($(this).children("ul").length == 0) {
         // There is no UL element in this LI so it means LI is a selectable option
         dropDownHTML = dropDownHTML + "<option value='" + $(this).children("label").children("input").attr("value") + "'>" + NBSPs(level) + $(this).children("label").text() + "</option>";
      } else {
         // There is a UL in the LI so it means the LABEL in the current LI is a OPTGROUP 
         // and the UL should be again processed
         dropDownHTML = dropDownHTML + "<optgroup label='" + NBSPs(level) + $(this).children("label").text() + "'>" + "</optgroup>" + buildDropDownFromUL($(this).children("ul"), level + 1);
      }
   });
   return dropDownHTML + "<optgroup label='&nbsp;'></optgroup>";
}

需要注意的是:该函数假定如果给定的 LI 元素仅包含一个 LABEL 元素(并且没有 UL 元素),那么 LABEL 是一个可选选项,如果 LI 包含一个 LABEL 和一个 UL,那么 LABEL 是一个选项团体。

这是小提琴

我希望它有帮助!

于 2013-10-07T14:45:40.227 回答