// script based on mr. paul sowden's example at idontsmoke.co.uk (thanks, paul),
// but updated so as to become a mix-in.

// mix-in.js basically copies all members of SortableTable that begin with "st_"
// onto a target HTML object that is passed in. Other members can be thought of
// as "class" properties, and stay on only the SortableTable object.

var SortableTable = new MixIn("st", "TABLE");

SortableTable.SORT_ASCENDING_CLASS = "sort-ascending";
SortableTable.SORT_DESCENDING_CLASS = "sort-descending";

SortableTable.st_sortDirection = null;
SortableTable.st_sortColumn = null;
SortableTable.st_thead = null;
SortableTable.st_tbody = null;
SortableTable.st_onsort = new Function("iSortColumn", "bSortDirection", "");

SortableTable.st_init = function() {
	if (document.getElementsByTagName) {
		this.st_thead = this.getElementsByTagName("thead").item(0);
		this.st_tbody = this.getElementsByTagName("tbody").item(0);

		this.st_index = SortableTable.instances.length;
		SortableTable.instances[this.st_index] = this;

		var f = new Function("e", "SortableTable.instances[" + this.st_index + "].st_sort(e)");

		for (var i = 0, node = null; (node = this.st_thead.getElementsByTagName("th").item(i)); i++) {
			if (node.addEventListener) node.addEventListener("click", f, false);
			else if (node.attachEvent) node.attachEvent("onclick", f);
		}
	}
}

SortableTable.st_sort = function(e) {
	var el = window.event ? window.event.srcElement : e.currentTarget;

	// a pretty ugly sort function, but it works nonetheless
	var a = new Array();

	var sClass = SortableTable.SORT_ASCENDING_CLASS;
	var sortDirection = true;
	var sortColumn = el.cellIndex;

	for (var j = 0, node; (node = this.st_tbody.rows.item(j)); j++) {
		a[j] = new Array();
		a[j][0] = SortableTable.getConcatenedTextContent(node.cells.item(sortColumn));
		a[j][1] = node;
	}

	a.sort();

	// if they're already sorted this way, sort the other way!
	// not a perfect way to check, but hell, it suits me fine
	if (this.st_sortColumn == sortColumn && this.st_sortDirection == sortDirection)
	{
			a.reverse();
			sortDirection = false;
	}


	// reset the old sort header
	if (this.st_sortColumn != null) {
		SortableTable.removeClass(
			this.st_thead.getElementsByTagName("th").item(this.st_sortColumn), 
			this.st_sortDirection ? SortableTable.SORT_ASCENDING_CLASS : SortableTable.SORT_DESCENDING_CLASS
		);
	}
	

	// set the new one
	this.st_sortColumn = sortColumn;
	this.st_sortDirection = sortDirection;
	SortableTable.addClass(
		this.st_thead.getElementsByTagName("th").item(sortColumn), 
		this.st_sortDirection ? SortableTable.SORT_ASCENDING_CLASS : SortableTable.SORT_DESCENDING_CLASS
	);

	
	// resort the rows
	for (var j = 0; j < a.length; j++) {
		this.st_tbody.appendChild(a[j][1]);
	}

	this.st_onsort(this.st_sortColumn, this.st_sortDirection);
}



// can anyone say "innerText" ?
SortableTable.getConcatenedTextContent = function(node) {
	var _result = "";
	if (node == null) {
		return _result;
	}	
	var childrens = node.childNodes;
	var i = 0;
	while (i < childrens.length) {
		var child = childrens.item(i);
		switch (child.nodeType) {
			case 1: // ELEMENT_NODE
			case 5: // ENTITY_REFERENCE_NODE
				_result += this.getConcatenedTextContent(child);
				break;
			case 3: // TEXT_NODE
				_result += child.nodeValue;
				break;
			default:
			    // skip
			    break;
		}
		i ++;
	}
	return _result;
}



// addClass does not add the class if it is already in place. 
SortableTable.addClass = function(el, sClass) {
	var a = el.className.split(" ");
	for (var i = 0; i < a.length; i++) {
		if (a[i] == sClass) return;
	}
	a[a.length] = sClass;
	el.className = a.join(" ");
}

// removeClass is ok to use, even if the element does not have the given class.
SortableTable.removeClass = function(el, sClass) {
	var a = el.className.split(" ");
	var b = new Array();
	for (var i = 0; i < a.length; i++) {
		if (a[i] != sClass) b[b.length] = a[i];
	}
	el.className = b.join(" ");
}