A fairly common problem in jQuery is to sort a set of elements eg a list of <li>, and most examples I came across seemed to offer pretty decent solutions – provided you want to sort alphabetically. If you want to do this in a number of ways, then tinysort is a great way of doing it.

I wanted to sort a list of links by length for aesthetic purposes, eg

sort by length | sort alphabetically

It turns out there isn’t an iron-cast way of doing this. If you go by length of the text of each <li>, you potentially run into problems with variable-width text, where links with more letters appear shorter than links with fewer but wider letters. I then tried the width of the <li> elements, but being block elements (in my case) they all had the same width. The solution that eventually worked for me was to compare the widths of the <a> child element of each <li>. This took a little bit of experimentation with the selectors and iterator functions as I’m not that familiar with either jQuery or javascript. I based my code off code for sorting a list by Dan Sargeant of one more take, so thanks Dan!

I packaged my code up into a function (well two, as I used the alphabetical sort too) which takes one argument – the selector object representing the parent <ul> or <ol> that is to be sorted. Please adapt the code to your own needs, as it may well not work as is! (ie works for me, YMMV, etc)

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

function sortbyalpha($elements) {
        var listitems = $elements.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) { $elements.append(itm); });
}