/**
 * sortableTable.js
 * requires:
 * 
 * - prototype.js
 * - yui/yahoo.js
 * - yui/dom.js
 * - yui/event.js
 * 
 * @see org.sharpertools.web.controls.SortableTable.java
 */ 
function SortableTable(id, sorts, columnSorts, opts)
{
	this.id = id;
	this.sorts = sorts;
	this.columnSorts = columnSorts;
	
	opts = opts == null ? [] : opts;
	this.initialSort = opts["initialSort"];
	this.asc = this.columnSorts[this.initialSort].match("asc$");
	this.bandingSize = opts["bandingSize"] == null ? 1 : opts["bandingSize"];
	this.bandingClasses = opts["bandingClasses"] == null ? [] : opts["bandingClasses"];
	this.hoverClass = opts["hoverClass"];
	this.ascClass = opts["sortAscClass"];
	this.descClass = opts["sortDescClass"];
	
	this.currentSort = null;
	this.rows = [];
	var me = this;

	YAHOO.util.Event.onAvailable(this.id, this._init, this);
}

SortableTable.prototype._init = function(me)
{	
	me.tbody = $(me.id).getElementsByTagName("tbody")[0];
	
	for (var sortBy in me.sorts)
	{
		YAHOO.util.Event.addListener(sortBy, "click", function(evt) {me.sort(YAHOO.util.Event.getTarget(evt).id); YAHOO.util.Event.stopEvent(evt);});
	}
	
	var mouseOver = function(evt) { Element.toggleClassName(YAHOO.util.Event.getTarget(evt), me.hoverClass); YAHOO.util.Event.stopEvent(evt); };
	
	if (me.tbody != null)
	{
		var trs = me.tbody.getElementsByTagName("tr");
		for (var i=0; i < trs.length; i++)
		{
			me.rows[i] = trs[i];
			if (me.hoverClass != null)
			{
				YAHOO.util.Event.addListener(tr[i], "mouseOver", mouseOver);
			}
		}
		
		if (me.initialSort != null)
		{
			me.sort(me.initialSort, true);
		}
	}
}

SortableTable.prototype.sort = function(sortBy, initial) 
{
	if (this.currentSort != null)
	{
		Element.removeClassName($(this.currentSort).parentNode, this.asc ? this.ascClass : this.descClass);
	}
	
	// if table already sorted by this column and bidirectional sorting isn't supported, don't re-sort
	if (this.currentSort == sortBy && this.columnSorts[sortBy].match("^uni"))
	{
		return;
	}
	
	if (!initial)
	{
		this.asc = (!this.asc && sortBy == this.currentSort) || (sortBy != this.currentSort && this.columnSorts[sortBy].match("asc$"));
	}
	
	var newOrdering = this.asc ? this.sorts[sortBy] : this.sorts[sortBy].reverse(false);
	for (var i=0; i < newOrdering.length; i++)
	{
		var tr = this.rows[newOrdering[i]];
		for (var j=0; j<this.bandingClasses.length; j++)
		{
			Element.removeClassName(tr, this.bandingClasses[j]);
		}
		if (this.bandingClasses.length > 0)
		{
			Element.addClassName(tr, this.bandingClasses[i%(this.bandingClasses.length*this.bandingSize)]);
		}
		this.tbody.appendChild(tr);	
	}
	
	this.currentSort = sortBy;
	Element.addClassName($(this.currentSort).parentNode, this.asc ? this.ascClass : this.descClass);
}