///////////////////////////////////////////////////////////
//  ListBox Object
///////////////////////////////////////////////////////////
var g_oCurrentTable;
function ListBox(oTable, oSelected, bMultiSelect)
{
	//  Properties
	if (oSelected.toString() === oSelected)
	{
		oTable.SelectedControl = document.getElementsByName(oSelected);
		oTable.SelectedControl = oTable.SelectedControl[0];
	}
	else
	{
		oTable.SelectedControl = oSelected;
	}
	oTable.MultiSelect = bMultiSelect;
	oTable.HeaderRowCt = 0;
	oTable.Buttons = new Array();
	//  Create PopupMenu Object
	oTable.PopupObject = new PopupMenu(oTable.id + "_pop");
	//  Create Methods
	oTable.Init = h_ListBox_Init;
	oTable.addButton = h_ListBox_AddButton;
	oTable.Popup = h_ListBox_CallPopup;
	oTable.refreshButtons = h_ListBox_RefreshButtons;
	//  Attach Events
	registerEvent(this, "oncontextmenu", oTable.Popup);
	//  Initialize and Return
	oTable.Init();
	return oTable;
}
///////////////////////////////////////////////////////////
function h_ListBox_Init()
{
	var x;
	var y;
	for (x = 0; x < this.rows.length; x++)
	{
		// loop through each row to determine if it is a HeaderRow
		if (this.rows[x].className == "listbox_header")
		{
			// increment HeaderRowCt
			this.HeaderRowCt++;
		}
		else
		{
			// capture the row's onClick event
			registerEvent(this.rows[x], "onclick", e_ListBox_RowClick);
			// capture each cell's onSelectStart event (this prevents the innerText from being selected)
			for (y = 0; y < this.rows[x].cells.length; y++)
  			registerEvent(this.rows[x].cells[y], "onselectstart", function(e){return false;});
		}
	}
	if (navigator.OS != "mac")
		// add a style to every cell so text will not expand the column
		for (x = 0; x < this.rows.length; x++)
		{
			for (y = 0; y < this.rows[x].cells.length; y++)
				if (this.rows[x].cells[y].parentNode.className != "listbox_header")
					this.rows[x].cells[y].innerHTML = "<span style='height:13px;overflow:hidden;'>" + this.rows[x].cells[y].innerHTML + "</span>";
		}
	if (this.rows.length > this.HeaderRowCt)
	{
		if (this.MultiSelect == true)
		{
			// setup the PopupObject
			this.po_SelectAll = e_ListBox_SelectAll;
			this.po_Reverse = e_ListBox_Reverse;
			this.po_SelectNone = e_ListBox_SelectNone;
			this.PopupObject.addItem("Select All", this.po_SelectAll);
			this.PopupObject.addItem("Reverse", this.po_Reverse);
			this.PopupObject.addItem("Select None", this.po_SelectNone);
			// determine if the server supplied SelectedControl.value
			if (this.SelectedControl.value == "" || this.SelectedControl.value.length != (this.rows.length - this.HeaderRowCt))
			{
				// build SelectedControl.value
				this.SelectedControl.value = "";
				for (x = this.HeaderRowCt; x < this.rows.length; x++)
					this.SelectedControl.value += "0";
				// click the first row
				this.rows[this.HeaderRowCt].click();
			}
			else
			  // simulate clicking of the supplied rows
				for (x = 0; x < this.SelectedControl.value.length; x++)
					if (this.SelectedControl.value.charAt(x) == "1")
						this.rows[x + this.HeaderRowCt].className = "listbox_selectedrow";
		}
		else // this ListBox is single-select
		{
			this.LastClickedRowIndex = this.HeaderRowCt;
			// determine if the server supplied SelectedControl.value
			if (this.SelectedControl.value == "" || this.SelectedControl.value >= (this.rows.length - this.HeaderRowCt))
			  // click the first row
				this.rows[this.HeaderRowCt].click();
			else
			  // click the supplied row
				this.rows[Math.abs(this.SelectedControl.value) + this.HeaderRowCt].click();
		}
	}
	else
		// blank SelectedControl
		this.SelectedControl.value = "";
}
///////////////////////////////////////////////////////////
function h_ListBox_AddButton(oCtrl, oCondition)
{
	this.Buttons[this.Buttons.length] = new _ListBoxButton(this, oCtrl, oCondition);
	return this.Buttons[this.Buttons.length - 1];
}
///////////////////////////////////////////////////////////
function h_ListBox_CallPopup(e)
{
	if (!e) e = window.event;
	if (!e.srcElement) e.srcElement = e.target;
	var oTable = h_GetCurrentTable(e.srcElement);
	g_oCurrentTable = oTable;
	oTable.PopupObject.draw(e);
	return false;
}
///////////////////////////////////////////////////////////
function e_ListBox_RowClick(e)
{
	if (!e)	e = window.event;
	if (!e.srcElement) e.srcElement = e.target;
	var oRow = h_GetCurrentRow(e.srcElement);
	var oTable = h_GetCurrentTable(oRow);
	if (oTable.disabled == true)
		return true;
	if (oTable.MultiSelect == true)
	{
		var x;
		if (document.ShiftDown == true)
		{
			if (oRow.rowIndex > oTable.LastClickedRowIndex)
			{
				for (x = oTable.HeaderRowCt; x < oTable.LastClickedRowIndex; x++)
				{
					oTable.rows[x].className = "listbox";
					oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(x - oTable.HeaderRowCt, "0");
				}
				for (x = oTable.LastClickedRowIndex; x <= oRow.rowIndex; x++)
				{
					oTable.rows[x].className = "listbox_selectedrow";
					oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(x - oTable.HeaderRowCt, "1");
				}
			}
			else
			{
				for (x = oRow.rowIndex; x < oTable.LastClickedRowIndex; x++)
				{
					oTable.rows[x].className = "listbox_selectedrow";
					oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(x - oTable.HeaderRowCt, "1");
				}
				for (x = oTable.rows.length - 1; x > oTable.LastClickedRowIndex; x--)
				{
					oTable.rows[x].className = "listbox";
					oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(x - oTable.HeaderRowCt, "0");
				}
			}
		}
		else if (document.CtrlDown == true)
		{
			if (oRow.className == "listbox_selectedrow")
			{
				oRow.className = "listbox"
				oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(oRow.rowIndex - oTable.HeaderRowCt, "0");
			}
			else
			{
				oRow.className = "listbox_selectedrow"
				oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(oRow.rowIndex - oTable.HeaderRowCt, "1");
			}
			oTable.LastClickedRowIndex = oRow.rowIndex;
		}
		else
		{
			for (x = oTable.HeaderRowCt; x < oTable.rows.length; x++)
			{
				oTable.rows[x].className = "listbox";
				oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(x - oTable.HeaderRowCt, "0");
			}
			oRow.className = "listbox_selectedrow";
			oTable.SelectedControl.value = oTable.SelectedControl.value.replaceAt(oRow.rowIndex - oTable.HeaderRowCt, "1");
			oTable.LastClickedRowIndex = oRow.rowIndex;
		}
	}
	else //oTable.MultiSelect == false
	{
		oTable.rows[oTable.LastClickedRowIndex].className = "listbox";
		oRow.className = "listbox_selectedrow";
		oTable.SelectedControl.value = oRow.rowIndex - oTable.HeaderRowCt;
		oTable.LastClickedRowIndex = oRow.rowIndex;
	}
	oTable.refreshButtons();
}
///////////////////////////////////////////////////////////
function h_GetCurrentTable(pElement)
{
	var oTable = pElement;
	for (;;)
	{
		if (oTable.tagName == "TABLE" || oTable.tagName == "HTML")
			break;
		oTable = oTable.parentNode;
	}
	return oTable;
}
///////////////////////////////////////////////////////////
function h_GetCurrentRow(pElement)
{
	var oRow = pElement;
	for (; ; )
	{
		if (oRow.tagName == "TR" || oRow.tagName == "HTML")
			break;
		oRow = oRow.parentNode;
	}
	return oRow;
}
///////////////////////////////////////////////////////////
function e_ListBox_SelectAll(e)
{
	var x;
	for (x = g_oCurrentTable.HeaderRowCt; x < g_oCurrentTable.rows.length; x++)
	{
		g_oCurrentTable.rows[x].className = "listbox_selectedrow";
		g_oCurrentTable.SelectedControl.value = g_oCurrentTable.SelectedControl.value.replaceAt(x - g_oCurrentTable.HeaderRowCt, "1");
	}
}
///////////////////////////////////////////////////////////
function e_ListBox_Reverse(e)
{
	var x;
	for (x = g_oCurrentTable.HeaderRowCt; x < g_oCurrentTable.rows.length; x++)
	{
		if (g_oCurrentTable.rows[x].className == "listbox_selectedrow")
		{
			g_oCurrentTable.rows[x].className = "listbox";
			g_oCurrentTable.SelectedControl.value = g_oCurrentTable.SelectedControl.value.replaceAt(x - g_oCurrentTable.HeaderRowCt, "0");
		}
		else
		{
			g_oCurrentTable.rows[x].className = "listbox_selectedrow";
			g_oCurrentTable.SelectedControl.value = g_oCurrentTable.SelectedControl.value.replaceAt(x - g_oCurrentTable.HeaderRowCt, "1");
		}
	}
}
///////////////////////////////////////////////////////////
function e_ListBox_SelectNone(e)
{
	var x;
	for (x = g_oCurrentTable.HeaderRowCt; x < g_oCurrentTable.rows.length; x++)
	{
		g_oCurrentTable.rows[x].className = "listbox";
		g_oCurrentTable.SelectedControl.value = g_oCurrentTable.SelectedControl.value.replaceAt(x - g_oCurrentTable.HeaderRowCt, "0");
	}
}
///////////////////////////////////////////////////////////
function h_ListBox_RefreshButtons()
{
	for (var x = 0; x < this.Buttons.length; x++)
		this.Buttons[x].refresh();
}
///////////////////////////////////////////////////////////
//  _ListBoxButton Object - should only be used within this file
///////////////////////////////////////////////////////////
function _ListBoxButton(oParent, oCtrl, oDisabled)
{
	// oParent should be a ListBox object
	// oCtrl can either be a string indicating the ID of an element
	//   or it can be the element itself
	// oDisabled can either be a string indicating a builtin condition,
	//   a string that will be eval'ed at runtime,
	//   an actual condition (or function) that returns a boolean,
	//   or it can be omitted
	this.parent = oParent;
	if (oCtrl.toString() === oCtrl) // oCtrl is a string
		this.ctrl = document.getElementById(oCtrl);
	else // oCtrl is an object
		this.ctrl = oCtrl;
	this.refresh = h_ListBoxButton_Refresh;
	if (this.ctrl.tagName == "A") // this.ctrl is a LinkButton
		this.href_orig = this.ctrl.href;
	this.Conditions = new Array();
	this.addCondition = h_ListBoxButton_AddCondition;
	if (oDisabled != null)
		this.addCondition(oDisabled);
	return this;
}
///////////////////////////////////////////////////////////
function h_ListBoxButton_Refresh()
{
	var bRet = false;
	for (var x = 0; x < this.Conditions.length; x++)
	{
		if (typeof this.Conditions[x].func == "function")
			bRet = this.Conditions[x].func();
		else
			bRet = this.Conditions[x].func;
		if (bRet == true)
			break;
	}
	if (bRet == true)
	{
		this.ctrl.disabled = "disabled";
		if (this.ctrl.tagName == "A") // this.ctrl is a LinkButton
			this.ctrl.href = "#";
	}
	else
	{
		this.ctrl.disabled = "";
		if (this.ctrl.tagName == "A") // this.ctrl is a LinkButton
			this.ctrl.href = this.href_orig;
	}
}
///////////////////////////////////////////////////////////
function h_ListBoxButton_AddCondition(oDisabled)
{
	var oCondition = new _ListBoxButtonCondition(this);
	if (oDisabled.toString() === oDisabled) // oDisabled is a string
		switch (oDisabled)
		{
			case "NoneSelected":
			{
				oCondition.func = h_ListBoxButtonCondition_NoneSelected;
				break;
			}
			case "MoreThanOneSelected":
				oCondition.func = h_ListBoxButtonCondition_MoreThanOneSelected;
				break;
			default:
				oCondition.func = h_ListBoxButtonCondition_Custom;
				oCondition.strEval = oDisabled;
		}
	else // oDisabled is an object
		oCondition.func = oDisabled;
	this.Conditions[this.Conditions.length] = oCondition;
  this.refresh();
	return this.Conditions[this.Conditions.length - 1];
}
///////////////////////////////////////////////////////////
//  _ListBoxButtonCondition Object - should only be used within this file
///////////////////////////////////////////////////////////
function _ListBoxButtonCondition(oParent, oFunc, strEval)
{
	this.parent = oParent; // this should be a ListBoxButton object
	this.listbox = oParent.parent; // this should be a ListBox object
	// oFunc and strEval will probably be set to null - but I'll setup them up anyway
	this.func = oFunc;
	this.strEval = strEval;
	return this;
}
///////////////////////////////////////////////////////////
function h_ListBoxButtonCondition_NoneSelected()
{
	var bRet = false;
	if (this.listbox.MultiSelect == true)
	{
		if (this.listbox.SelectedControl.value.indexOf("1") == -1)
			bRet = true;
	}
	else
	{
		if (this.listbox.SelectedControl.value == "")
			bRet = true;
	}
	return bRet;
}
///////////////////////////////////////////////////////////
function h_ListBoxButtonCondition_MoreThanOneSelected()
{
	var bRet = false;
	if (this.listbox.MultiSelect == true)
	{
		var n = this.listbox.SelectedControl.value.indexOf("1");
		if (n != -1 && this.listbox.SelectedControl.value.indexOf("1", n + 1) != -1)
			bRet = true;
	}
	return bRet;
}
///////////////////////////////////////////////////////////
function h_ListBoxButtonCondition_Custom()
{
	return eval(this.strEval);
}