// SpryDynamicTable.js - version 0.1 - Spry Pre-Release 1.6
//
// Copyright (c) 2007. Adobe Systems Incorporated.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of Adobe Systems Incorporated nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

if (!Spry) Spry = {}; if (!Spry.Widget) Spry.Widget = {};

Spry.Widget.DynamicTable = function(ele, opts)
{
	this.element = Spry.$(ele);
	this.columnTypes = {};
	this.sortOrder = "";
	this.columnNameMap = {};
	this.cache = {};
	this.ascendingSortClass = "ascending";
	this.descendingSortClass = "descending";
	this.hoverClass = "hover";
	this.selectedClass = "selected";

	this.addBehaviors();
};

Spry.Widget.DynamicTable.prototype.addBehaviors = function()
{
	var dt = this;
	Spry.$$("th.sortable", this.element).addEventListener("click", function(e)
	{
		dt.sort(this, "toggle");
	}, false).forEach(function(n)
	{
		var txt = n.innerHTML;
		if (txt)
		{
			txt = txt.replace(/^\s+|<\/?([^>]|\s)+>|\s+$/g, "").replace(/\s+/g, " ").replace(/\s/g, "_");
			dt.columnNameMap[txt] = n;
			n.spryColumnName = txt;
		}
	});

	//Spry.$$("#atoms tr:nth-child(n+2)").setStyle("background-color: yellow");
};

Spry.Widget.DynamicTable.prototype.getTHForColumnName = function(columnName)
{
	if (typeof columnName == "object")
		return columnName;
	return this.columnNameMap[columnName];
};

Spry.Widget.DynamicTable.prototype.extractColumnData = function(columnName)
{
	var data = this.cache[columnName];
	if (data)
		return data;

	var th = this.getTHForColumnName(columnName);
	if (!th) return null;

	data = new Array;

	var thNodes = Spry.$$("th");
	var pos = 1;
	for (var i = 0; i < thNodes.length; i++)
	{
		if (thNodes[i] == th)
			break;
	}

	var tds = Spry.$$("td:nth-child(" + (i+1) + ")", this.element).forEach(function(n)
	{
		var o = new Object;
		o.element = n;
		var v = n.innerHTML;
		if (v)
			v = v.replace(/^\s+|<\/?([^>]|\s)+>|\s+$/g, "");
		else
			v = "";
		o.value = v;
		data.push(o);
	});

	this.cache[columnName] = data;

	return data;
};

Spry.Widget.DynamicTable.prototype.sort = function(columnName, order)
{
	var th = this.getTHForColumnName(columnName);
	if (!th)
		return this.sortOrder;

	columnName = th.spryColumnName;

	Spry.$$("th.sortable", th.parentNode).removeClassName(this.ascendingSortClass).removeClassName(this.descendingSortClass);

	if (order == "toggle")
	{
		order = this.ascendingSortClass;
		if (this.sortOrder)
			order = (this.sortOrder == this.ascendingSortClass) ? this.descendingSortClass : this.ascendingSortClass;
	}

	var data = this.extractColumnData(columnName);
	if (data && data.length > 1)
	{
		data.sort(this.sort.getSortFunc("value", this.getColumnType(columnName), order));

		var rowParent = data[0].element.parentNode.parentNode;
		for (var i = 0; i < data.length; i++)
			rowParent.insertBefore(data[i].element.parentNode, null);
	}
	this.sortOrder = order;
	Spry.Utils.addClassName(th, this.sortOrder);

	return this.sortOrder;
};

Spry.Widget.DynamicTable.prototype.sort.getSortFunc = function(prop, type, order)
{
	var sortfunc = null;
	if (type == "number")
	{
		if (order == "ascending")
			sortfunc = function(a, b)
			{
				a = a[prop]; b = b[prop];
				if (a == undefined || b == undefined)
					return (a == b) ? 0 : (a ? 1 : -1);
				return a-b;
			};
		else // order == "descending"
			sortfunc = function(a, b)
			{
				a = a[prop]; b = b[prop];
				if (a == undefined || b == undefined)
					return (a == b) ? 0 : (a ? -1 : 1);
				return b-a;
			};
	}
	else if (type == "date")
	{
		if (order == "ascending")
			sortfunc = function(a, b)
			{
				var dA = a[prop];
				var dB = b[prop];
				dA = dA ? (new Date(dA)) : 0;
				dB = dB ? (new Date(dB)) : 0;
				return dA - dB;
			};
		else // order == "descending"
			sortfunc = function(a, b)
			{
				var dA = a[prop];
				var dB = b[prop];
				dA = dA ? (new Date(dA)) : 0;
				dB = dB ? (new Date(dB)) : 0;
				return dB - dA;
			};
	}
	else // type == "string" || type == "html"
	{
		if (order == "ascending")
			sortfunc = function(a, b){
				a = a[prop];
				b = b[prop];
				if (a == undefined || b == undefined)
					return (a == b) ? 0 : (a ? 1 : -1);
				var tA = a.toString();
				var tB = b.toString();
				var tA_l = tA.toLowerCase();
				var tB_l = tB.toLowerCase();
				var min_len = tA.length > tB.length ? tB.length : tA.length;

				for (var i=0; i < min_len; i++)
				{
					var a_l_c = tA_l.charAt(i);
					var b_l_c = tB_l.charAt(i);
					var a_c = tA.charAt(i);
					var b_c = tB.charAt(i);
					if (a_l_c > b_l_c)
						return 1;
					else if (a_l_c < b_l_c)
						return -1;
					else if (a_c > b_c)
						return 1;
					else if (a_c < b_c)
						return -1;
				}
				if(tA.length == tB.length)
					return 0;
				else if (tA.length > tB.length)
					return 1;
				return -1;
			};
		else // order == "descending"
			sortfunc = function(a, b){
				a = a[prop];
				b = b[prop];
				if (a == undefined || b == undefined)
					return (a == b) ? 0 : (a ? -1 : 1);
				var tA = a.toString();
				var tB = b.toString();
				var tA_l = tA.toLowerCase();
				var tB_l = tB.toLowerCase();
				var min_len = tA.length > tB.length ? tB.length : tA.length;
				for (var i=0; i < min_len; i++)
				{
					var a_l_c = tA_l.charAt(i);
					var b_l_c = tB_l.charAt(i);
					var a_c = tA.charAt(i);
					var b_c = tB.charAt(i);
					if (a_l_c > b_l_c)
						return -1;
					else if (a_l_c < b_l_c)
						return 1;
					else if (a_c > b_c)
						return -1;
					else if (a_c < b_c)
						return 1;
				}
				if(tA.length == tB.length)
					return 0;
				else if (tA.length > tB.length)
					return -1;
				return 1;
			};
	}

	return sortfunc;
};

Spry.Widget.DynamicTable.prototype.sort.buildSecondarySortFunc = function(funcA, funcB)
{
	return function(a, b)
	{
		var ret = funcA(a, b);
		if (ret == 0)
			ret = funcB(a, b);
		return ret;
	};
};

Spry.Widget.DynamicTable.prototype.setColumnType = function(columnNames, columnType)
{
	if (columnNames)
	{
		if (typeof columnNames == "string")
			columnNames = [ columnNames ];
		for (var i = 0; i < columnNames.length; i++)
			this.columnTypes[columnNames[i]] = columnType;
	}
};

Spry.Widget.DynamicTable.prototype.getColumnType = function(columnName)
{
	if (this.columnTypes[columnName])
		return this.columnTypes[columnName];
	return "string";
};

