21

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.

2
  • see here stackoverflow.com/q/1134976/771300 Commented Jan 12, 2012 at 15:08
  • @maerics I tried originaly to build it up from scratch with an array function listSort(a, B) { return a - b; } var n = ["10", "775", "40", "1125","1", "8"]; document.write(n.sort(listSort)); I got as far as rearranging the list in order but couldnt figure it to work with different list IDs. Commented Jan 12, 2012 at 17:21

11 Answers 11

25

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>
Sign up to request clarification or add additional context in comments.

14 Comments

That's beautiful - works a charm. Now to try and disect what you wrote..!
@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.
Why clone the UL node? You can just reinsert the sorted LI nodes to the original UL node.
@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.
@jfriend00 I meant reflow not rerender
|
6

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

2 Comments

Have you fully tested your live example? It displayed "170 28 32"
Nice... if my site was already using jquery I would have used this.
6

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

Comments

6

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

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

Comments

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/

Comments

3

Non jquery version (vanilla javascript)

Benefits: the list is sorted in place, which doesn't destroy the LI's nor remove any events that may be associated with them. It just shuffles things around

Added an id to the UL:

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

and the vanilla javascript (no jquery)

// Grab a reference to the UL
var container = document.getElementById("myList");

// Gather all the LI's from the container
var contents = container.querySelectorAll("li");

// The querySelector doesn't return a traditional array
// that we can sort, so we'll need to convert the contents 
// to a normal array.
var list = [];
for(var i=0; i<contents.length; i++){
    list.push(contents[i]);
}

// Sort based on innerHTML (sorts "in place")
list.sort(function(a, b){
    var aa = parseInt(a.innerHTML);
    var bb = parseInt(b.innerHTML);
    return aa < bb ? -1 : (aa > bb ? 1 : 0);
});

// We'll reverse the array because our shuffle runs backwards
list.reverse();

// Shuffle the order based on the order of our list array.
for(var i=0; i<list.length; i++){
    console.log(list[i].innerHTML);
    container.insertBefore(list[i], container.firstChild);
}

And the fiddle proof: https://jsfiddle.net/L27gpnh6/1/

2 Comments

Bob thanks, the best solution I've found thus far. You can also use data attributes parseInt(a.getAttribute(attr))
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); });
1

You can use this method:

var mylist = $('ul');
var listitems = mylist.children('li').get();
listitems.sort(function(a, b) {
   var compA = $(a).text().toUpperCase();
   var compB = $(b).text().toUpperCase();
   return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
})
$.each(listitems, function(idx, itm) { mylist.append(itm); });

Check the article here: http://www.onemoretake.com/2009/02/25/sorting-elements-with-jquery/

Edit: There is a very cool jquery plugin that does that : http://tinysort.sjeiti.com/

Comments

1

Something like this should help:

var $parent = $(".list");

$(".list li").sort(function (a, b) {
    return window.parseInt($(a).text(), 10) - window.parseInt($(b).text(), 10);
}).remove().each(function () {
    $parent.append($(this));
});

Comments

1

One method could be to sort an array (well, a jQuery object) of the li elements and replace the contents (using the html method) of the ul with the sorted array of elements:

$(".list").html($(".list li").sort(function(a, b) {
     return parseInt($(b).text(), 10) - parseInt($(a).text(), 10);    
}));

Here's a working example.

1 Comment

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

using jQuery for help:

var sortFunction = function(a, b) {
    return (+($(b).text())) - (+($(a).text()));
}
var lis = $('ul.list li');
lis = Array.prototype.sort.call(lis, sortFunction);

for (var i = 0; i < lis.length; i++) {
    $('ul.list').append(lis[i]);
}

Fiddle Link

Comments

0

Sort jQuery collection as usual array and then append each element back in correct order.

$(".list li").sort(function(a, b) {
    return parseInt($(b).text(), 10) - parseInt($(a).text(), 10);    
}).appendTo('.list');

http://jsfiddle.net/zMmWj/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.