jQuery:按顺序将<li>标签插入列表中

5
我有一组<li>标签的订单:
var order = ["a-link", "b-link", "c-link", "d-link", "e-link", "f-link"];

在任何时候,一些<li>标签可能存在于列表中,也可能不存在:

例如:

<ul>
<li id="a-link"></li>
<li id="d-link"></li>
</ul>

我希望能够按正确顺序插入<li>标签...
    <ul>
        <li id="a-link"></li> 
<!-- i'd like to insert <li id="b-link"> right after this -->
        <li id="d-link"></li>
    </ul>

有时我的列表可能看起来像这样:

    <ul>
    <li id="b-link"></li>

<!-- but maybe I want to insert a <li id="d-link"> here-->

    <li id="e-link"></li>
    </ul>

或者像这样:

    <ul>
    <li id="a-link"></li>
    <li id="d-link"></li>
<!-- but maybe I want to insert a <li id="e-link"> here-->
    <li id="f-link"></li>
    </ul>

基本上,列表可能会发生变化...但是每当我想插入一个<li>标签(一次一个)时,它需要按照顺序数组的正确顺序放置。


你必须为我澄清一些事情,而且你可能希望在你的问题中澄清以供未来读者参考。你是想插入订单中缺少的第一个,还是想手动选择要插入的位置,并将其放在正确的位置?你给出的例子可以两种方式解释。 - RightSaidFred
我添加了一些其他的例子,谢谢。 - redconservatory
2个回答

2
我的理解与其他回答者不同(这个词是存在的吗?)。
我理解的问题是:在已经存在未知数量元素的页面中,您想要插入单个元素,并希望该单个元素按照数组定义的顺序插入列表中。
编辑:另一个可能具有更好性能的选项是查找要插入的元素在顺序数组中的索引。然后从该索引开始循环到结尾。一旦找到一个已存在的元素,在该元素之前插入新元素。 http://jsfiddle.net/bWPX8/5/
var order = ["a-link", "b-link", "c-link", "d-link", "e-link", "f-link"];        

var toInsert = "c-link";
var insertIndex = order.indexOf(toInsert);

if($("ul>li").length === 0){

    $("ul").append(  $("<li>",{id:toInsert}));

}else if($("#"+toInsert).length===0){
    var inserted = false;

    for(var i = insertIndex + 1, len = order.length; i<len; i++){
        var $el = $("#" + order[i]);

        if($el.length > 0){
            $el.before($("<li>",{id:toInsert}));
            inserted = true;
            break;
        }
    }

    if(!inserted){
         // should be last
          $("ul").append($("<li>",{id:toInsert}));
    }
}

为了获得更好的性能,确定您的元素索引是在数组的中点之前还是之后,并根据需要循环向前或向后,以减少循环迭代次数。
如果这是问题,以下是一种暴力方法。如果列表比所给示例大得多,则性能可能不太理想。 http://jsfiddle.net/bWPX8/3/ 某些版本的IE可能不支持Array.indexOf,因此可能需要替换为其他内容。

订单中只会有几个(不超过12个)元素,所以我认为提供的解决方案很好。但是了解其他优化方法也很好,所以感谢您提供这些信息。 - redconservatory
“different than the other answerers” 我是这里唯一的其他答案,但我们的解决方案表现相同。你是指别人的答案吗?(我还看不到已删除的答案。) - RightSaidFred
@RightSaidFred,已经有多个回答被删除了。我没有机会完全检查你的回答。 - James Montagne
@JamesMontagne:好的,谢谢提供信息。我记得看到过另一个,但从未真正关注它。 - RightSaidFred

0

为了给问题中的更新信息添加一个解决方案:

var ul = document.getElementsByTagName('ul')[0],
    lis = ul.getElementsByTagName('li'),
    order = ["a-link", "b-link", "c-link", "d-link", "e-link", "f-link"],
    toInsert = "b-link",
    i = $.inArray( toInsert, order ),
    el = lis[ toInsert ],
    new_li;

if( !el && i > -1 ) {
    do el = lis[ order[ ++i ] ];
    while( i < order.length && !el )

    (new_li = document.createElement('li')).id = new_li.innerHTML = toInsert;

    if( el ) ul.insertBefore( new_li, el );
    else ul.appendChild( new_li );
}

这利用了“实时”列表和列表中的元素可通过使用它们的ID作为列表属性来访问的事实。 JSFIDDLE DEMO

翻译:

应该可以这样做:

var order = ["a-link", "b-link", "c-link", "d-link", "e-link", "f-link"],
    i = 0,
    place = $('ul'),
    el = $('#' + order[i] );

if( !el.length ) {

    $('<li>',{id:order[i]}).prependTo( place );

} else {

    do {
        ++i;
        place = el;
        el = $('#' + order[i] );
    } while( el.length )

    if( i < order.length ) {
        $('<li>',{id:order[i]}).insertAfter( place );
    }
}

JSFIDDLE演示


这里有另一种做法:

var order = ["a-link", "b-link", "c-link", "d-link", "e-link", "f-link"],
    prev,
    el;

$.each( order, function(i,v) {
    prev = el;
    el = $('#' + v);
    if( !el.length ) {
        if( !i ) {
            $('<li>',{id:order[i],text:order[i]}).appendTo('ul');
        } else {
            $('<li>',{id:order[i],text:order[i]}).insertAfter( prev );
        }
        return false;
    }
});

{{link1:JSFIDDLE演示}}


似乎只有 i=0 才能正常运行,其它参数都会失败。 - James Montagne
@JamesMontagne:我不确定你的意思。i是分析的起点,因此它永远不应该被更改。 - RightSaidFred
哦,所以OP想要确定要插入的那个?问题中听起来像是自然顺序中的下一个。看来不是这样。 - RightSaidFred

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