
/****************************************
* Sorting table data by the specified column.
* 
* Assumption.
*     1) the table must have thead and tbody tags.
*     2) the code invoking this SortTable obj must exist in 'th' within 'thead' tag.
*     3) the td tag must have a sorting value in the attribute, 'dispVal'.
*	  
* Reserved attring name :
*     1) 'dispVal'
*     2) 'lastSortBy'
*
*  Example.     new SortTable().sort(thObj, indexOfColumn, isNumberSorting)
*  
*  Parameter type :
*     thObj - the object of 'th'
*     indexOfColumn - integer
*     isNumberSorting - boolean
*  
*/



function SortTable(){
	this.CSSClsName;
	this.altCSSClsName;
}

SortTable.prototype.sortNumber = function(a, b){
	return a - b;
}

SortTable.prototype.sort = function(td, idx, isNumber){

//	this.setMousePointer();
	
	var tBody = this.getTBody(td);
	this.CSSClsName = tBody.getAttribute("CSSClsName");
	this.altCSSClsName = tBody.getAttribute("altCSSClsName");
	
	if(!tBody){ return	};
	
	var tBodyChilArr = tBody.childNodes;
	
	var indexArray = new Array();
	var indexMap = new SortTableIndexMap();
	
	var oldtrArr = new Array();
	this.constIndex(tBodyChilArr, idx, indexArray, indexMap, oldtrArr);
	
	if(isNumber){
		indexArray.sort(this.sortNumber);
	}else{
		indexArray.sort();
	}	

	var lastSort = td.getAttribute("lastSortBy");
	var newSortBy = lastSort?(lastSort == 'asc'?'desc':'asc'):'asc';
	
	if(newSortBy == 'desc'){
		indexArray.reverse();
	}
	
	var newtrArr = this.constNewTrArr(indexArray, indexMap);
	
	this.reconstructTable(tBody, oldtrArr, newtrArr);
	
	td.setAttribute('lastSortBy', newSortBy);
	
//	this.resetMousePointer();
//	var bodyArr = document.getElementsByTagName('body');
//	var body = bodyArr[0];
//	
//	body.appendChild(document.createTextNode("Total getTime : " + (getT/1000)));
//	body.appendChild(document.createElement('br'));
//	body.appendChild(document.createTextNode("Total appendTime : " + (appendT/1000)));
}

//SortTable.prototype.setMousePointer = function(){
//	var body = document.getElementsByTagName('body')[0];
//	var cur0 = body.style.cursor;
//	body.setAttribute("cur0", cur0);
//	body.style.cursor = "wait";
//}
//
//SortTable.prototype.resetMousePointer = function(){
//	var body = document.getElementsByTagName('body')[0];
//	body.style.cursor = body.getAttribute("cur0");
//}

SortTable.prototype.constNewTrArr = function(indexArray, indexMap){
	var newarr = new Array();
	var cnt = 0;
	
	for(var i = 0; i < indexArray.length; i++){
		var dispVal = indexArray[i];
		var trArr = indexMap.get(dispVal);
		
		for(var j = 0; j < trArr.length; j++){
			var tr = trArr[j];
			cnt++;
			newarr.push(tr);
		}
	}
	return newarr;
}


SortTable.prototype.constIndex = function(tBodyChilArr, idx, indexArray, indexMap, oldtrArr){
	var filter = new Object();
	
	for(var ridx = 0; ridx < tBodyChilArr.length; ridx++){
		var tr = tBodyChilArr[ridx];
		
		if(tr.nodeType != 1){
			continue;
		}
		
		if(tr.tagName.toLowerCase() != 'tr'){
			continue;
		}
		
		oldtrArr.push(tr);
		
		var tdCandArr = tr.childNodes;
		var tdArr = new Array();
		
		for(var i = 0; i < tdCandArr.length; i++){
			var obj = tdCandArr[i];
			if(obj.nodeType == 1 && obj.tagName.toLowerCase() == 'td'){
				tdArr.push(obj);
			}
		}
	
		var td = tdArr[idx];
		var dispVal = td.getAttribute("dispVal");

		if(!filter[dispVal]){
			indexArray.push(dispVal);		
			filter[dispVal] = true;
		}			
		indexMap.add(dispVal,tr);
	}
}

SortTable.prototype.getTBody = function(td){
	var tr = td.parentNode;
	var thead = tr.parentNode;
	var table = thead.parentNode;
	
	var blockArr = table.childNodes;
	
	for(var i = 0; i < blockArr.length; i++){
		var block = blockArr[i];
		if(block.nodeType == 1 && block.tagName.toLowerCase() == 'tbody'){
			return block;
		}
	}
}

	var getT = 0;
	var appendT = 0;

SortTable.prototype.reconstructTable = function(tBody, oldtrArr, newtrArr){
	
	this.removeChildNodes(tBody);

	for(var i = 0; i < oldtrArr.length; i++){
//		var oldtr = oldtrArr[i];
		var newtr = newtrArr[i];
		var cltr = newtr.cloneNode(true);
		
		if( i % 2 == 0){
			if(this.CSSClsName){
				newtr.className = this.CSSClsName;
			}
		}else{
			if(this.altCSSClsName){
				newtr.className = this.altCSSClsName;
			}
		}
		
//		tBody.replaceChild(cltr, oldtr);
		tBody.appendChild(newtr);
	}


}

SortTable.prototype.removeChildNodes = function(obj) {
    if (!obj) {
        return;
    }
    var len = obj.childNodes.length;
    while (obj.hasChildNodes()) {
        obj.removeChild(obj.firstChild);
    }
}


function SortTableIndexMap(){
	this.map = new Object();
}

SortTableIndexMap.prototype.add = function(k, v){
	var val = this.map[k];
	if(val){
		val.push(v);
	}else{
		var arr = new Array();
		arr.push(v);
		this.map[k] = arr;
	}
}

SortTableIndexMap.prototype.get = function(k){
	return this.map[k];
}

