JavaScript to sort DOM elements by some comparator, without jQuery - Stack Overflow

Imagine some DOM elements:<ul id="list"><li data-index="3">Baz<li&g

Imagine some DOM elements:

<ul id="list">
  <li data-index="3">Baz</li>
  <li data-index="1">Foo</li>
  <li data-index="2">Bar</li>
</ul>

How can these elements be sorted using JavaScript and without jQuery?

Something similar to:

document.getElementById('list').sort(function(li) { return li.dataset.index; });

Imagine some DOM elements:

<ul id="list">
  <li data-index="3">Baz</li>
  <li data-index="1">Foo</li>
  <li data-index="2">Bar</li>
</ul>

How can these elements be sorted using JavaScript and without jQuery?

Something similar to:

document.getElementById('list').sort(function(li) { return li.dataset.index; });
Share Improve this question asked Jun 21, 2014 at 13:52 Drew NoakesDrew Noakes 311k170 gold badges697 silver badges765 bronze badges 14
  • Try searching for this question online and you'll find nothing out there that covers this other than some jQuery stuff. Seems like a perfectly reasonable question to me. Explain why if you feel otherwise. – Drew Noakes Commented Jun 21, 2014 at 13:58
  • 1 Put references to li elements into an array (or convert NodeList into one), sort, and insert elements back into DOM in array order … done. – C3roe Commented Jun 21, 2014 at 14:00
  • @CBroe, that involves a lot of DOM churn, which is bad for performance especially if the list is already mostly sorted. I'd like to do the sort in-place ideally. – Drew Noakes Commented Jun 21, 2014 at 14:01
  • 1 "In-place" sorting would probably be even slower, you'd need to append the same element several times. Btw. I didn't vote down, but maybe the lack of a true attempt to solve this has caused a down-vote. – Teemu Commented Jun 21, 2014 at 14:04
  • 2 jsfiddle/f4s7s/1 – C3roe Commented Jun 21, 2014 at 14:12
 |  Show 9 more ments

3 Answers 3

Reset to default 5

You should use the ordering capabilities of flexboxes. This will allow to re-order the elements without moving them around in the DOM. This involves setting the CSS order property.

See https://developer.mozilla/en-US/docs/Web/Guide/CSS/Flexible_boxes for more details.

Some time ago I wrote this:

function sortChildren(wrap, f, isNum) {
    var l = wrap.children.length,
        arr = new Array(l);
    for(var i=0; i<l; ++i)
        arr[i] = [f(wrap.children[i]), wrap.children[i]];
    arr.sort(isNum
        ? function(a,b){ return a[0]-b[0]; }
        : function(a,b){ return a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0; }
    );
    var par = wrap.parentNode,
        ref = wrap.nextSibling;
    par.removeChild(wrap);
    for(var i=0; i<l; ++i) wrap.appendChild(arr[i][1]);
    par.insertBefore(wrap, ref);
}

Basically:

  1. First create an array to store the elements with its corresponding value returned by the parator function.

    We could also run the function when sorting, but since DOM interactions are slow, this way we make sure the function will only run once per element.

  2. Then, we sort it using native sort.

    If isNum argument is truly, we use a sorting function that pares numerically. This is needed if the parator function returns strings but you want to pare numerically instead of lexicographically.

  3. Now, we remove the wrapper element from the DOM. This way reordering the children will be less expensive (e.g. avoiding repaitings).

  4. Finally we reorder the children, and insert wrapper back in its place.

Run it like

sortChildren(
    document.getElementById('list'),
    function(li) { return li.dataset.index; },
    true
);

or

sortChildren(
    document.getElementById('list'),
    function(li) { return +li.dataset.index; }
);

Demo

<!doctype html>
<html lang="en">
<head>
<meta charset= "utf-8">
<title>sort list</title>
</head>
<body>
<strong>Double click the list to sort by data-index</strong>
<ul id= "list">
<li data-index= "3">Baz</li>
<li data-index= "1">Foo</li>
<li data-index= "2">Bar</li>
</ul>
<script>

document.body.ondblclick=function(){
    var A=[], pa= document.getElementById('list');
    var itemz= pa.getElementsByTagName('li');

    A.slice.call(itemz).sort(function(a, b){
        return a.getAttribute('data-index')-b.getAttribute('data-index');
    }).forEach(function(next){
            pa.appendChild(next);
    });
}

</script>
</body>
</html>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1741484325a4349528.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信