Table Sort
See the demo page for the finished version of the code.Choosing a Sort Algorithm
There are several well-known methods for sorting items in a list. Some are theoretically faster than others but there are other considerations, such as the number of items to sort and the expense of moving items around within the list.
For an HTML table, we can assume a fairly small number of rows. Since web pages are documents intended for human viewing, displaying millions, thousands or even hundreds of rows of data is generally not practical. Likewise, since we will be dynamically modifying the DOM, we want to minimize the number of row swaps performed since these can be relatively expensive operations.
The selection sort makes a good candidate. Compared to other sort algorithms, it's relatively fast for the number of items we'd expect to find in a typical table display. Also, in a worst case senario, it requires only one swap per item.
The Selection Sort
A selection sort works like this: starting with the entire list of items, you find the smallest one. You then move this item to the beginning of the list. Then you look at the items that are left, again finding the one with the smallest value. That item you move to the position just after the first.
This continues until you get down to the last item left which, by then, will be the largest in the list. The diagram below illustrates the process.
7 |
5 |
3 |
1 |
---|
4 |
1 |
---|
7 |
5 |
3 |
4 |
1 |
---|
7 |
5 |
3 |
4 |
1 |
---|
3 |
7 |
5 |
4 |
1 |
---|
3 |
7 |
5 |
4 |
1 |
---|
3 |
4 |
7 |
5 |
1 |
---|
3 |
4 |
7 |
5 |
1 |
---|
3 |
4 |
5 |
7 |
This process will work well for sorting the table rows because moving an item involves two actions, removing it (the row node) from the list (table section node) and then inserting it back at a specific location. The DOM already provides simple methods for removing and inserting nodes.
The Sort Code
So let's look at the sortTable()
function. The first order of
business is to get the table or table section that contains the rows to be
sorted.
function sortTable(col) { // Get the table section to sort. var tblEl = document.getElementById("planetData"); // Set the table display style to "none" - necessary for Netscape 6 // browsers. var oldDsply = tblEl.style.display; tblEl.style.display = "none";
Here, we just use document.getElementByID()
with the id of the
TBODY tag, "planetData."
display
style property
to none
and then restore it after we're done sorting. Fortunately,
this has no adverse effect on other browsers so it's done for all.
Next we do the actual sorting. We start with a loop to run from the first row to the next to last row. This will give us the insert position for each step. Within this loop, we want to look at all the rows between this position and the last row to find the one with the smallest value in the selected column. So a second, inner loop is started.
// Sort the rows based on the content of the specified column // using a selection sort. var tmpEl; var i, j; var minVal, minIdx; var testVal; var cmp; for (i = 0; i < tblEl.rows.length - 1; i++) { // Assume the current row has the minimum value. minIdx = i; minVal = getTextValue(tblEl.rows[i].cells[col]); // Search the rows that follow the current one for a smaller value. for (j = i + 1; j < tblEl.rows.length; j++) { testVal = getTextValue(tblEl.rows[j].cells[col]); cmp = compareValues(minVal, testVal); // If this row has a smaller value than the current minimum, // remember its position and update the current minimum value. if (cmp > 0) { minIdx = j; minVal = testVal; } }
The minVal
variable contains the smallest column value found
so far while minIdx
is used to keep track of the index of the row
that value was found in. We initially assume the first row has the smallest
value, but any of the rows could be used since all of them will be
compared.
Once we finish this inner loop, we'll know which row needs to be moved to the current insert position. If it happens to be the row currently in that position, we just leave it. Otherwise, we move it.
// By now, we have the row with the smallest value. Remove it from // the table and insert it before the current row. if (minIdx > i) { tmpEl = tblEl.removeChild(tblEl.rows[minIdx]); tblEl.insertBefore(tmpEl, tblEl.rows[i]); } }
The DOM removeChild()
method removes the row from the document
and returns that element node. The row is still a valid element node, it's just
no longer a part of the document. We can then use the DOM
insertBefore()
method to move the row node back into the table
section at the current insert position.
Once the rows have been sorted, we can restore the table display and return.
// Restore the table's display style. tblEl.style.display = oldDsply; return false; }
Note that the sort function returns a value of false
because it
will be called using the onclick
event of a link tag. We don't
want the browser to actually follow the link, just want it to call the sort
function. Returning false
will prevent the browser from trying to
load the link URL.
Now let's see the code in action.