examples/html/js/tablesort.js
/*
* $Id: tablesort.js,v 1.4 2009/05/08 18:21:06 andnyb Exp $
*
* Based on various examples from
* http://www.terrill.ca/sorting/
*
*/
function TableSort() {
var table = new Object; // The table to be sorted
var columnNames = new Array;
var tableRows = new Array;
var columnIdx = new Object();
var columnTypeAbbr = new Object();
var N = 0;
var previouslySortedColumn = '0'; // Default sorting on Run column.
function get(index){
var ret = getCell(index).firstChild.nodeValue;
if (null==ret) {
ret = getCell(index).firstChild.text;
}
return ret;
}
function getCell(index){
return tableRows[index].cells[columnIdx];
}
/**
* Main entry function. Registers the methods that gets invoked when clicking
* the column headers.
*/
this.init = function(tableId) {
table = document.getElementById(tableId);
if (null==table) {
return false;
}
// get all the column names
columnNames = table.getElementsByTagName("th");
// for each column name we register the sortOnColumn method.
for(var i=0; i<columnNames.length; i++) {
columnNames[i].onclick = function() {
sortOnColumn(this);
}
}
return true;
};
/**
* Triggers the sorting of the rows based on the column that was clicked.
*
* @param column The column object that was clicked on.
*/
function sortOnColumn(column) {
columnIdx = column.cellIndex;
columnTypeAbbr = column.abbr; // In case there is some special comparison needed.
if (column.innerHTML == "SPREAD") {
return;
}
tableRows = table.tBodies[0].getElementsByTagName("tr"); // Get rows from first TBODY in the table
// Check the sorting
if (previouslySortedColumn==columnIdx) {
if ('0'==columnIdx) {
column.className = (column.className != 'graphHeaderLeftAsc' ? 'graphHeaderLeftAsc' : 'graphHeaderLeftDesc' );
} else {
column.className = (column.className != 'graphHeaderAsc' ? 'graphHeaderAsc' : 'graphHeaderDesc' );
}
reverseTable();
} else {
if ('0'==columnIdx) {
column.className = (column.className != 'graphHeaderLeftAsc' ? 'graphHeaderLeftAsc' : 'graphHeaderLeftDesc' );
} else {
column.className = (column.className != 'graphHeaderAsc' ? 'graphHeaderAsc' : 'graphHeaderDesc' );
}
// Resetting the TD class
if ('0'==previouslySortedColumn) {
columnNames[previouslySortedColumn].className = 'graphHeaderLeft';
} else {
columnNames[previouslySortedColumn].className = 'graphHeader';
}
// Works, but there is a need to sort the columns based on type.
N = (tableRows.length)/2;
if ((k = Math.floor(N/5)) > 7) {
for (var m=0; m<k; m++) {
isort(true, m, k);
}
}
if ((k = Math.floor(N/7)) > 7) {
for (var m=0; m<k; m++) {
isort(true, m, k);
}
}
for (k=7; k>0; k-=2) {
for (var m=0; m<k; m++) {
isort(true, m, k);
}
}
}
previouslySortedColumn = columnIdx;
}
/**
* Shell sort, check Wikipedia.
*
* @param start Starting index
* @param step Step size
*/
function isort(desc, start, step) {
for(var j=start+step; j<N; j+=step) {
if (desc==true) {
for(var i=j; i>=step; i-=step) {
var first = get(i*2);
var second = get(((i-step)*2));
if ('input_text'==columnTypeAbbr) {
var fIdx1 = first.indexOf('>');
if (fIdx1<0) {
fStripped = first;
} else {
var fIdx2 = first.lastIndexOf('<');
fStripped = first.substring((fIdx1+1),(fIdx2-1));
}
var sIdx1 = second.indexOf('>');
if (sIdx1<0) {
sStripped = second;
} else {
var sIdx2 = second.lastIndexOf('<');
sStripped = second.substring((sIdx1+1),(sIdx2-1));
}
if (fStripped>sStripped) {
exchange(i, (i-step));
}
} else if ('number'==columnTypeAbbr) {
var fa = parseFloat(first);
var sa = parseFloat(second);
if (isNaN(fa) ) {
fa = 0;
}
if (isNaN(sa) ) {
sa = 0;
}
if (fa>sa) {
exchange(i, (i-step));
}
} else if ('date'==columnTypeAbbr){
if (first>second) {
exchange(i, (i-step));
}
} else if ('float'==columnTypeAbbr){
// Cannot find so we take the next char
var fIdx = first.indexOf('(')-1;
var sIdx = second.indexOf('(')-1;
var fStripped = "";
var sStripped = ""
if (fIdx<0) {
fStripped = first;
} else {
fStripped = first.substring(0, fIdx);
}
if (sIdx<0) {
sStripped = second;
} else {
sStripped = second.substring(0, sIdx);
}
var fa = parseFloat(fStripped);
var sa = parseFloat(sStripped);
if (isNaN(fa) ) {
fa = 0;
}
if (isNaN(sa) ) {
sa = 0;
}
if (fa>sa) {
exchange(i, (i-step));
}
} else if ('percent'==columnTypeAbbr){
// Cannot find so we take the next char
var fIdx = first.indexOf('%');
var sIdx = second.indexOf('%');
var fStripped = first.substring(0, fIdx);
var sStripped = second.substring(0, sIdx);
var fa = parseFloat(fStripped);
var sa = parseFloat(sStripped);
if (isNaN(fa) ) {
fa = 0;
}
if (isNaN(sa) ) {
sa = 0;
}
if (fa>sa) {
exchange(i, (i-step));
}
}
}
}
}
}
/**
* Swaps two different rows.
*
* @param i Index of the row to insert in front of row j.
* @param j The row to be swapped with.
*/
function exchange(i, j) {
i = i*2; // Switching only every second row.
j = j*2; // Switching only every second row.
if(i == j+1) {
table.tBodies[0].insertBefore(tableRows[i], tableRows[j]);
} else if(j == i+1) {
table.tBodies[0].insertBefore(tableRows[j], tableRows[i]);
} else {
var tmpNode = table.tBodies[0].replaceChild(tableRows[i], tableRows[j]);
if(typeof(tableRows[i]) == "undefined") {
table.tBodies[0].appendChild(tmpNode);
} else {
table.tBodies[0].insertBefore(tmpNode, tableRows[i]);
}
}
}
/**
* Reversing the tables rows. Simply walks through them all and replaces the top one.
*/
function reverseTable() {
var topRow = tableRows[0];
for(var i = 2; i<tableRows.length; i+=2) {
table.tBodies[0].insertBefore(tableRows[i], topRow);
topRow = tableRows[0];
}
}
}
// EOS