So, using the concepts detailed in the sorting objects article. I put together a simple demo that uses the technique to sort a hard-coded table.
Click on a cell header to sort the table in Ascending order of the values for that column.
Click again to sort the table in descending order.
| First Name | Middle Name | Last Name |
|---|---|---|
| Mike | Joeseph | Smith |
| Nicholas | Michael | Peterson |
| Mary | Frances | Jones |
| Josephine | Marie | Adams |
source:
/*
Create an object that represents a single row of data
in this example it is a simple table consisting of 3 columns
first name, middle name, last name
*/
function tableRow(fname, mname,lname){
this.fname = fname;
this.mname = mname;
this.lname = lname;
//default sort setting
this.sortby = fname;
/*
this setsortby method sets the value of the sort by property of this object (in our case this row)
there are some things to be aware of: note case matters when sorting so set all
strings to lower case. Also there are special rules with the array.sort() method which
will actually do the sorting work. For example numerical sorting will take an extra step.
See the JavaScript documentation for more on sorting caveats.
Also this setsortby method is a simple case that will only work for sorting string data.
Sorting numbers is also simple and easy to implement. Things get a lot more interesting
when you you have to sort by dates and times. For those cases you will need to create
Date objects from the date strings and store the Date objects millisecond value as the
sorby value. This millisecond value can then be sorted like any other number.
*/
this.setsortby = function (property){ this.sortby = this[property].toLowerCase() };
/*
this toString method overrides the default to string method and instead returns the value
stored in the sortby property
*/
this.toString = function (){return this.sortby};
}
/*
I need to store an object defines which column and which direction
is currently being sorted
*/
var activeSort = null;
/*
this is an object that stores the column name that is currently being sorted on
and which direction
*/
function sortReference(column, direction){
this.column = column;
this.direction = direction;
}
/*
The sortby() method is a workflow method that ddefines the order
of work that needs to be done.
The parameter columnid needs to macth a property defined in our tableRow object
*/
function sortby(columnid){
/*
create array of tabletRow objects based on the data in the table
NOTE: this script assumes a single tbody defines the table data
a better and more efficient way to handle this is to send the data to the client
as and array of tableRow objects to begin with and then create the table
on the client at runtime, but since I doubt many developers follow this practice
I've created this demo which works with hard coded table data
*/
var rowArray = createTableRowArray();
//loop through the array and set the sortby property
for (var x=0;x<rowArray.length;x++) {
rowArray[x].setsortby(columnid);
}
//get the sort direction, and store for future reference
var direction = getSortDirection(columnid);
//sort the array
rowArray.sort();
//if descending reverse the array
if (direction == "dsc") rowArray.reverse();
//rebuild the table from the array of tableRow objects
createTable(rowArray);
}
function createTableRowArray(){
var data = new Array();
var table = document.getElementById("tableData");
var tbody = table.tBodies[0];
var rows = tbody.rows;
for (var x=0;x<rows.length;x++) {
var cells = rows[x].cells;
var aTableRow = new tableRow(cells[0].innerHTML, cells[1].innerHTML, cells[2].innerHTML);
data.push(aTableRow);
}
return data;
}
function getSortDirection(columnid){
if (activeSort == null || activeSort.column != columnid) {
activeSort = new sortReference(columnid, "asc");
}else{
if (activeSort.direction == "asc") {
activeSort.direction = "dsc";
}else{
activeSort.direction = "asc";
}
}
return activeSort.direction;
}
function createTable(rowArray){
var table = document.getElementById("tableData");
var tbody = table.tBodies[0];
var mybody = tbody.cloneNode(false);
var numOfArguments = tableRow.length;
for (var x=0;x<rowArray.length;x++) {
var index = 0;
var tr = document.createElement("TR");
for (var i in rowArray[x]) {
if (index == numOfArguments) break;
var td = document.createElement("TD");
td.innerHTML = rowArray[x][i];
tr.appendChild(td);
index++;
}
mybody.appendChild(tr);
}
table.replaceChild(mybody, tbody);
}