• text 1
  • text 2
  • Easiest way to sort DOM nodes?

    If I have a list like this:

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

    What is the easiest way to reconfigure DOM nodes according to my preferences? (This should happen automatically when the page loads, preference in list order is obtained from the cookie)

    eg.

     <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> 
    +42
    javascript dom
    Nov 12 '08 at 0:58
    source share
    8 answers

    Although there may be an easier way to do this using the JS library, the solution using vanilla js works here.

     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]); } 
    +62
    Nov 12 '08 at 1:23
    source share

    You may find that sorting DOM nodes does not work well. Another approach would be to have your javascript have an array representing the data that will fall into the DOM nodes, sort that data and then restore the div that contains the DOM nodes.

    Maybe you don’t have many nodes to sort, so it doesn’t matter. My experience is based on trying to sort HTML tables by manipulating the DOM, including tables with hundreds of rows and several tens of columns.

    +14
    Nov 12 '08 at 3:32
    source share

    See in action: 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

    +13
    Jun 15 '12 at 14:18
    source share

    If you are already using jQuery, I would recommend tinysort: http://tinysort.sjeiti.com/

     $("li").tsort({order:"asc"}); $("li").tsort({order:"desc"}); 
    +9
    Jan 04 '12 at 18:40
    source share

    My version, I hope, will be useful for others:

     var p = document.getElementById('mylist'); Array.prototype.slice.call(p.children) .map(function (x) { return p.removeChild(x); }) .sort(function (x, y) { return /* sort logic */; }) .forEach(function (x) { p.appendChild(x); }); 
    +6
    Sep 19 '16 at 9:34
    source share

    Here is the ES6 function for sorting DOM nodes:

     const sortChildren = ({ container, childSelector, getScore }) => { const items = [...container.querySelectorAll(childSelector)]; items .sort((a, b) => getScore(b) - getScore(a)) .forEach(item => container.appendChild(item)); }; 

    Here's how you could use it to sort Unallocated user reviews by account :

     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; } }); 
    +2
    Aug 31 '17 at 16:15
    source share

    without analyzing too much if this brings something new to the table, I usually use this:

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

    where item is an array of children of the same parent. we remove the beginning from the last and add the beginning from the first to avoid flickering at the top, which is probably on the screen. I usually get my array of elements as follows:

     forEachSnapshot(document.evaluate(..., 6, null), function(n, i){ items[i] = n; }); 
    +1
    Feb 04 2018-12-12T00:
    source share

    Use es6 syntax for resort kids:

     var list = $('#test-list')[0] var arr =[]; for(let i=0;i<list.children.length;i++){ arr.push(list.children[i]) } arr.sort((a,b)=>a.innerText>b.innerText) arr.map(node=>list.appendChild(node)) 
    +1
    May 2 '18 at 5:38
    source share



    All Articles