this is part of as days pass by, by Stuart Langridge

sorttable: Make all your tables sortable


While the web design community gradually moves away from using tables to lay out the structure of a page, tables really do have a vital use, their original use; they're for laying out tabular data. For instance, imagine a table of employees.

NameSalaryExtensionStart date Start date (American)
Bloggs, Fred$12000.00 135318/08/200308/18/2003
Turvey, Kevin$191200.00 234202/05/197905/02/1979
Mbogo, Arnold$32010.12 275509/08/199808/09/1998
Shakespeare, Bill$122000.00 321112/11/196111/12/1961
Shakespeare, Hamnet$9000 900501/01/200201/01/2002
Fitz, Marvin$3300 555422/05/199505/22/1995

Pretty simple. But if you saw that table in a client-side application, you'd expect to be able to click on the headers and have the table sort, would you not? I know it always annoys me when you can't. A fair few web applications do allow this; most of them, which are pulling this data by submitting a SQL query to a relational database (an environment eminently suited to tabular data) implement this by resubmitting the whole page with something like ordercolumn=4 in the URL, and then adding an ORDER BY clause to their SQL query to return the data from the DB ordered by the specified column.

Resubmit the page? Just to sort data we already have? I'm sure we can do better than that.

NameSalaryExtensionStart date Start date (American)
Bloggs, Fred$12000.00 135318/08/200308/18/2003
Turvey, Kevin$191200.00 234202/05/197905/02/1979
Mbogo, Arnold$32010.12 275509/08/199808/09/1998
Shakespeare, Bill$122000.00 321112/11/196111/12/1961
Shakespeare, Hamnet$9000 900501/01/200201/01/2002
Fitz, Marvin$3300 555422/05/199505/22/1995

As you can see, the above table now has clickable headers that sort the table by the clicked column. Note how the numeric and date columns all sort properly, too, rather than sorting alphanumerically.

This is not a new trick, sorting a table using the DOM. However, this mini-library has two nice attributes; the first is, unsurprisingly, that it follows my principles of unobtrusive DHTML, as you'll see below. The second is that, as mentioned above, it knows how to sort a variety of different data types, and it works them out for itself -- you don't have to tell it.

Now, how to use it. To make a table of your choice sortable, there are three steps:

  1. Download the Javascript library
  2. Include the Javascript library, by putting a link to it in the HEAD of your page, like so:
    <script src="sorttable.js"></script>
  3. Mark your table as a sortable one by giving it a class of "sortable":
    <table class="sortable">
    Note that the library's JavaScript file is called sorttable (two Ts), but the class you add to the table is sortable (one T).

And that's all you need. Your table will now have column sorting available by clicking the headers. For niceness, you might want to add the following styles to your stylesheet, or make up some of your own based on this:


/* Sortable tables */
table.sortable thead {
    background-color:#eee;
    color:#666666;
    font-weight: bold;
    cursor: default;
}

This is version 2 of sorttable, released April 2007 and tweaked continually since. If you're using the old version, you may find it useful to update; v2 has numerous new features and should be completely backwards compatible.


Advanced usage

You probably don't need the bits here. Sorttable is designed to require no configuration, no fiddling around. Just take it and use it. If you need it to do more than it does by default, then come back here and read this part.

  1. How do I sort a table that I added with Ajax?
  2. How do I make my "totals" row stay at the bottom of my table?
  3. Can I make a sortable table show symbols before it's sorted, so my viewers know that it's sortable?
  4. How do I sort some data in a format that sorttable doesn't understand?
  5. What do I do if sorttable isn't sorting my data the way I'd expect it to?
  6. How do I make sorttable handle dates in the format I put them in?
  7. Can sorttable do a stable sort?
  8. How can I tell a sortable table to sort from my code, rather than from a user click?
  9. How do I make some columns not be sortable?
  10. Can sorttable sort a table as soon as the page loads, without requiring the user to click?
  11. How do I make sorttable sort columns in descending order first rather than ascending order?
  12. How do I make sorttable sort text case-insensitively (i.e., so lower-case and upper-case letters sort together)?
  13. How do I have a column of "row numbers" on the left of my table which sorttable doesn't sort?
  14. How do I have my table striped (alternating rows in different colours) and keep that striping after sorting?
  15. Can I have the body of the table be scrollable?
  16. Can I sort tables on a page I didn't write?
  17. What's new in version 2 of sorttable?
  18. Can I use sorttable in a commercial product? On a commercial website? What licencing terms is it available under?
  19. I love sorttable so much that I want to donate some money to you even though I don't have to. Can I?
  20. I've found a problem in sorttable. How can I tell you about it?
  21. But I need my problem with sorttable to be fixed! Can I pay you to fix it?

Sorting a table added after page load

Once you've added a new table to the page at runtime (for example, by doing an Ajax request to get the content, or by dynamically creating it with JavaScript), get a reference to it (possibly with var newTableObject = document.getElementById(idOfTheTableIJustAdded) or similar), then do this:

sorttable.makeSortable(newTableObject);

Totals rows

If you have a "totals" row at the bottom of your table that you want to stay at the bottom of your table (and not get sorted), then add it to a <tfoot> section in your table (which is what you should be doing anyway, according to the HTML spec). So, your table should look like this:

<table class="sortable">
<thead>
  <tr><th>Person</th><th>Monthly pay</th></tr>
</thead>
<tbody>
  <tr><td>Jan Molby</td><td>£12,000</td></tr>
  <tr><td>Steve Nicol</td><td>£8,500</td></tr>
  <tr><td>Steve McMahon</td><td>£9,200</td></tr>
  <tr><td>John Barnes</td><td>£15,300</td></tr>
</tbody>
<tfoot>
  <tr><td>TOTAL</td><td>£45,000</td></tr>
</tfoot>
</table>

Note how sorting the table leaves the TOTAL row at the bottom.

PersonMonthly pay
Jan Molby£12,000
Steve Nicol£8,500
Steve McMahon£9,200
John Barnes£15,300
TOTAL£45,000

Show "sort icons" before the table is sorted

It's possible to show a symbol in a sortable table's column headers to indicate that the table is sortable. Something like this:

SeriesMarks out of ten
Original series7
Next Generation9
DS95
Voyager2
Enterprise3

To do this, add a bit of CSS to your stylesheet:

table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):after { 
    content: " \25B4\25BE" 
}

Note that this requires support for CSS generated content, which needs a modern-ish browser. You can, of course, change the generated content to whatever you want.

Using custom sort keys

You may have some data which does go in an order but isn't identified by sorttable. The way to fix this problem is to use custom sort keys. Take, for example, a column of spelled out numbers. Ordinarily, sorttable wouldn't work here; it will treat the spelled-out numbers as strings, and so would sort the numbers in alphabetical order, i.e., five, four, one, three, two. To get around this, you can specify on a cell in your table a sorttable_customkey attribute, and sorttable will use the contents of that attribute instead of the text in the cell itself when sorting the table. So, for example, your table might look like this:

<table class="sortable">
<tr><th>Number (spelled)</th><th>Person</th></tr>
<tr><td sorttable_customkey="2">two</td><td>Jan</td></tr>
<tr><td sorttable_customkey="3">three</td><td>Bruce</td></tr>
<tr><td sorttable_customkey="1">one</td><td>Steve</td></tr>
</table>

Note that clicking on the "Number (spelled)" column in the table below sorts it in the correct one,two,three order.

Number (spelled)Person
twoJan
threeBruce
oneSteve

You can fix practically any problem you have with sorttable's automatic column typing by specifying custom sort keys.

Manually specifying a column's type

Sorttable works out the type of your columns in order to work out how to sort them (numbers sort differently than letters, for example). Occasionally, it might get it wrong. If so, you can explicitly specify a type for a column, which will override sorttable's assessment. To specify a type, add a class of sorttable_columntype to the header row of that column. Available column types are numeric, alpha, ddmm, and mmdd. The latter two are for dates, but are not likely to be useful because if sorttable fails to automatically identify a date then the sort won't work anyway.

So, for example, if you have a "part number" column which you want to be treated as if it were numeric, then you might do your table like this:

<table class="sortable">
<tr>
  <th class="sorttable_numeric">Part number</th><th>Part name</th>
</tr>
<tr>
  <td>111-A5</td><td>Three-eighths Gripley</td>
</tr>
<tr>
  <td>31337-H4X0R</td><td>Computer system intrusion toolkit</td>
</tr>
</table>

Remember: you probably do not need to do this. It is unlikely that you'll need to "force" sorttable to recognise a column type. You may also want to investigate using custom sortkeys, above, as a better way of achieving your goals.

Using custom date formats

One common question with sorttable is how to make it handle custom date formats. Sorttable will have a try at understanding dates in whatever format you add them in, but it sometimes needs help. The way to do this is with custom sort keys, as mentioned above. If you have table cells like this:

<td>February 11th 2008, 1.19pm</td>

change them by adding a custom sort key in YYYYMMDDHHMMSS format:

<td sorttable_customkey="20080211131900">February 11th 2008, 1:19pm</td>

The YYYYMMDDHHMMSS format for the date in the custom key will sort properly, and sorttable will use the information in the custom key rather than the information in the table cell itself.

Stable sorting

Sorttable, by default, does an unstable sort. This means that it does not maintain the order of rows where those rows have the same key in the sorted column. Wikipedia has more on stable sorting. If this is a problem, and you need the sort to be stable, you can do it by making a tiny edit to sorttable.js. Edit the file and find the lines:

/* If you want a stable sort, uncomment the following line */
//sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
/* and comment out this one */
row_array.sort(this.sorttable_sortfunction);

and change them so the shaker_sort line is uncommented instead:

sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
//row_array.sort(this.sorttable_sortfunction);

The sort will now be stable. However, it will be considerably slower (the stable sorting can take eight times as long as the unstable sort), which is why it isn't enabled by default.

Sorting a table from your code

Sometimes you want to, from your own JavaScript code, tell a table to sort. This is deliberately awkward because you shouldn't be doing it, and you'll want to make sure that you have an up-to-date version of sorttable.js to do it (download it from this site), but it's doable. Call

var myTH = document.getElementsByTagName("th")[0];
sorttable.innerSortFunction.apply(myTH, []);

See the example table and buttons below.

NameCar
Stuart LangridgeNissan Juke
Jeremy ClarksonMercedes CLK Black
Penelope PitstopThe Pink Pussycat
The Ant Hill MobChug-a-Boom

Making some columns unsortable

If you'd like some column headers to not be clickable, meaning that your users won't be able to resort the table by those columns, then add class="sorttable_nosort" to the <th> column header. Observe how the "number of legs" column here isn't sortable.

NameTeam Number of legs
Molby, JanLiverpool2
Hughes, MarkManchester Utd2
Nicol, SteveLiverpool2
Ardiles, OssieTottenham Hotspur2
Nellie the ElephantLondon Zoo United4
Nicholas, CharlieArsenal2

Sorting the table when the page is loaded

Lots of people ask, "how do I make sorttable sort the table the first time the page is loaded?" The answer is: you don't. Sorttable is about changing the HTML that is served from your server without a page refresh. When the page is first served from the server, you have to incur the wait for it to be served anyway. So, if you want the table sorted when a page is first displayed, serve the table in sorted order. Tables often come out of a database; get the data from the database in a sorted order with an ORDER BY clause in your SQL. Any solution which involves you running sorttable as soon as the page loads (i.e., without user input) is a wrong solution.

(However, if you really want to, see sorting a table from your own code.)

Sort in descending order first

Making sorttable sort your columns in descending order first rather than ascending order requires editing sorttable.js. Find the line:

row_array.sort(this.sorttable_sortfunction);

and after it, add a new line:

row_array.reverse();

Sort case-insensitively

Making sorttable sort your columns case-insensitively (so uppercase and lowercase letters sort together) requires editing sorttable.js. Find the lines:

  sort_alpha: function(a,b) {
    if (a[0]==b[0]) return 0;
    if (a[0]<b[0]) return -1;
    return 1;
  },

and change them for

  sort_alpha: function(a,b) {
    if (a[0].toLowerCase()==b[0].toLowerCase()) return 0;
    if (a[0].toLowerCase()<b[0].toLowerCase()) return -1;
    return 1;
  },

Adding a "left-hand-header" column

A fairly common request is to have a column on the left of the table which contains a "row number" for each row (so the first row is "1", the second "2" and so on) which is not reordered when the table is sorted.

This is possible without sorttable using some advanced CSS. Add to your stylesheet:

table.sortable tbody {
    counter-reset: sortabletablescope;
}
table.sortable thead tr::before {
    content: "";
    display: table-cell;
}
table.sortable tbody tr::before {
    content: counter(sortabletablescope);
    counter-increment: sortabletablescope;
    display: table-cell;
}

and your sortable tables will now have a left-hand "row number" column in browsers which support this technique, which is basically everything these days from IE8 and onward.

A simple live example (remember that the "row number" column will not show in very old browsers)

NameAge
Methusaleh969
Elijah Snow100
Shirley Temple10
George Burns91
Mrs Robinson40

Alternately striping the table

It is quite common to want to add background striping ("zebra stripes") to a table and have those stripes work even after sorting.

This is possible without sorttable using some advanced CSS. Add to your stylesheet:

table.sortable tbody tr:nth-child(2n) td {
  background: #ffcccc;
}
table.sortable tbody tr:nth-child(2n+1) td {
  background: #ccfffff;
}

and your sortable tables will now be zebra striped in browsers which support this technique, which is basically everything these days from IE9 and onward.

A simple live example (remember that the striping will not show in very old browsers)

TeamColour
Liverpoolred
Englandwhite
Wolverhamptonorange
Arsenalred

Tables with a scrollable body

You can have a sortable table with a scrollable body, although it will require you to specify explicit widths for your columns. See http://jsbin.com/enotac/2 for a worked example; CSS inspiration for the scrollable body was taken from Terence Ordona.

CompanyLeader
Kryogenix ConsultingStuart Langridge
AppleTim Cook
OracleLarry Ellison
VirginRichard Branson
Louis VuittonLouis Vuitton
CanonicalMark Shuttleworth
GoogleLarry Page
ArmaniGiorgio Armani
FerrariEnzo Ferrari

Can I sort tables on a page I didn't write?

You can load sorttable from a bookmarklet. A simple example, which makes all tables on the current page sortable, is make tables sortable. Drag it to your bookmarks bar and then clicking it while on a page will make all tables on that page sortable.

Changes from sorttable v1

Sorttable has changed quite a lot in this new version 2. Please read the release announcement for more details of what's changed and who is to be thanked. If for some reason you need the original version 1 of sorttable you can download it from sorttable_v1.js along with the original instructions.

Licencing

Sorttable, like all my DOM scripts, is under the X11 licence, which basically means you can do what you want with it, including using it at work, in a commercial setting or product, or in open source projects (including those that are GPL licenced). If you're not sure, or you have other questions, please contact me for details.

Can I give you money for sorttable? I really like it

You don't have to. I believe in Free Software; writing this and seeing people use it is its own reward. Of course, if you're determined to give me money then I'm not going to stop you. You can send money to my PayPal account with the button below.

I've found a problem in sorttable. How can I tell you about it?

Firstly, thanks for using sorttable; sorry it's not doing quite what you want! If your question isn't answered on this page, please contact me and tell me about it, and I'll try and give you some pointers on how to fix it yourself.

But I need my problem with sorttable fixed! Can I pay you to fix it?

Yes. Sorttable gets worked on in my spare time, between paid work, which means that development might not be as fast as you like. If you really want something fixed, you can jump it up my priority list by waving money at me. Best thing to do is to contact me and we can talk about rates and so on.

Stuart Langridge, November 2003, April 2007

kryogenix.org | other browser experiments