Introduction
This tutorial contains client side sorting (ascending and descending) of a table according to the type of data you specify in the HTML. Just add the "type=Date
" and "onclick="sortTable(event,0)"
" attributes to each cell in the thead
section of the table (second parameter of the function is the index of the column starting from zero).
This JavaScript code can be used to write your own sorting on any form of Array
data type. As you know, JavaScript is a loosely typed language, so the generic sorting function available in the Array
object can be used to sort any type of data in an Array
object. Only thing you have to do is to write a custom comparing logic which can be called with the Array.sort()
function. With three easy steps, you can implement your own sorting mechanism.
- Populate the
Array
object with specific data you need. If the table is to be sorted, take each row into the Array
. - Write the custom comparing function. If the values that need to be sorted are of type
date
or float
, write a function to compare those values. - Call the
Array
object's sort()
function by passing the custom comparing function name as parameter.
Array
's sort
function internally calls the function passed to it to compare two values. So this custom function should take two arguments. And it should return a positive or negative value or zero. If it returns any other data, the sort
function will throw an error. In this example function, Custom()
is used to compare different types of data. This way, you can implement sorting your own type of data.
Here's the code I have writen to implement sorting:
var type;
var columnIndex,lastIndex,isDescending;
var upArrow,downArrow;
function initSortArrows()
{
upArrow = document.createElement("SPAN");
var node6 = document.createTextNode("6");
upArrow.appendChild(node6);
upArrow.className = "arrow";
downArrow = document.createElement("SPAN");
var node5 = document.createTextNode("5");
downArrow.appendChild(node5);
downArrow.className = "arrow";
}
function toString(value)
{
return value.toUpperCase();
}
function toDate(value)
{
return Date.parse(value);
}
function Custom(a,b)
{
if(a==undefined||b==undefined)
return 0;
var val1=a.children[columnIndex].innerText;
var val2=b.children[columnIndex].innerText;
var a1=val1.split('.');
var b1=val2.split('.');
var maxlength;
if(a1.length>b1.length)
maxlength=a1.length;
else
maxlength=b1.length;
for(var i=0;i<maxlength;i++)
{
if(a1[i]!=undefined && b1[i]!=undefined)
{
if(parseInt(a1[i])==parseInt(b1[i]))
{
continue;
}
else
{
if(parseInt(a1[i])<parseInt(b1[i]))
return isDescending?-1:+1;
if(parseInt(a1[i])>parseInt(b1[i]))
return isDescending ?+1:-1;
return 0;
}
}
else
{
if(a1[i]==undefined)
return -1;
else
return 1;
}
}
return 0;
}
function customCompare(type,isDescend,columnIndex)
{
var TypeCast;
if(type=="Number")
TypeCast=Number;
else if(type=="Date")
TypeCast=toDate;
else if(type=="Custom")
return Custom;
else
TypeCast=toString;
return function(row1,row2)
{
var val1,val2;
val1=row1.children[columnIndex].innerText;
val2=row2.children[columnIndex].innerText;
if(TypeCast(val1)<TypeCast(val2))
return isDescend ?-1:+1;
if(TypeCast(val1)>TypeCast(val2))
return isDescend ?+1:-1;
return 0;
}
}
function sortTable(eventclick,index)
{
if(upArrow==undefined)
initSortArrows();
var cell=eventclick.srcElement;
if(cell.tagName=="SPAN")
cell=cell.parentElement;
else if (cell.type==undefined)
type="String";
else
type=cell.type;
columnIndex=index;
var thead=cell.parentElement;
var table=thead.parentElement.parentElement;
if(!table.tBodies)
{
table=table.parentElement;
thead=thead.parentElement;
}
var tblBody = table.tBodies[0];
var tblRows = tblBody.rows;
if(columnIndex==lastIndex)
{
if(isDescending==true)
isDescending=false;
else
isDescending=true;
}
else
isDescending=true;
var rowArray=new Array();
for(var i=0;i<tblRows.length;i++)
{
rowArray[i]=tblRows[i];
}
rowArray.sort(customCompare(type,isDescending,columnIndex));
for(var i=0;i<rowArray.length;i++)
{
tblBody.appendChild(rowArray[i]);
}
if(lastIndex==undefined)
{
cell.appendChild(downArrow.cloneNode(true));
isDescending=true;
}
else if(index!=lastIndex)
{
thead.cells[lastIndex].removeChild(thead.cells[lastIndex].children[0]);
cell.appendChild(downArrow.cloneNode(true));
}
else if(index==lastIndex)
{
cell.removeChild(cell.children[0]);
if(isDescending==true)
cell.appendChild(downArrow.cloneNode(true));
else
cell.appendChild(upArrow.cloneNode(true));
}
lastIndex=index;
}
Using the Code
The rowArray.sort()
function will call the customCompare()
function internally each time to compare two values. This function returns another function which will take two arguments and return +1, -1, or 0. The only thing we have to take care of is to return a positive or negative data from the customCompare
function. Here, I have added one more level of abstraction, which will find out what type of data to compare and what is specified as a 'type' attribute in the HTML table header columns.
Points of Interest
The code available for download contains sorting of date, case insensitive string, and a custom data type. It will also add an up arrow or down arrow automatically to the table column header. To get the arrows dynamically, a CSS class array should be added.
History
- 18 Sep. 2007 - Created.
- 05 Oct. 2007 - Modified.
- 16 Oct. 2007 - Modified.