Mink Machine

Client-side table sorting using DOM scripting

Update: Please note that this content contains decade-old “old school” stuff
and should not be considered as best practise.

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. The big advantage is of course that all activity takes place on the client side, thus avoiding any unnecessary chatting with the server.

Below is a live demonstration. 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

Mark it up

How to achieve this? We will start with the table. Create a HTML file with the following markup:

<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, like this:

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

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

New script kids on the block

This calls for an implementation of SortTable. This little thing will perform the following action:

  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 achieved 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.

Here is the full code.

<!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!


  • avatar
    23 Nov, 2007


  • avatar
    15 Sep, 2008

    This makes live sweet : )

  • avatar
    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
    28 May, 2010

    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;
    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
    07 Nov, 2012

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

  • avatar
    21 Jun, 2013


    jus suggestin an easier way. :)

Post a comment

Your email address will not be published. Required fields are marked *

Featured stories

The lakes of Lombardy

"The town of Como, largest settlement around Lake Como, attracts a lot of people with big wallets. But I preferred to take the funicular up the mountain to the Brunate region, where you get a much better view of the lake."

The streets of Paris

"One of the advantages of repeated visits to a place is the leisure pace of awe and discovery while drifting slowly down the worn streets of the French capital."

Conquering Machu Picchu

"A life-long dream came true this morning, as I stood upon the mountain looking down at Machu Picchu. I felt like some strange mix between Indiana Jones and a small boy, gazing down upon the final treasure of the Incas."

Chilling in Chile

"My weary feet has reached Valparaiso. After almost a month of traveling across the South American continent I realize that this is as far south as I will come, due to weather conditions."

Reliving history in Washington D.C.

"As I entered the heavily guarded Rotunda in the center, some of the most famous documents in the world laid before me."

The urban maze of Tangier

"There are exciting things waiting around every corner and my bucket list is long, but the Medina has a mindset of its own regarding time and space."