For table sorting in JavaScript people always look at the existing awesome solutions. However, when time is tight and you don’t want another 71KB dependency in your project sometimes rolling your own table sorting code is necessary.
This is a 30 LOC solution for quick table sorting.1 It interferes minimally with any existing table structures or modifications you might have. Example table and source code below.
Item No. | Product Name | Rating | Price |
---|---|---|---|
1 | The Giver | ★★★★ | $5.17 |
2 | The Lion, the Witch and the Wardrobe | ★★★★ | $8.09 |
3 | Behold the Man | ★★★★ | $12.56 |
4 | The Bourne Ultimatum | ★★★ | $7.19 |
5 | The Cuckoo’s Calling | ★★★★ | $15.20 |
6 | The Count of Monte Cristo | ★★★★★ | $11.99 |
7 | Let the Right One In | ★★★★ | $12.91 |
8 | Perfume: The Story of a Murderer | ★★★★ | $12.28 |
// Takes a table row element and an index and returns the normalized form
// of the sort attribute for the nth-child td. To be more clear, take the
// nth-child td element inside this table row as defined by index (that is
// `:nth-child(idx)`) and then normalize it's sort attribute (if it exists)
// otherwise use the internal text.
function sort_attr ($tr, idx) {
var $td = $tr.children("td:nth-child(" + idx + ")"),
sort_attr = $td.attr("sort")
if (typeof(sort_attr) === "undefined") {
sort_attr = $td.text()
}
// Normalize case
sort_attr = sort_attr.trim().toLowerCase()
// Try to treat this as an integer
var int_attr = parseInt(sort_attr)
if (int_attr === 0 || !!int_attr && typeof(int_attr) == "number") {
return int_attr
}
// Guess we're using a string
return sort_attr
}
// Returns a sorting function that can be applied to an array.
function _sort (idx, ascending) {
return ascending ? function _sorter (a, b) {
return sort_attr($(a), idx) > sort_attr($(b), idx) ? 1 : -1;
} : function _sorter (a, b) {
return sort_attr($(a), idx) < sort_attr($(b), idx) ? 1 : -1;
}
}
// When clicking on a table header, perform some sorting.
$("table thead th").on("click", function () {
var self = $(this)
// Setup sort direction, defaulting to ascending and reversing
// direction if previously set.
var asc = self.attr("asc") == "true" ? false : true
self.attr("asc", asc)
// Clear all directions
$(".dir").html("")
// Setup current direction flag
self.find(".dir").html(asc ? " (▲)" : " (▼)")
// Sort!
var fn = _sort(self.index() + 1, asc)
$("table tbody").html($("table tbody tr").sort(fn))
})
// Affix a .dir to every th
$("table thead th").append("<span class=\"dir\"></span>");