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

Getting lost in Yazd

"Navigating on random while surrounded by staring old men, pointing their crooked fingers at the Godzilla Viking in surprise. It feels like I’m walking around in Mos Eisley."

Visions of Singapore

"By extensive use of landfill with sand bought from Indonesia and Cambodia, the bay area has expanded greatly in the last few years and tall buildings pop up everywhere."

The dark days of Sarajevo

"The city survived on the edge of annihilation and has started to recover, but the stone walls still seem to cry out in lament of all the horrible things they have seen."

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

The sound of Salzburg

"It is based on the true story of Maria von Trapp, even though I suspect she didn’t go singing alone in the mountain ranges."

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