Sort an html list with javascript

62,545

Solution 1

This will probably be the fastest way to do it, since it doesn't use jQuery:

function sortList(ul){
    var new_ul = ul.cloneNode(false);

    // Add all lis to an array
    var lis = [];
    for(var i = ul.childNodes.length; i--;){
        if(ul.childNodes[i].nodeName === 'LI')
            lis.push(ul.childNodes[i]);
    }

    // Sort the lis in descending order
    lis.sort(function(a, b){
       return parseInt(b.childNodes[0].data , 10) - 
              parseInt(a.childNodes[0].data , 10);
    });

    // Add them into the ul in order
    for(var i = 0; i < lis.length; i++)
        new_ul.appendChild(lis[i]);
    ul.parentNode.replaceChild(new_ul, ul);
}

Call the function like:

sortList(document.getElementsByClassName('list')[0]);

You can sort other lists the same way, and if you have other elements on the same page with the list class you should give your ul an id and pass it in using that instead.

Example JSFiddle

Edit

Since you mentioned that you want it to happen on pageLoad, I'm assuming you want it to happen ASAP after the ul is in the DOM which means you should add the function sortList to the head of your page and use it immediately after your list like this:

<head>
    ...
    <script type="text/javascript">
        function sortList(ul){
            var new_ul = ul.cloneNode(false);
            var lis = [];
            for(var i = ul.childNodes.length; i--;){
                if(ul.childNodes[i].nodeName === 'LI')
                    lis.push(ul.childNodes[i]);
            }
            lis.sort(function(a, b){
               return parseInt(b.childNodes[0].data , 10) - parseInt(a.childNodes[0].data , 10);
            });
            for(var i = 0; i < lis.length; i++)
                new_ul.appendChild(lis[i]);
            ul.parentNode.replaceChild(new_ul, ul);
        }
    </script>
</head>
<body>
    ...
    <ul class="list">
        <li id="alpha">32</li>
        <li id="beta">170</li>
        <li id="delta">28</li>
    </ul>
    <script type="text/javascript">
        !function(){
            var uls = document.getElementsByTagName('ul');
            sortList( uls[uls.length - 1] );
        }();
    </script>
    ...
</body>

Solution 2

you can use this lightweight jquery plugin List.js cause

  1. it's lightweight [only 3K script]
  2. easy to implement in your existing HTML table using class
  3. searchable, sortable and filterable

HTML

<div id="my-list">
    <ul class="list">
       <li>
           <h3 class="name">Luke</h3>
       </li>
       <li>
           <h3 class="name">John</h3>
       </li>
    </ul>
</div>

Javascript

var options = {
    valueNames: ['name']
};
var myList = new List('my-list', options);

Solution 3

There's also this small jQuery plugin. Which would make your sort nothing more than:

$('.list>li').tsort({attr:'id'});

Solution 4

You can try this

var ul = $(".list:first");
var arr = $.makeArray(ul.children("li"));

arr.sort(function(a, b) {
    var textA = +$(a).text();
    var textB = +$(b).text();

    if (textA < textB) return -1;
    if (textA > textB) return 1;

    return 0;
});

ul.empty();

$.each(arr, function() {
    ul.append(this);
});

Live example : http://jsfiddle.net/B7hdx/1

Solution 5

This code will sort that list assuming there is only one .list item:

function sortList(selector) {
    var parent$ = $(selector);
    parent$.find("li").detach().sort(function(a, b) {
        return(Number(a.innerHTML) - Number(b.innerHTML));
    }).each(function(index, el) {
        parent$.append(el);
    });
}

sortList(".list");

You can see it work here: http://jsfiddle.net/jfriend00/FjuMB/

To explain how it works:

  1. It gets the .list parent object.
  2. It finds all the <li> child objects.
  3. It removes all the <li> child objects from the DOM, but preserves their data
  4. It sorts the li objects using a custom sort function
  5. The custom sort function gets the HTML in the li tag and converts it to a number
  6. Then, traversing the array in the newly sorted order, each li tag is appended back onto the original parent.

The result is that they are displayed in sorted order.

Edit:

This improved version will even sort multiple list objects at once:

function sortList(selector) {
    $(selector).find("li").sort(function(a, b) {
        return(Number(a.innerHTML) - Number(b.innerHTML));
    }).each(function(index, el) {
        $(el).parent().append(el);
    });
}

sortList(".list");

Demo: http://jsfiddle.net/jfriend00/RsLwX/

Share:
62,545
danssker
Author by

danssker

Website developer who can't see the wood for trees, but enjoys the trees he sees.

Updated on June 27, 2020

Comments

  • danssker
    danssker almost 4 years

    I have a set of three list items that I would like to automatically display from high to low on page load. Ideally using jquery or javascript.

    <ul class="list">
    <li id="alpha">32</li>
    <li id="beta">170</li>
    <li id="delta">28</li>
    </ul>
    

    Each list item needs its own ID because they each have individual background images. The numbers must text nodes so that a user can edit them.

  • Gran
    Gran over 12 years
    Have you fully tested your live example? It displayed "170 28 32"
  • danssker
    danssker over 12 years
    That's beautiful - works a charm. Now to try and disect what you wrote..!
  • danssker
    danssker over 12 years
    thanks, looks nice but.. not sure the sort array is working properly here? looks like its sorting by first digit and not by the actual value.
  • danssker
    danssker over 12 years
    Nice... if my site was already using jquery I would have used this.
  • jfriend00
    jfriend00 over 12 years
    Note: this won't work in versions of IE before IE9 without more code because getElementsByClassName() doesn't exist in older versions of IE.
  • jfriend00
    jfriend00 over 12 years
    @danssker - Why you would pick the more complicated native javascript version over the simpler jQuery version if you're already using jQuery? Can you really see a performance difference on an operation like this? My mantra in this regard is: go with simplicity first and only add complexity if you absolutely need it.
  • jfriend00
    jfriend00 over 12 years
    Why clone the UL node? You can just reinsert the sorted LI nodes to the original UL node.
  • Paul
    Paul over 12 years
    @jfriend00 You mean versions before IE 7, not IE 9... Also the sortList function works in IE 6, just need to call it differently like I said with using an id.
  • Paul
    Paul over 12 years
    @jfriend00 It is much faster to clone the node, because the browser doesn't need to rerender after every appendChild. The difference will be in the seconds range if the ul contains thousands of lis.
  • Paul
    Paul over 12 years
    @jfriend00 I meant reflow not rerender
  • jfriend00
    jfriend00 over 12 years
    I think you're mistaken. According to both this compatibility page and this test page run in IE8, document.getElementsByClassName() does not exist in IE8. This is one of the advantages of using jQuery - you don't have to do selector-type things differently in different browsers.
  • Paul
    Paul over 12 years
    @jfriend00 Huh... I suppose you're right about getElementsByclassName, still it's better to just use an id, and like I said my sortList function is cross browser :) It's easy to write your own getElementsByClassName for browsers which do not support it, and considering the OP wants this to execute immediately I think it's a good idea to use the fastest code possible.
  • danssker
    danssker over 12 years
    @jfriend00 I said if i was using jquery I would have gone with jquery. For exactly the same reason you mentioned, why complicate things by preloading the jquery library when I only needed it for this one thing.
  • jfriend00
    jfriend00 over 12 years
    @danssker - you did tag your question with jQuery. I'm not sure why you did that if you don't want any jQuery solutions.
  • danssker
    danssker over 12 years
    @jfriend00 true, i did that. my apologies. i guess i'd did expect so many comprehensive replies. I'm a bit overwhelmed!
  • CPHPython
    CPHPython over 7 years
    @danssker I'm glad you tagged it with jquery, although this solution seems neat, since I'm using jQuery, I prefer the solution with it.
  • Hector
    Hector over 5 years
    Bob thanks, the best solution I've found thus far. You can also use data attributes parseInt(a.getAttribute(attr))
  • qyb2zm302
    qyb2zm302 almost 4 years
    for(var i = ul.childNodes.length; i--;) is equivalent to for(var i = ul.childNodes.length - 1; i>=0; i--). Seems like it's a shortcut that takes advantage of the optional nature of the for statements's final-expression by decrementing within the conditional and leaving the final-expression blank. I had never seen this before so I had to take some time to puzzle this out.
  • Ludo
    Ludo over 2 years
    Thanks, Here is a solution for sorting alphabetically: list.sort(function(a, b){ var aa = a.innerHTML; var bb = b.innerHTML; return aa.localeCompare(bb); });