Bookmark and Share

Table Sort

See the demo page for the finished version of the code.

Altering the Table Display

Initially, every other row in the body of both tables has a style class assigned to its TR tag. This gives the rows an alternating background color for improved readability.

All attributes are retained as the sort function moves those rows around within the table body. So after sorting, chances are that this alternating pattern will be broken.

So after sortTable() finishes sorting the rows, it calls a function named makePretty() to fix the display. It will go through the rows and restore the alternating backgrounds by changing the row elements className properties. It will also do the same for each cell in those rows in order to highlight the column that was just sorted.

First, a few global variables are defined to make things easier. These include strings designating the style class names to be used and some regular expressions.

// Style class names.
var rowClsNm = "alternateRow";
var colClsNm = "sortedColumn";

// Regular expressions for setting class names.
var rowTest = new RegExp(rowClsNm, "gi");
var colTest = new RegExp(colClsNm, "gi");

An element may have multiple class names assigned to it. This is done by listing the class names, separated by spaces, in the tag's CLASS attribute or by setting the className property of its corresponding DOM element with a string in that same format.

Adding and Removing Class Names

In order to preserve any other class names that may be set for a row or column element, we'll use these regular expressions to remove just the one designated class name with code like the following:

rowEl.className = rowEl.className.replace(rowTest, "");

Conversely, to add the class name to an element, we just append the name to its className property with a space.

rowEl.className += " " + rowClsNm;

Setting the alternate row styles and highlighting the sorted column is then accomplished by looping through each row and cell.

function makePretty(tblEl, col) {

  var i, j;
  var rowEl, cellEl;

  // Set style classes on each row to alternate their appearance.
  for (i = 0; i < tblEl.rows.length; i++) {
   rowEl = tblEl.rows[i];
   rowEl.className = rowEl.className.replace(rowTest, "");
    if (i % 2 != 0)
      rowEl.className += " " + rowClsNm;
    rowEl.className = normalizeString(rowEl.className);
    // Set style classes on each column (other than the name column) to
    // highlight the one that was sorted.
    for (j = 2; j < tblEl.rows[i].cells.length; j++) {
      cellEl = rowEl.cells[j];
      cellEl.className = cellEl.className.replace(colTest, "");
      if (j == col)
        cellEl.className += " " + colClsNm;
      cellEl.className = normalizeString(cellEl.className);

So the function runs through each row first removing the alternate row style class from it. Then, if it an odd numbered row, it adds the class name back.

Note how the normalizeString() function is used here to clean up the class name list so it doesn't keep growing with extra spaces. This is the same function, described earlier, that we used with getTextValue() to remove extra white space in the text extracted from a table cell.

Within each row, we also loop through each cell, doing basically the same thing with the style class for highlighting the sorted column. The only difference is that we skip the first two columns because the first is not sortable and the second is the team name column. There is no compelling reason for not highlighting the team names, it's just an aesthetic choice.

Setting the Column Header Style

The next step in makePretty() is to highlight the column header, that is, the table cell containing the sort link that was clicked.

The tblEl argument that was passed by sortTable() refers to the table body. But the sort link resides in a row within the head section of the table. So first we need to find that row. Fortunately, this is relatively easy.

We first use the parentNode property of tblEl to get to the TABLE element that both the head and body belong to. Then we use the tHead property of that node to get to the last row in the table head.

  var el = tblEl.parentNode.tHead;
  rowEl = el.rows[el.rows.length - 1];

Given the way the tables are set up, this will be the row containing the sort links (the first row in the head section contains a single, spanned cell for displaying a title).

From there, we do exactly what we did for the cells in each row of the table body.

  // Set style classes for each column as above.
  for (i = 2; i < rowEl.cells.length; i++) {
    cellEl = rowEl.cells[i];
    cellEl.className = cellEl.className.replace(colTest, "");
    // Highlight the header of the sorted column.
    if (i == col)
      cellEl.className += " " + colClsNm;
    cellEl.className = normalizeString(cellEl.className);

Once makePretty() finishes, sortTable() will then call setRanks()to display the team rankings in the first column of the table.