Quick Table Sorting in JavaScript

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 ? "&nbsp;(&#9650;)" : "&nbsp;(&#9660;)")

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

  1. This solution does make use of jQuery, but if you’re writing front-end JavaScript you’re probably already using that. ↩︎

written July 28th, 2013

July 2013

Can’t find what you’re looking for? Try hitting the home page or viewing all archives.