web-dev-qa-db-ja.com

DOMノードをソートする最も簡単な方法は?

このようなリストがある場合:

<ul id="mylist">
    <li id="list-item1">text 1</li>
    <li id="list-item2">text 2</li>
    <li id="list-item3">text 3</li>
    <li id="list-item4">text 4</li>
</ul>

自分の好みに合わせてDOMノードを再配置する最も簡単な方法は何ですか? (これは、ページが読み込まれたときに自動的に行われる必要があり、リスト順序の設定はCookieから取得されます)

例えば。

<ul id="mylist">
    <li id="list-item3">text 3</li>
    <li id="list-item4">text 4</li>
    <li id="list-item2">text 2</li>
    <li id="list-item1">text 1</li>
</ul>
47
James

JSライブラリを使用してこれを行う簡単な方法はおそらくありますが、Vanilla jsを使用した実用的なソリューションがあります。

var list = document.getElementById('mylist');

var items = list.childNodes;
var itemsArr = [];
for (var i in items) {
    if (items[i].nodeType == 1) { // get rid of the whitespace text nodes
        itemsArr.Push(items[i]);
    }
}

itemsArr.sort(function(a, b) {
  return a.innerHTML == b.innerHTML
          ? 0
          : (a.innerHTML > b.innerHTML ? 1 : -1);
});

for (i = 0; i < itemsArr.length; ++i) {
  list.appendChild(itemsArr[i]);
}
71
nickf

DOMノードの並べ替えがうまくいかない場合があります。別のアプローチは、DOMノードに入るデータを表す配列をjavascriptに入れ、そのデータをソートしてから、DOMノードを保持するdivを再生成することです。

ソートするノードがそれほど多くないので、それは重要ではありません。私の経験は、DOMを操作してHTMLテーブルを並べ替えることに基づいています。これには、数百行と数十列のテーブルが含まれます。

16
Corey Trager

実際にご覧ください: http://jsfiddle.net/stefek99/y7JyT/

    jQuery.fn.sortDomElements = (function() {
        return function(comparator) {
            return Array.prototype.sort.call(this, comparator).each(function(i) {
                  this.parentNode.appendChild(this);
            });
        };
    })();

テルセ

13
Mars Robertson

Es6構文を使用して、子を再ソートします。

var list = document.querySelector('#test-list')

[...list.children]
  .sort((a,b)=>a.innerText>b.innerText?1:-1)
  .map(node=>list.appendChild(node))
9
ahuigo

私のバージョン、希望は他の人に役立つでしょう:

var p = document.getElementById('mylist');
Array.prototype.slice.call(p.children)
  .map(function (x) { return p.removeChild(x); })
  .sort(function (x, y) { return /* your sort logic, compare x and y here */; })
  .forEach(function (x) { p.appendChild(x); });
9
Ebrahim Byagowi

すでにjQueryを使用している場合は、tinysortをお勧めします。 http://tinysort.sjeiti.com/

$("li").tsort({order:"asc"});
$("li").tsort({order:"desc"});
8
Jay

DOMノードを適切にソートするES6関数を次に示します。

const sortChildren = ({ container, childSelector, getScore }) => {
  const items = [...container.querySelectorAll(childSelector)];

  items
    .sort((a, b) => getScore(b) - getScore(a))
    .forEach(item => container.appendChild(item));
};

これを使用して、 未タップのユーザーレビューをスコア でソートする方法を次に示します。

sortChildren({
  container: document.querySelector("#main-stream"),
  childSelector: ".item",
  getScore: item => {
    const rating = item.querySelector(".rating");
    if (!rating) return 0;
    const scoreString = [...rating.classList].find(c => /r\d+/.test(c));
    const score = parseInt(scoreString.slice(1));
    return score;
  }
});
5
cgenco

これがテーブルに新しいものをもたらす場合、あまり分析することなく、私は通常これを使用します:

function forEach(ar, func){ if(ar){for(var i=ar.length; i--; ){ func(ar[i], i); }} }
function removeElement(node){ return node.parentNode.removeChild(node); }
function insertBefore(ref){ return function(node){ return ref.parentNode.insertBefore(node, ref); }; }

function sort(items, greater){ 
    var marker = insertBefore(items[0])(document.createElement("div")); //in case there is stuff before/after the sortees
    forEach(items, removeElement);
    items.sort(greater); 
    items.reverse(); //because the last will be first when reappending
    forEach(items, insertBefore(marker));
    removeElement(marker);
} 

ここで、itemは同じ親の子の配列です。画面上にあると思われる上部のちらつきを避けるために、最後から始めて削除し、最初から始めて追加します。私は通常、次のようなアイテム配列を取得します:

forEachSnapshot(document.evaluate(..., 6, null), function(n, i){ items[i] = n; });
1
peter