このようなリストがある場合:
<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>
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]);
}
DOMノードの並べ替えがうまくいかない場合があります。別のアプローチは、DOMノードに入るデータを表す配列をjavascriptに入れ、そのデータをソートしてから、DOMノードを保持するdivを再生成することです。
ソートするノードがそれほど多くないので、それは重要ではありません。私の経験は、DOMを操作してHTMLテーブルを並べ替えることに基づいています。これには、数百行と数十列のテーブルが含まれます。
実際にご覧ください: 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);
});
};
})();
テルセ
Es6構文を使用して、子を再ソートします。
var list = document.querySelector('#test-list')
[...list.children]
.sort((a,b)=>a.innerText>b.innerText?1:-1)
.map(node=>list.appendChild(node))
私のバージョン、希望は他の人に役立つでしょう:
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); });
すでにjQueryを使用している場合は、tinysortをお勧めします。 http://tinysort.sjeiti.com/
$("li").tsort({order:"asc"});
$("li").tsort({order:"desc"});
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;
}
});
これがテーブルに新しいものをもたらす場合、あまり分析することなく、私は通常これを使用します:
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; });