Client-side table sorting using DOM scripting

Update: Please note that this content contains decade-old “old school” stuff.

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!

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

Write a comment

You need to enter name and email, but your email will never be visible.