Самый простой способ сортировки DOM-узлов? - PullRequest
46 голосов
/ 12 ноября 2008

Если у меня есть такой список:

<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)

* 1006 Е.Г. *

<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>

Ответы [ 8 ]

70 голосов
/ 12 ноября 2008

Хотя, возможно, есть более простой способ сделать это с помощью библиотеки 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]);
}
15 голосов
/ 12 ноября 2008

Вы можете обнаружить, что сортировка DOM-узлов не работает должным образом. Другой подход заключается в том, чтобы иметь в вашем javascript массив, который представляет данные, которые будут поступать в узлы DOM, сортировать эти данные, а затем повторно генерировать div, содержащий узлы DOM.

Может быть, у вас не так много узлов для сортировки, так что это не имеет значения. Мой опыт основан на попытке сортировать HTML-таблицы путем манипулирования DOM, включая таблицы с сотнями строк и несколькими десятками столбцов.

13 голосов
/ 15 июня 2012

Смотрите это в действии: 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);
            });
        };
    })();

Terse

9 голосов
/ 19 сентября 2016

Моя версия, надеюсь, будет полезна другим:

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); });
8 голосов
/ 04 января 2012

Если вы уже используете jQuery, я бы порекомендовал tinysort: http://tinysort.sjeiti.com/

$("li").tsort({order:"asc"});
$("li").tsort({order:"desc"});
6 голосов
/ 02 мая 2018

Используйте синтаксис es6 для курортов детей:

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

[...list.children]
  .sort((a,b)=>a.innerText>b.innerText?1:-1)
  .map(node=>list.appendChild(node))
3 голосов
/ 31 августа 2017

Вот функция ES6 для сортировки узлов DOM на месте:

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;
  }
});
1 голос
/ 04 февраля 2012

, не анализируя слишком много, если это приносит что-то новое в таблицу, я обычно использую это:

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; });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...