//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Layout Functionality

function PopHelp(Help_ID)
{
	//TODO: Popup Help Window
	alert("Popup Help_ID " + Help_ID);
}

function TopHelpHide()
{
	//TODO: Ajax call to server to specify that this help ID should be hidden from now on
	document.getElementById('Layout_HelpBar').style.display = 'none';
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Miscellenaous Functions

//A simple redirect
function GoURL(URL)
{
	window.location = URL;
}

function PopClean(URL, x, y)
{
	return window.open(URL, 'CleanWindow', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=' + x + ',height=' + y + '');
}

//Print out an object to an alert window
function ZInspect(o)
{
	var str = "The Object:\n\n" + o + "\n\n";

	for(s in o)
		str += s + " = " + o[s] + " ::: ";
	alert(str);
}

function Trim(str)
{
	if (typeof str != 'string')
		str = "" + str;
	return str.replace(/^\s*|\s*$/g,"");
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Validation Functions

//Signed Currency
function IsSignedCurrency(sNumber)
{
	return sNumber.match(/^ *\-?\d+(\.\d{0,2})? *$/) != null;
}
function IsSignedCurrency_Error(sNumber)
{
	alert("The input '" + sNumber + " is not valid.\n\nPlease enter your input in the '9.99' or '-9.99' format.");
}


//Unsigned Currency
function IsUnsignedCurrency(sNumber)
{
	return sNumber.match(/^ *\d+(\.\d{0,2})? *$/) != null;
}
function IsUnsignedCurrency_Error(sNumber)
{
	alert("The input '" + sNumber + " is not valid.\n\nPlease enter your input in the '9.99' format.");
}


//Signed Numeric
function IsSignedNumeric(sNumber)
{
	return sNumber.match(/^ *\-?\d+(\.\d*)? *$/) != null;
}
//Error function for IsSignedNumeric
function IsSignedNumeric_Error(sNumber)
{
	alert("The input '" + sNumber + " is not valid.\n\nPlease enter your input in the '99.99' or '-99.99' format.");
}


//Unsigned Numeric
function IsUnsignedNumeric(sNumber)
{
	return sNumber.match(/^ *\d+(\.\d*)? *$/) != null;
}
//Error function for IsUnsignedNumeric
function IsUnsignedNumeric_Error(sNumber)
{
	alert("The input '" + sNumber + " is not valid.\n\nPlease enter your input in the '99.99' format.");
}


//Signed Integer
function IsSignedInteger(sNumber)
{
	return sNumber.match(/^ *\-?\d+ *$/) != null;
}
function IsSignedInteger_Error(sNumber)
{
	alert("The input '" + sNumber + " is not valid.\n\nPlease enter your input in the '99' or '-99' format.");
}


//Unsigned Integer
function IsUnsignedInteger(sNumber)
{
	return sNumber.match(/^ *\d+ *$/) != null;
}
function IsUnsignedInteger_Error(sNumber)
{
	alert("The input '" + sNumber + " is not valid.\n\nPlease enter your input in the '99' format.");
}

//Required
function IsRequired(sValue)
{
	return Trim(sValue) != '';
}
function IsRequired_Error(sInputName)
{
	alert(sInputName + " is required.");
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Formatting Functions

// Format currency number
// Take a float in and return a string
function CurrencyFormat(nNumber)
{
	var s = (Math.round(nNumber * 100) / 100).toString();
	var i = s.indexOf('.');
	return (i == -1 ? s + ".00" : (s + "00").substr(0, i+3));
}
function CurrencyFormat_Test()
{
	var aNum = [0,1,.1,.7,.99,.999,.01, .001, 22.39, 34.03, 3483.99, 343.998]
	//aNum = [2332434.3932]
	var n;
	var s = "Test Results for CurrencyFormat()\n\n";

	for(i=0; i<aNum.length; i++)
	{
		n = aNum[i];
		s += n + " = " + CurrencyFormat(n) + "\n";
		n = -n;
		s += n + " = " + CurrencyFormat(n) + "\n";
	}
	alert(s);
}
//CurrencyFormat_Test();

// Format numeric number e.g. for quantity display.
function NumericFormat(nNumber)
{
	var s = (Math.round(nNumber * 100) / 100).toString();
	var i = s.indexOf('.');
	return (i == -1 ? s + ".00" : (s + "00").substr(0, i+3));
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Serialization

//This function in called internally from SerializeToURL.  It is recursive, and generates a query string variable
//suitable for passing directly to PHP in a URL, or directly to PHP using POST/GET (as the value of a variable), later 
//to be decoded with the PHP function `parse_str()`
//TODO: Gracefully handle cyclic references
function _SerializeToURL(o,name, arrayname)
{
	var s = '';
	switch(typeof(o))
	{
		case 'string':
		case 'number':
			if(arrayname)
			{
				s += encodeURIComponent(arrayname + '[' + name + "]") + "=" + encodeURIComponent(o) + "&";
			}
			else
			{
				s += encodeURIComponent(name) + "=" + encodeURIComponent(o) + "&";
			}
			break;
		case 'boolean':
			if(arrayname)
			{
				s += encodeURIComponent(arrayname + '[' + name + "]") + "=" + (o ? 1 : 0) + "&";
			}
			else
			{
				s += encodeURIComponent(name) + "=" + (o ? 1 : 0) + "&";
			}
			break;
		case 'array':
			for(i = 0; i < o.length; i++)
			{
				s += _SerializeToURL(o[i], i, arrayname ? arrayname + '[' + name + ']' : name);
			}
			break;
		case 'object':
			for(i in o)
			{
				s += _SerializeToURL(o[i], i, arrayname ? arrayname + '[' + name + ']' : name);
			}
			break;
		case 'function':
			//Do nothing
			break;
		default:
			throw ("Attemt to serialize an unknown type of " + typeof(o) + ", name='" + name + "', value='" + o + "'");
	}
	return s;
}

//Call this with an array or object (can be nested, probabally DOES NOT HANDLE CYCLIC REFERENCES)
function SerializeToURL(o)
{
	var s = _SerializeToURL(o, null, null);
	return s.substr(0, s.length - 1);
}	
function SerializeToURL_Test()
{
	prompt("Complex", SerializeToURL({a:'b',c:'d',e:{f:'g',h:'i',j:{k:'l',m:'n'},o:['p', 'q', 'r']},s:['t','u',true,false],v:true,w:false,x:"foo ba'/.z"}));
	prompt("Simple String", SerializeToURL({name:"Jerry went to town"}));

}
//SerializeToURL_Test();

// Prototype dependencies
if (typeof Prototype != 'undefined') {
	/* ******************************************************************************************* */
	/* Class which handles table row highlighting */
	var TableHighlight = Class.create();
	TableHighlight.prototype = {
		tableID: null,
		tableElement: null,
		mouseoverClass: null,
		mouseoutClass: null,
		initialize: function(tableID, mouseoverClass, mouseoutClass) 
		{
			this.tableElement = $(tableID);
			this.mouseoverClass = mouseoverClass;
			this.mouseoutClass = mouseoutClass;

			// Register table events
			Event.observe(this.tableElement, 'mouseover', this.onMouseOver.bind(this));
			Event.observe(this.tableElement, 'mouseout', this.onMouseOut.bind(this));
		},

		onMouseOver: function(e)
		{
			// Traverses the DOM tree upwards, searching for the first TR element
			var trElement = Event.findElement(e, 'TR');
			// change the TR clas sname
			trElement.className = this.mouseoverClass;
		},

		onMouseOut: function(e)
		{
			// Traverses the DOM tree upwards, searching for the first TR element
			var trElement = Event.findElement(e, 'TR');
			// change the TR clas sname
			trElement.className = this.mouseoutClass;
		}
	}

	/* ******************************************************************************************* */
	/* Class which keeps elemnt always in view */
	var ViewKeeper = Class.create();
	ViewKeeper.prototype = {
		elementID: null,
		domElement: null,
		controlElementID: null,
		/* 
		* elementID - elemt to keep in a view
		* controlElementID - elements which should be located NOT in a view in order to position elementID
		*/ 
		initialize: function(elementID, controlElementID) 
		{
			this.elementID = elementID;
			this.domElement = $(elementID);
			this.controlElementID = controlElementID;

			// Register el events
			Event.observe(window, 'resize', this.onResize.bind(this));
			Event.observe(window, 'scroll', this.onScroll.bind(this));
		},

		onResize: function(e)
		{
			this.postion();
		},

		onScroll: function(e)
		{
			this.postion();
		},
		// process elements position
		postion: function()
		{
			// get the X/Y coordinates of a control element relative to the viewport.
			var XY = Position.page($(this.controlElementID));

			if (navigator.appVersion.match(/\bMSIE\b/))
			{

				Element.makePositioned(this.elementID); // IE fix
				this.domElement.style.position="absolute";
				if (XY[1] <= 0)
				{
					this.domElement.style.top=document.body.scrollTop;
				}
				else
				{
					this.domElement.style.top=96;
				}
			}
			else
			{
				/* FireFox Only  */
				if (XY[1] <= 0)
				{
					this.domElement.style.position="fixed";
					this.domElement.style.top=0;
				}
				else
				{
					this.domElement.style.position="relative";
				}
			}
		}
	}

	/* ******************************************************************************************* */
	/* Class which calculates number of characters left for input */
	var LengthChecker = Class.create();
	LengthChecker.prototype = {
		textElement: null,
		statusElement: null,
		len: null,
		infoMessage: '{value} characters left.',
		errorMessage: 'Text length can\'t be no more than {value} characters.<br>Please remove {diff} characters.',
		valueRegExp: /{value}/i,
		diffRegExp: /{diff}/i,

		initialize: function(textElementID, statusElementID, len) 
		{
			this.textElement = $(textElementID);
			this.statusElement = $(statusElementID);
			this.len = $(len);

			// Register events to check text length
			Event.observe(this.textElement, 'change', this.checkLen.bind(this));
			Event.observe(this.textElement, 'keyup', this.checkLen.bind(this));
		},

		checkLen: function(e)
		{
			var currLen = this.textElement.value.length;
			if (currLen > this.len) {
				// show error message
				var str = this.errorMessage.replace(this.valueRegExp, this.len);
				str = str.replace(this.diffRegExp, (currLen - this.len));
				this.statusElement.innerHTML = str;
			}
			else {
				// show information message
				this.statusElement.innerHTML = this.infoMessage.replace(this.valueRegExp, (this.len - currLen));
			}
		}

	}
}
	/* ***************************************************************************************************** */


var onPageExit = false;
function GoPageIf(sURL)
{
	if((! onPageExit) || onPageExit())
		window.location = sURL;
}
