Update: Please note that this content is outdated and should not be considered as best practice.

There are many ways to sort a table containing tabular data. A common approach is to perform the sort on the server using ASP or something similar, maybe out of routine using the same thought pattern as in ordinary desktop applications.

An alternative for web pages is to do it with client-side scripting. One advantage is that all activity takes place on the client side, thus avoiding any unnecessary round-trip to the server.

Below is an example. Click on the column headers to sort the column alphabetically.

Title Director Release date
Casablanca Michael Curtiz 1942
Citizen Kane Orson Welles 1941
Its a Wonderful Life Frank Capra 1946
Metropolis Fritz Lang 1927
North by Northwest Alfred Hitchcock 1959

Markup

The HTML markup looks like this:

<table id="movies"> <thead> <tr> <th>Title</th> <th>Director</th> <th>Release date</th> </tr> </thead> <tbody> <tr> <td>Casablanca</td> <td>Michael Curtiz</td> <td>1942</td> </tr> … </tbody> </table>

Next, insert links into the header and use the onclick event to call a JavaScript function.

<th> <a href="javascript:;" onclick="SortTable(0);">Title</a> </th>

Using the onclick attribute is not best practice, we should do it the proper way with event handlers, but this is only for demonstration purposes.

JavaScript

The simple implementation works as follows:

  1. Get all rows in our table
  2. For each row, get the data of selected column and store it in an array along with the index
  3. Sort the column data
  4. Select order of table rows using the sorted index and copy them to a new table body
  5. Replace old table body with sorted table body

This is quite easily done using the DOM. The rows are fetched by the usual getElement methods. Sorting is performed by two custom functions, depending on type of table column content. For the copy I use cloneNode, the DOM equivalent of innerHTML.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Table sort example</title> <script language="JavaScript" type="text/javascript"> <!– // initial column must be pre-sorted var previousColumnIndex = 0; function SortTable(selectedColumnIndex) { var table = document.getElementById("movies"); var tableBody = table.getElementsByTagName("tbody")[0]; var tableRows = tableBody.getElementsByTagName("tr"); // Get the data of selected column var originalColumnArray = new Array(); for (var i=0; i < tableRows.length; i++) { originalColumnArray[i] = new Object; originalColumnArray[i].oldIndex = i; originalColumnArray[i].value = tableRows[i].getElementsByTagName("td") [selectedColumnIndex].firstChild.nodeValue; } if (selectedColumnIndex == previousColumnIndex) { // User clicked on the same column again, reverse sort direction. originalColumnArray.reverse(); } else { // Select sorting method depending on column type if (selectedColumnIndex == 2) { originalColumnArray.sort(CompareDigits); } else { originalColumnArray.sort(Compare); } previousColumnIndex = selectedColumnIndex; } // Create a new tbody and copy old rows using the sorted index var sortedTableBody = document.createElement("tbody"); for (var i=0; i < originalColumnArray.length; i++) { sortedTableBody.appendChild(tableRows [originalColumnArray[i].oldIndex]. cloneNode(true)); } // Replace old table with new one table.replaceChild(sortedTableBody, tableBody); }

function Compare(x, y) { var xValue = x.value; var yValue = y.value; return (xValue == yValue ? 0 : (xValue > yValue ? 1 : -1)); }

function CompareDigits(x, y) { var xValue = parseInt(x.value); var yValue = parseInt(y.value); return (xValue – yValue); }

//–> </script> </head> <body> <h1>Table sort example</h1> <table id="movies" border="1"> <thead> <tr> <th><a href="javascript:;" onclick="SortTable(0);">Title</a></th> <th><a href="javascript:;" onclick="SortTable(1);">Director</a></th> <th><a href="javascript:;" onclick="SortTable(2);">Release date</a></th> </tr> </thead> <tbody> <tr> <td>Casablanca</td> <td>Michael Curtiz</td> <td>1942</td> </tr> <tr> <td>Citizen Kane</td> <td>Orson Welles</td> <td>1941</td> </tr> <tr> <td>Its a Wonderful Life</td> <td>Frank Capra</td> <td>1946</td> </tr> <tr> <td>Metropolis</td> <td>Fritz Lang</td> <td>1927</td> </tr> <tr> <td>North by Northwest</td> <td>Alfred Hitchcock</td> <td>1959</td> </tr> </tbody> </table> </body> </html>

Easy as pie. Good luck!

8 comments

  • avatar
    johan
    23 Nov, 2007

    sweet

  • avatar
    Robinder
    15 Sep, 2008

    This makes live sweet : )

  • avatar
    Tom
    19 Jan, 2010

    Thank you, very functional script! I’ve made a little modification to produce alternating colors on rows:
    var rowColor = 0;
    for ( var i=0 ; i Thank you, very functional script! I’ve made a little modification to produce alternating colors on rows:
    var rowColor = 0;
    for ( var i=0 ; i < originalColumn.length ; i++ ) { sortedTabBody.appendChild( tableRows[originalColumn[i].oldIndex]. cloneNode( true )); if ( rowColor % 2 == 0 ) { sortedTabBody.childNodes[i].setAttribute( "class", "even" ); } else { sortedTabBody.childNodes[i].removeAttribute( class" ); } rowColor++; }

  • avatar
    19 Jan, 2010

    @Tom: Thanks for your input!

  • avatar
    Bart
    28 May, 2010

    Hey!
    Just wanted to give you a heads up for the great script ^^ Gave me a good idea how to tackle my sorting problem. Also rewrote it to make use of jQuery ^^
    Just a little note… Wouldnt it be better to change:
    var previousColumnIndex = 0;
    to
    var previousColumnIndex;
    Costed me a lot of time to figure out why it sorted in a very strange way.
    Anyways, cheers for the great idea and you got a new follower now ^^

  • avatar
    02 Jun, 2010

    Bart, thanks a lot!

  • avatar
    Udara
    07 Nov, 2012

    Thanx a lot for this…I need to know how to sort in ascending order . . .

  • avatar
    Annonymous
    21 Jun, 2013

    tr:nth-child(2n){background-color:#fff;}
    tr:nth-child(2n+1){background-color:#666;}

    jus suggestin an easier way. :)

Leave a reply