// ** Provides exception style error handling. ** //
function Exception(p_message) { return new Error(p_message); }
function ArgumentNullException(p_argument) { return Exception('Missing or NULL value for the argument: ' + p_argument); }
function InvalidArgumentException(p_argument) { return Exception('Invalid value for the argument: ' + p_argument); }
// ** Common javascript functions library. ** //
function Extend(p_subClass, p_baseClass)
{
	function inheritance() { }
	inheritance.prototype = p_baseClass.prototype;
	p_subClass.prototype = new inheritance();
	p_subClass.prototype.constructor = p_subClass;
	p_subClass.baseConstructor = p_baseClass;
	p_subClass.superClass = p_baseClass.prototype;
	return;
}
function TypeOf(p_object) { if(p_object == undefined || p_object == null) { return typeof(p_object); } try { return p_object.GetType(); } catch(e) { return typeof(p_object).ToProperCase(); } }
// ** Common javascript object library. ** //
Utils = {};
Utils.IsIE = navigator.appName == 'Microsoft Internet Explorer'
Utils.IsNetscape = navigator.appName == 'Netscape';
Utils.RandomNumber = function(p_lowerBound, p_upperBound)
{
    if(TypeOf(p_lowerBound) != 'Number') { p_lowerBound = 0; }
    if(TypeOf(p_upperBound) != 'Number') { p_upperBound = p_lowerBound + 1; }
    p_upperBound = p_upperBound + 1; // +1 so that the upper bound can be included.
    return (Math.floor(Math.random() * (p_upperBound - p_lowerBound)) + p_lowerBound);
}
Utils.RandomPassword = function(p_numberOfCharacters)
{
    var v_retval = '';
    if(TypeOf(p_numberOfCharacters) != 'Number') { p_numberOfCharacters = 8; }
    for(var i = 0; i < p_numberOfCharacters; i++)
    {
        switch(Utils.RandomNumber(1, 3))
        {
            case 1: v_retval += String.fromCharCode(Utils.RandomNumber(48, 57)); break;
            case 2: v_retval += String.fromCharCode(Utils.RandomNumber(65, 90)); break;
            case 3: v_retval += String.fromCharCode(Utils.RandomNumber(97, 122)); break;
        }
    }
    return v_retval;
}
Utils.AddBookmark = function(p_description)
{
    if(TypeOf(p_description) != 'String' || p_description.length <= 0) { p_description = document.title; }
    if(Utils.IsIE) { window.external.AddFavorite(window.location.href, p_description); }
    else if(Utils.IsNetscape) { window.sidebar.addPanel(p_description, window.location.href, ''); }
    else { alert('Please press Ctrl+D to bookmark this page.'); }
    return;
}
Utils.GetElement = function(p_elementId)
{
	if(p_elementId == null || p_elementId.length <= 0) { throw ArgumentNullException('p_elementId'); return null; }
	var v_element = document.getElementById(p_elementId);
	if(v_element == null) { throw Exception('HTML element with ID of \'' + p_elementId + '\' was not found!'); }
	return v_element;
}
Utils.GetOrCreateElement = function(p_elementId, p_elementType, p_hideElement)
{
	var v_element = document.getElementById(p_elementId);
	if(v_element == null)
	{
		v_element = document.createElement(p_elementType);
		v_element.setAttribute('id', p_elementId);
		document.body.appendChild(v_element);
	}
	if(p_hideElement)
	{
		v_element.style.display  = 'none';
		v_element.style.position = 'absolute';
		v_element.style.left     = '0px';
		v_element.style.top      = '0px';
	}
	return v_element;
}
Utils.AddListener = function(p_element, p_event, p_listener, p_bubble)
{
	p_bubble = TypeOf(p_bubble) != 'Boolean' ? false : p_bubble;
	if(Utils.IsIE) { p_element.attachEvent("on" + p_event, p_listener); }
	else { p_element.addEventListener(p_event, p_listener, p_bubble);} 
	return;
}
Utils.OpenPopup = function(p_link, p_handle, p_height, p_width, p_scrollbars, p_resizeable, p_left, p_top, p_dependent)
{
	if(!window.focus) { return; }
	p_link = String(p_link);
	if(!p_link || p_link.IsEmpty()) { throw ArgumentNullException('p_link'); }
	p_handle = String(p_handle);
	if(!p_handle || p_handle.IsEmpty()) { throw ArgumentNullException('p_handle'); }
	p_height = Number(p_height);
	if(isNaN(p_height)) { p_height = 100; }
	p_width = Number(p_width);
	if(isNaN(p_width)) { p_width = 100; }
	if(p_scrollbars !== false) { p_scrollbars = true; }
	if(p_resizeable !== false) { p_resizeable = true; }
	p_left = Number(p_left);
	if(isNaN(p_left)) { p_left = 10; }
	p_top = Number(p_top);
	if(isNaN(p_top)) { p_top = 10; }
	if(p_dependent !== false) { p_dependent = true; }
    var v_attr = 'height=' + String(p_height) + ',width=' + String(p_width) + ',left=' + String(p_left) + ',top=' + String(p_top);
    v_attr += !p_scrollbars ? ',scrollbars=no' : ',scrollbars=yes';
    v_attr += !p_resizeable ? ',resizable=no'  : ',resizable=yes';
    v_attr += !p_dependent  ? ',dependent=no'  : ',dependent=yes';
    var v_winhandle = window.open(p_link, p_handle, v_attr);
    v_winhandle.focus();
    return v_winhandle;
}
Utils.CreateCssPropertyString = function(p_name, p_value) { p_name = String(p_name); p_value = String(p_value); if(p_value != null && p_value.length > 0) { return ' ' + p_name + ': ' + p_value + ';'; } return ''; }
Utils.CreateAttributeString = function(p_name, p_value) { p_name = String(p_name); p_value = String(p_value); if(p_value != null && p_value.length > 0) { return ' ' + p_name + '="' + p_value + '"'; } return ''; }
Utils.GetIntValue = function(p_value) { p_value = parseInt(p_value); return p_value < 0 || isNaN(p_value) ? 0 : p_value; }
Utils.GetScrollBarWidth = function()
{
	var v_wo_scroll = 0, v_w_scroll = 0;
	var v_inner = document.createElement('div');
	v_inner.style.width = '100%';
	v_inner.style.height = '200px';
	v_inner.innerHTML = '&nbsp;';
	var v_scroll = document.createElement('div');
	v_scroll.style.position = 'absolute';
	v_scroll.style.top = '-1000px';
	v_scroll.style.left = '-1000px';
	v_scroll.style.width = '100px';
	v_scroll.style.height = '50px';
	v_scroll.style.overflow = 'hidden';
	v_scroll.appendChild(v_inner);
	document.body.appendChild(v_scroll);
	v_wo_scroll = v_inner.offsetWidth;
	v_scroll.style.overflow = 'auto';
	v_w_scroll = v_inner.offsetWidth;
	document.body.removeChild(document.body.lastChild);
	return v_wo_scroll - v_w_scroll;
}
Utils.GetCssFixedWidth = function(p_widthInPixels)
{
	if(p_widthInPixels < 0) { p_widthInPixels = 0; }
	return 'max-width: ' + p_widthInPixels.ToCssString() + '; width: expression("' + p_widthInPixels.toString() + 'px");';
}
Utils.GetKeyCode = function(p_keyEvent)
{
	if(!p_keyEvent) { var p_keyEvent = window.event; }
	if(p_keyEvent.keyCode) { return p_keyEvent.keyCode; }
	else if(p_keyEvent.which) { return p_keyEvent.which; }
	return -1;
}
Utils.IsNumericKey = function(p_keyCode)
{
	 // 31 or less are system key codes, 48 - 57 are numerical key codes for key pad nubers, 96 - 105 are numerical key codes for num pad numbers.
	return p_keyCode <= 31 || (p_keyCode >= 48 && p_keyCode <= 57) || (p_keyCode >= 96 && p_keyCode <= 105);
}

Xml = {};
Xml.CreateDocument = function(p_rootTagName, p_namespaceUrl)
{ 
	if(!p_rootTagName) { p_rootTagName = ''; }
	if(!p_namespaceUrl) { p_namespaceUrl = ''; }
	if(document.implementation && document.implementation.createDocument) { return document.implementation.createDocument(p_namespaceUrl, p_rootTagName, null); } // This is the W3C standard way to do it
	else
	{ // This is the IE way to do it
		// Create an empty document as an ActiveX object, if there is no root element, this is all we have to do
		var v_doc = new ActiveXObject('MSXML2.DOMDocument');
		// If there is a root tag, initialize the document
		if(p_rootTagName)
		{
			// Look for a namespace prefix
			var v_prefix  = '';
			var v_tagname = p_rootTagName;
			var v_temp    = p_rootTagName.indexOf(':');
			if(v_temp != -1) { v_prefix = p_rootTagName.substring(0, v_temp); v_tagname = p_rootTagName.substring(v_temp + 1); }
			// If we have a namespace, we must have a namespace prefix, if we don't have a namespace, we discard any prefix
			if(p_namespaceUrl) { if(!v_prefix) { v_prefix = 'a0'; } } // What Firefox uses
			else { v_prefix = ''; }
			// Create the root element (with optional namespace) as a string of text
			var v_text = '<' + (v_prefix ? (v_prefix + ':') : '') +  v_tagname + (p_namespaceUrl ? (' xmlns:' + v_prefix + '="' + p_namespaceUrl +'"') : '') + '/>';
			// And parse that text into the empty document
			v_doc.loadXML(text);
		}
		return v_doc;
	}
}
Xml.Load = function(p_url, p_callback)
{
	if(!p_url || p_url.length <= 0) { throw ArgumentNullException('p_url'); return null; }
	var v_doc = Xml.CreateDocument();
	if(!p_callback) { v_doc.async = false; }
	else
	{
		if(document.implementation && document.implementation.createDocument) { v_doc.onload = function() { if(p_callback) { p_callback(v_doc); } } }
		else { v_doc.onreadystatechange = function() { if(p_callback && v_doc.readyState == 4) { p_callback(v_doc); } } }
	}
	v_doc.load(p_url);
	return v_doc;
}
Xml.LoadXml = function(p_xml)
{
	if(!p_xml || p_xml.length <= 0) { throw ArgumentNullException('p_xml'); return null; }
	if(typeof(DOMParser) != 'undefined') { return (new DOMParser()).parseFromString(p_xml, 'application/xml'); } // Mozilla, Firefox, and related browsers
	else if(typeof(ActiveXObject) != 'undefined') { var v_doc = Xml.CreateDocument(); v_doc.loadXML(p_xml); return v_doc; } // Internet Explorer
	else
	{ // As a last resort, try loading the document from a data: URL. This is supposed to work in Safari.
		var v_url = 'data:text/xml;charset=utf-8,' + encodeURIComponent(p_xml);
		var v_request = new XMLHttpRequest();
		v_request.open('GET', v_url, false);
		v_request.send(null);
		return request.responseXML;
	}
}
Xml.SelectSingleNode = function(p_doc, p_xpath, p_ieNameSpaces)
{
	try // IE
	{
		if(TypeOf(p_ieNameSpaces) == 'String' && p_ieNameSpaces.length > 0) { p_doc.setProperty('SelectionNamespaces', p_ieNameSpaces); }
		return p_doc.selectSingleNode(p_xpath);
	}
	catch(e) // Mozilla
	{
		var v_ns_resolver = p_doc.createNSResolver(p_doc.ownerDocument == null ? p_doc.documentElement : p_doc.ownerDocument.documentElement);
		var v_response_node = p_doc.evaluate(p_xpath, p_doc, v_ns_resolver, 9, null);
		return v_response_node.singleNodeValue;
	}
}
Xml.GetNodeValue = function(p_node)
{
	if(p_node != null)
	{
		if(Utils.IsIE) { return p_node.text; }
		var v_retval = '';
		for(var i = 0; i < p_node.childNodes.length; i++) { if(p_node.childNodes[i].nodeType == 3 || p_node.childNodes[i].nodeType == 4) { v_retval += p_node.childNodes[i].nodeValue; } }
		return v_retval;
	}
	return '';
}
Xml.GetAttributeValue = function(p_element, p_attributeName)
{
	if(p_element != null && p_element.nodeType == 1)
	{
		if(p_element.attributes[p_attributeName] != undefined) { return p_element.attributes[p_attributeName] == null ? '' : p_element.attributes[p_attributeName].value; } // Mozilla based browsers.
		else if(p_element.attributes.getNamedItem(p_attributeName) != undefined) { return p_element.attributes.getNamedItem(p_attributeName) == null ? '' : p_element.attributes.getNamedItem(p_attributeName).nodeValue; } // IE
	}
	return '';
}

function Collection() { this.List = new Array(); this.Count = 0; return; }
Collection.prototype.GetType = function() { return 'Collection'; }
Collection.prototype.ToString = function() { return this.List.InternalToString(this.GetType()); }
Collection.prototype.toString = function() { return this.ToString(); }
Collection.prototype.Equals = function(p_object) { return this == p_object; }
Collection.prototype.CompareTo = function(p_object) { return 0; }
Collection.prototype.Item = function(p_index, p_value) { if(p_index < this.Count && p_index >= 0) { if(arguments.length == 1) { return this.List[p_index]; } else { this.List[p_index] = p_value; return; } } throw Exception('The specified index of ' + p_index + ' is not within the bounds of the collection.'); }
Collection.prototype.IndexOf = function(p_value)
{
	for(var i = 0; i < this.Count; i++)
	{
		var v_equals = false;
		try { v_equals = p_value.Equals(this.List[i]); }
		catch (e) { v_equals = this.CompareFunction(p_value, this.List[i]) == 0; }
		if(v_equals) { return i; }
	}
	return -1;
}
Collection.prototype.Contains = function(p_value) { return this.IndexOf(p_value) >= 0; }
Collection.prototype.Add = function(p_value) { if(!this.Contains(p_value)) { this.List.push(p_value); this.Count++; return this.Count - 1; } return -1; }
Collection.prototype.RemoveAt = function(p_index) { this.List.RemoveAt(p_index); this.Count = this.List.length; return; }
Collection.prototype.Remove = function(p_value) { this.RemoveAt(this.IndexOf(p_value)); return; }
Collection.prototype.Clear = function() { this.List.Clear(); this.Count = 0; return; }
Collection.prototype.Sort = function() { this.List.sort(this.CompareFunction); return; }
Collection.prototype.CompareFunction = function(p_left, p_right) { return p_left === p_right ? 0 : (p_left < p_right ? -1 : 1); }

function DateCollection() { DateCollection.baseConstructor.call(this); return; }
Extend(DateCollection, Collection);
DateCollection.prototype.GetType = function() { return 'DateCollection'; }
DateCollection.prototype.CompareFunction = function(p_left, p_right) { return p_left.CompareTo(p_right); }

function StringBuilder(p_initialText) { this._Strings = Utils.IsIE == true ? new Array('') : ''; this.Append(p_initialText); return; }
StringBuilder.prototype.Append = function(p_text) { if(p_text != undefined && p_text != null) { if(Utils.IsIE == true) { this._Strings.push(p_text.toString()); } else { this._Strings += p_text.toString(); } } return this; }
StringBuilder.prototype.Clear = function() { if(Utils.IsIE == true) { this._Strings.length = 1; } else { this._Strings = ''; } return; }
StringBuilder.prototype.ToString = function() { return Utils.IsIE == true ? this._Strings.join('') : this._Strings; }
StringBuilder.prototype.toString = function() { return this.ToString(); }
StringBuilder.prototype.GetType = function() { return 'StringBuilder'; }
StringBuilder.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'StringBuilder' && this._Strings.Equals(p_object); }
StringBuilder.prototype.CompareTo = function(p_object) { return this._Strings.CompareTo(p_object); }

function HashArray() { this.List = new Object(); this.Count = 0; return; }
HashArray.prototype.toString = function() { return this.ToString(); }
HashArray.prototype.GetType = function() { return 'HashArray'; }
HashArray.prototype.Item = function(p_key, p_value)
{
	if(TypeOf(p_key) != 'Number')
	{
		if(p_key == null) { throw ArgumentNullException('p_key'); return null; }
		var v_index = this.IndexOfKey(p_key);
		if(v_index >= 0)
		{
			if(p_value != undefined)
			{
				this.List[p_key] = p_value;
				return this.List[p_key];
			}
			return this.List[p_key];
		}
		throw Exception('Key does not exist (' + p_key + ').');
	}
	else
	{
		if(p_key < 0) { throw Exception('Index out of range (' + p_key + ').'); return null; }
		var v_count  = 0;
		for(var v_key in this.List)
		{
			if(v_count == p_key)
			{
				if(p_value != undefined)
				{
					this.List[v_key] = p_value;
					return this.List[v_key];
				}
				return this.List[v_key];
			}
			v_count++;
		}
		throw Exception('Index out of range (' + p_key + ').');
	}
	return null;
}
HashArray.prototype.KeyAt = function(p_index)
{
	if(p_index < 0) { throw Exception('Index out of range (' + p_index + ').'); return null; }
	var v_count = 0;
	for(var v_key in this.List) { if(v_count == p_index && this.List[v_key] != undefined) { return v_key; } v_count++; }
	throw Exception('Index out of range (' + p_index + ').');
	return null;
}
HashArray.prototype.Keys = function() { var v_keys = new Array(); for(var v_key in this.List) { if(this.List[v_key] != undefined) { v_keys.push(v_key); } } return v_keys; }
HashArray.prototype.Values = function() { var v_values = new Array(); for(var v_key in this.List) { if(this.List[v_key] != undefined) { v_values.push(this.List[v_key]); } } return v_values; }
HashArray.prototype.Add = function(p_key, p_value) { if(p_key == null) { throw ArgumentNullException('p_key'); return -1; } this.List[p_key] = p_value; this.Count++; return; }
HashArray.prototype.Remove = function(p_key) { if(p_key == null) { throw ArgumentNullException('p_key'); return; } this.List[p_key] = undefined; this.Count--; if(this.Count < 0) { this.Count = 0; } return; }
HashArray.prototype.RemoveAt = function(p_index) { this.Item(p_index, undefined); this.Count--; if(this.Count < 0) { this.Count = 0; } return; }
HashArray.prototype.Clear = function() { for(var v_key in this.List) { this.List[v_key] = undefined; } this.Count = 0; return; }
HashArray.prototype.Contains = function(p_key) { return this.IndexOfKey(p_key) > -1; }
HashArray.prototype.ContainsValue = function(p_value) { return this.IndexOfValue(p_value) > -1; }
HashArray.prototype.IndexOfKey = function(p_key)
{
	if(p_key == null) { throw ArgumentNullException('p_key'); return -1; }
	var v_index = 0;
    for(var v_key in this.List) { if(this.List[v_key] != undefined) { if(v_key == p_key) { return v_index; } v_index++; } }
    return -1;
}
HashArray.prototype.IndexOfValue = function(p_value)
{
    if(p_value == null) { throw ArgumentNullException('p_value'); return -1; }
    var v_index = 0;
    for(var v_key in this.List) { if(this.List[v_key] != undefined) { if(this.List[v_key] == p_value) { return v_index; } v_index++; } }
    return -1;
}
HashArray.prototype.ToString = function()
{
	var v_count = 0;
	var v_sb = (new StringBuilder('HashArray [')).Append(this.Count).Append(' items]\n(\n');
	for(var v_key in this.List)
	{
		if(this.List[v_key] != undefined && typeof(this.List[v_key]) != 'function')
		{
			if(v_count != 0) { v_sb.Append(',\n'); }
			v_sb.Append('\t[').Append(v_count).Append('] ').Append(v_key).Append(' => ').Append(this.List[v_key]);
			v_count++;
		}
	}
	v_sb.Append('\n)\n')
	return v_sb.ToString();
}

function QueryString() { QueryString.baseConstructor.call(this); return; }
Extend(QueryString, HashArray);
QueryString.prototype.GetType = function() { return 'QueryString'; }
QueryString.prototype.ToString = function()
{
	var v_retval = '';
	for(var v_key in this.List)
	{
		var v_item = this.List[v_key];
		var v_type = typeof(v_item);
		if(v_type != 'function' && v_type != 'undefined') { v_retval += encodeURIComponent(v_key) + '=' + encodeURIComponent(v_item) + '&'; }
	}
	return v_retval.substring(0, v_retval.length - 1);
}
QueryString.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'QueryString' && (this.ToString() == p_object.ToString()); }
QueryString.prototype.Load = function(p_string)
{
	if(TypeOf(p_string) != 'String' || p_string.length <= 0) { p_string = location.search; }
	var v_index = p_string.indexOf('?');
	if(v_index >= 0) { p_string = p_string.substring(v_index + 1); } // Strip all characters before and including the ?.
	v_index = p_string.indexOf('#');
	if(v_index >= 0) { p_string = p_string.substring(0, v_index); } // Strip out the hash if there is one included after the variable list.
	v_index = -1;
	var v_vars = p_string.split('&');
	for(var i = 0; i < v_vars.length; i++)
	{
		v_index = v_vars[i].indexOf('=');
		if(v_index >= 0) { this.Add(decodeURIComponent(v_vars[i].substring(0, v_index)).toLowerCase(), decodeURIComponent(v_vars[i].substring(v_index + 1))); }
	}
	return;
}
QueryString.Load = function(p_string) { var v_qs = new QueryString(); v_qs.Load(p_string); return v_qs; }
QueryString.Create = function(p_variableObject) { var v_qs = new QueryString(); v_qs.List = p_variableObject; return v_qs.ToString(); }

function Uri(p_string)
{
	this.Protocol = '';
	this.Host = '';
	this.Path = '';
	this.File = '';
	this.Hash = '';
	this.Query = new QueryString();
	if(TypeOf(p_string) == 'String' && p_string.length > 0) { this._Parse(p_string); }
	return;
}
Uri.prototype.GetType = function() { return 'Uri'; }
Uri.prototype.toString = function() { return this.ToString(); }
Uri.prototype.ToString = function()
{
	var v_sb = new StringBuilder();
	if(this.Protocol.length > 0) { v_sb.Append(this.Protocol).Append('://'); }
	v_sb.Append(this.Host).Append(this.Path).Append(this.File);
	if(this.Query.Count > 0) { v_sb.Append('?').Append(this.Query.ToString()); }
	if(TypeOf(this.Hash) == 'String' && this.Hash.length > 0) { v_sb.Append('#').Append(this.Hash); }
	return v_sb.ToString();
}
Uri.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'Uri' && (this.ToString() == p_object.ToString()); }
Uri.prototype.Load = function(p_string)
{
	if(TypeOf(p_string) != 'String' || p_string.length <= 0) { this._Parse(window.location.href); }
	else { this._Parse(p_string); }
	return;
}
Uri.Load = function(p_string) { var v_uri = new Uri(); v_uri.Load(p_string); return v_uri; }
Uri.prototype._Parse = function(p_string)
{
	try {
	var regex_pattern = /^((http|https|ftp):\/\/)?([^:\/\s]*)((\/\w+)*\/)([\w\-\.]+\.[^#?\s]+).*$/;
	if(p_string.match(regex_pattern))
	{
		this.Protocol = RegExp.$2;
		this.Host = RegExp.$3;
		this.Path = RegExp.$4;
		this.File = RegExp.$6;
	}
	var v_index_p = p_string.indexOf('#');
	if(v_index_p >= 0)
	{
		var v_index_q = p_string.indexOf('?');
		if(v_index_q > v_index_p) { this.Hash = p_string.substring(v_index_p, v_index_q); }
		else { this.Hash = p_string.substring(v_index_p); }
		this.Hash = this.Hash.replace(/#/g, '');
	}
	this.Query.Load(p_string);
	} catch(e) { throw new Error('Can not parse the string into a valid URI.'); }
	return;
}

function HttpCookies()
{
	HttpCookies.baseConstructor.call(this);
	var v_index = -1;
	var v_array = document.cookie.split(';');
	for(var i = 0; i < v_array.length; i++)
	{
		v_index = v_array[i].indexOf('=');
		if(v_index >= 0) { HttpCookies.superClass.Add.call(this, decodeURIComponent(v_array[i].substring(0, v_index).Trim()), decodeURIComponent(v_array[i].substring(v_index + 1).Trim())); }
	}
	return;
}
Extend(HttpCookies, HashArray);
HttpCookies.prototype.GetType = function() { return 'HttpCookies'; }
HttpCookies.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'HttpCookies' && (this.ToString() == p_object.ToString()); }
HttpCookies.prototype.Item = function(p_key, p_value) { if(p_value != undefined) { HttpCookies.SetCookie(TypeOf(p_key) != 'Number' ? p_key : this.KeyAt(p_key), p_value); } return HttpCookies.superClass.Item.call(this, p_key, p_value); }
HttpCookies.prototype.Add = function(p_key, p_value, p_expires) { HttpCookies.superClass.Add.call(this, p_key, p_value); HttpCookies.SetCookie(p_key, p_value, p_expires); return; }
HttpCookies.prototype.Remove = function(p_key) { HttpCookies.superClass.Remove.call(this, p_key); var v_date = Date.Today(); v_date.AddDays(-1); HttpCookies.SetCookie(p_key, 'null', v_date); return; }
HttpCookies.prototype.RemoveAt = function(p_index) { this.Remove(this.KeyAt(p_index)); return; }
HttpCookies.prototype.Clear = function()
{
	var v_date = Date.Today(); v_date.AddDays(-1);
	for(var v_key in this.List) { this.List[v_key] = undefined; HttpCookies.SetCookie(v_key, 'null', v_date); }
	this.Count = 0;
	return;
}
HttpCookies.SetCookie = function(p_key, p_value, p_expires) { document.cookie = encodeURIComponent(p_key) + '=' + encodeURIComponent(p_value) + (TypeOf(p_expires) == 'Date' ? '; ' + p_expires.toUTCString() : '') + '; path=/'; return; }

// ** Add some array searching functionality to the javascript Array object, since it isn't provided by default. ** //
Array.prototype.GetType = function() { return 'Array'; }
Array.prototype.ToString = function() { return this.toString(); }
Array.prototype.Equals = function(p_object) { return TypeOf(p_object) == this.GetType() && this == p_object; }
Array.prototype.CompareTo = function(p_array) { return Array.Compare(this, p_array); }
Array.prototype.IndexOf = function(p_value) { for(var i = 0; i < this.length; i++) { if(this.CompareFunction(this[i], p_value) == 0) { return i; } } return -1; }
Array.prototype.Contains = function(p_value) { return (this.IndexOf(p_value) >= 0) ? true : false; }
Array.prototype.Add = function(p_value) { this.push(p_value); return this.length - 1; }
Array.prototype.RemoveAt = function(p_index) { if(p_index < this.length && p_index >= 0) { this.splice(p_index, 1); return true; } return false; }
Array.prototype.Remove = function(p_value) { return this.RemoveAt(this.IndexOf(p_value)); }
Array.prototype.Clear = function() { this.length = 0; return; }
Array.prototype.Sort = function() { this.sort(this.CompareFunction); return; }
Array.prototype.CompareFunction = function(p_left, p_right) { return p_left == p_right ? 0 : (p_left < p_right ? -1 : 1); }
Array.prototype.InternalToString = function(p_type)
{
	var v_retval = p_type + ' [' + this.length + ' item(s)]\n(\n';
	if(this.length > 0)
	{
		for(var i = 0; i < this.length; i++) { v_retval += '\t[' + i + '] => (' + TypeOf(this[i]) + ') => ' + this[i] + ',\n'; }
		v_retval = v_retval.substr(0, v_retval.length - 2) + '\n';
	}
	v_retval += ')\n';
	return v_retval;
}
Array.prototype.toString = function() { return this.InternalToString(this.GetType()); }
Array.Compare = function(p_array1, p_array2) { return p_array1.length == p_array2.length ? 0 : (p_array1.length < p_array2.length ? -1 : 1); }
// ** Added functionality to the javascript core Boolean class ** //
Boolean.prototype.GetType = function() { return 'Boolean'; }
Boolean.prototype.ToString = function() { return this.toString(); }
Boolean.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'Boolean' && this == p_object; }
Boolean.prototype.CompareTo = function(p_bool) { return Boolean.Compare(this, p_bool); }
Boolean.Compare = function(p_bool1, p_bool2) { return p_bool2 && !p_bool1 ? 1 : (!p_bool2 && p_bool1 ? -1 : 0); }
// ** Added functionality to the javascript core Date class ** //
Date.prototype.GetType = function() { return 'Date'; }
Date.prototype.ToString = function() { return this.toString(); }
Date.prototype.Equals = function(p_object) { var v_d1_ms = this.getTime(); var v_d2_ms = p_object.getTime(); return v_d1_ms == v_d2_ms; }
Date.prototype.CompareTo = function(p_date) { return Date.Compare(this, p_date); }
Date.prototype.AddYears = function(p_value) { this.setFullYear(this.getFullYear() + p_value); return; }
Date.prototype.AddMonths = function(p_value) { this.setMonth(this.getMonth() + p_value); return; }
Date.prototype.AddDays = function(p_value) { this.setDate(this.getDate() + p_value); return; }
Date.prototype.AddHours = function(p_value) { this.setHours(this.getHours() + p_value); return; }
Date.prototype.AddMinutes = function(p_value) { this.setMinutes(this.getMinutes() + p_value); return; }
Date.prototype.AddSeconds = function(p_value) { this.setSeconds(this.getSeconds() + p_value); return; }
Date.prototype.AddMilliseconds = function(p_value) { this.setMilliseconds(this.getMilliseconds() + p_value); return; }
Date.prototype.GetFirstWeekDay = function() { var v_date = this.Clone(); v_date.AddDays(v_date.getDay() * -1); return v_date; }
Date.prototype.GetLastWeekDay = function() { var v_date = this.Clone(); v_date.AddDays((v_date.getDay() * -1) + 6); return v_date; }
Date.prototype.GetFirstMonthDay = function() { return new Date(this.getFullYear(), this.getMonth(), 1, 0, 0, 0, 0); }
Date.prototype.GetLastMonthDay = function() { return new Date(this.getFullYear(), this.getMonth(), this.GetDaysInMonth(), 0, 0, 0, 0); }
Date.prototype.GetDaysInMonth = function() { return Date.DaysInMonth(this.getFullYear(), this.getMonth()); }
Date.prototype.GetIsoWeekNumber = function() { return Date.IsoWeekNumber(this); }
Date.prototype.GetDayOfYear = function() { return Date.DayOfYear(this.getFullYear(), this.getMonth(), this.getDate()); }
Date.prototype.GetLongMonthName = function() { return Date.LongMonthName(this.getMonth()); }
Date.prototype.GetShortMonthName = function() { return Date.ShortMonthName(this.getMonth()); }
Date.prototype.GetLongWeekDayName = function() { return Date.LongWeekDayName(this.getDay()); }
Date.prototype.GetShortWeekDayName = function() { return Date.ShortWeekDayName(this.getDay()); }
Date.prototype.GetWeekDayLetter = function() { return Date.WeekDayLetter(this.getDay()); }
Date.prototype.DateValue = function() { var v_date = this.Clone(); v_date.setHours(0, 0, 0, 0); return v_date; }
Date.prototype.TimeValue = function() { var v_date = this.Clone(); v_date.setFullYear(1970, 0, 1); return v_date; }
Date.prototype.Clone = function() { return new Date(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds(), this.getMilliseconds()); }
Date.prototype.IsLessThan = function(p_date) { var v_d1_ms = this.getTime(); var v_d2_ms = p_date.getTime(); return v_d1_ms < v_d2_ms; }
Date.prototype.IsGreaterThan = function(p_date) { var v_d1_ms = this.getTime(); var v_d2_ms = p_date.getTime(); return v_d1_ms > v_d2_ms; }
Date.prototype.IsLessThanOrEqualTo = function(p_date) { var v_d1_ms = this.getTime(); var v_d2_ms = p_date.getTime(); return v_d1_ms <= v_d2_ms; }
Date.prototype.IsGreaterThanOrEqualTo = function(p_date) { var v_d1_ms = this.getTime(); var v_d2_ms = p_date.getTime(); return v_d1_ms >= v_d2_ms; }
Date.prototype.Format = function(p_format)
{
	var v_retval = '', i = 0, v_char = '', v_token = '', v_in_html = false;
	var v_year = this.getFullYear();
	var v_month = this.getMonth();
	var v_day = this.getDate();
	var v_hour = this.getHours();
	var v_minute = this.getMinutes();
	var v_second = this.getSeconds();
	var v_millisecond = this.getMilliseconds();
	var v_ms = v_millisecond / 1000;
	var v_12hour = v_hour > 11 ? v_hour - 12 : v_hour;
	if(v_12hour == 0) { v_12hour = 12; }
	var v_tzo_sign = this.getTimezoneOffset() < 0 ? '+' : '-';
	var v_abs_tzo = Math.abs(this.getTimezoneOffset());
	var v_tzo_hours = v_abs_tzo / 60;
	var v_iso_week_number = this.GetIsoWeekNumber();
	var v_day_of_year = this.GetDayOfYear();
	var v_values = new Object();
	v_values['ffff'] = v_ms.RoundRight(4).toString().replace('0.', '');
	v_values['fff']  = v_ms.RoundRight(3).toString().replace('0.', '');
	v_values['ff']   = v_ms.RoundRight(2).toString().replace('0.', '');
	v_values['f']    = v_ms.RoundRight(1).toString().replace('0.', '');
	v_values['FFFF'] = v_ms.RoundRight(4).PadDecimals(4).replace('0.', '');
	v_values['FFF']  = v_ms.RoundRight(3).PadDecimals(3).replace('0.', '');
	v_values['FF']   = v_ms.RoundRight(2).PadDecimals(2).replace('0.', '');
	v_values['F']    = v_ms.RoundRight(1).PadDecimals(1).replace('0.', '');
	v_values['ss']   = v_second.Pad(2);
	v_values['s']    = v_second.toString();
	v_values['mm']   = v_minute.Pad(2);
	v_values['m']    = v_minute.toString();
	v_values['hhhh'] = v_hour == 0 ? 'midnight' : (v_hour == 12 ? 'noon' : v_12hour.Pad(2));
	v_values['hhh']  = v_hour == 0 ? 'midnight' : (v_hour == 12 ? 'noon' : v_12hour.toString());
	v_values['hh']   = v_12hour.Pad(2);
	v_values['h']    = v_12hour.toString();
	v_values['HHHH'] = v_hour == 0 ? 'midnight' : (v_hour == 12 ? 'noon' : v_hour.Pad(2));
	v_values['HHH']  = v_hour == 0 ? 'midnight' : (v_hour == 12 ? 'noon' : v_hour.toString());
	v_values['HH']   = v_hour.Pad(2);
	v_values['H']    = v_hour.toString();
	v_values['dddd'] = this.GetLongWeekDayName();
	v_values['ddd']  = this.GetShortWeekDayName();
	v_values['dd']   = v_day.Pad(2);
	v_values['d']    = v_day.toString();
	v_values['MMMM'] = this.GetLongMonthName();
	v_values['MMM']  = this.GetShortMonthName();
	v_values['MM']   = (v_month + 1).Pad(2);
	v_values['M']    = (v_month + 1).toString();
	v_values['yyyy'] = v_year.Pad(4);
	v_values['yy']   = this.getYear().Pad(2);
	v_values['y']    = v_year.toString();
	v_values['jjj']  = v_day_of_year.Pad(3);
	v_values['jj']   = v_day_of_year.Pad(2);
	v_values['j']    = v_day_of_year.Pad(1);
	v_values['wwww'] = v_iso_week_number.Pad(2) + v_iso_week_number.GetOrdinal();
	v_values['www']  = v_iso_week_number.Pad(1) + v_iso_week_number.GetOrdinal();
	v_values['ww']   = v_iso_week_number.Pad(2);
	v_values['w']    = v_iso_week_number.Pad(1);
	v_values['O']    = v_day_of_year.GetOrdinal();
	v_values['o']    = v_day.GetOrdinal();
	v_values['zzzz'] = v_tzo_sign + v_tzo_hours.Pad(2) + ':' + (v_abs_tzo - (v_tzo_hours * 60)).Pad(2);
	v_values['zzz']  = v_tzo_sign + v_tzo_hours.toString() + ':' + (v_abs_tzo - (v_tzo_hours * 60)).Pad(2);
	v_values['zz']   = v_tzo_sign + v_tzo_hours.Pad(2);
	v_values['z']    = v_tzo_sign + v_tzo_hours.toString();
	v_values['TT']   = v_hour > 11 ? 'PM' : 'AM';
	v_values['T']    = v_hour > 11 ? 'P' : 'A';
	v_values['tt']   = v_hour > 11 ? 'pm' : 'am';
	v_values['t']    = v_hour > 11 ? 'p' : 'a';
	v_values['G']    = v_year < 0 ? 'BC' : 'AD';
	v_values['g']    = v_year < 0 ? 'bc' : 'ad';
	if((v_hour == 0 || v_hour == 12) && v_minute == 0 && v_second == 0 && v_millisecond == 0 && (p_format.indexOf('hhh') >= 0 || p_format.indexOf('HHH') >= 0))
	{
		p_format = p_format.replace('f', '');
		p_format = p_format.replace('F', '');
		p_format = p_format.replace('s', '');
		p_format = p_format.replace('m', '');
		p_format = p_format.replace('T', '');
		p_format = p_format.replace('t', '');
		p_format = p_format.replace(':', '');
	}
	while(i < p_format.length)
	{
		v_char = p_format.charAt(i);
		v_token = '';
		if(!v_in_html && v_char == '<') { v_in_html = true; }
		if(!v_in_html)
		{
			while((p_format.charAt(i) == v_char) && (i < p_format.length)) { v_token += p_format.charAt(i++); }
			if(v_values[v_token] != null) { v_retval += v_values[v_token]; }
			else { v_retval += v_token; }
		}
		else
		{
			i++;
			v_retval += v_char;
			if(v_in_html && v_char == '>') { v_in_html = false; }
		}
	}
	return v_retval.Trim();
}
Date.Compare = function(p_date1, p_date2) { return p_date1.IsLessThan(p_date2) ? -1 : (p_date1.Equals(p_date2) ? 0 : 1); }
Date.Today = function() { var v_date = new Date(); v_date.setHours(0, 0, 0, 0); return v_date; }
Date.Now = function() { return new Date(); }
Date.DaysInMonths = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
Date.LongMonthNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
Date.ShortMonthNames = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
Date.LongWeekDayNames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
Date.ShortWeekDayNames = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
Date.WeekDayLetters = new Array('S', 'M', 'T', 'W', 'T', 'F', 'S');
Date.IsLeapYear = function(p_year) { if(p_year % 400 == 0) { return true; } else if(p_year % 100 == 0) { return false; } else if(p_year % 4 == 0) { return true; } return false; }
Date.DaysInMonth = function(p_year, p_month) { if(p_month > 11 || p_month < 0) { throw InvalidArgumentException('p_month'); return 0; } if(p_month == 1) { return Date.IsLeapYear(p_year) ? 29 : 28; } return Date.DaysInMonths[p_month]; }
Date.LongMonthName = function(p_month) { if(p_month > 11 || p_month < 0) { throw InvalidArgumentException('p_month'); return 'Invalid month'; } return Date.LongMonthNames[p_month]; }
Date.ShortMonthName = function(p_month) { if(p_month > 11 || p_month < 0) { throw InvalidArgumentException('p_month'); return 'Invalid month'; } return Date.ShortMonthNames[p_month]; }
Date.LongWeekDayName = function(p_weekday) { if(p_weekday > 6 || p_weekday < 0) { throw InvalidArgumentException('p_weekday'); return 'Invalid weekday'; } return Date.LongWeekDayNames[p_weekday]; }
Date.ShortWeekDayName = function(p_weekday) { if(p_weekday > 6 || p_weekday < 0) { throw InvalidArgumentException('p_weekday'); return 'Invalid weekday'; } return Date.ShortWeekDayNames[p_weekday]; }
Date.WeekDayLetter = function(p_weekday) { if(p_weekday > 6 || p_weekday < 0) { throw InvalidArgumentException('p_weekday'); return 'Invalid weekday'; } return Date.WeekDayLetters[p_weekday]; }
Date.DateDiff = function(p_part, p_date1, p_date2)
{
	var v_d1_ms = p_date1.getTime();
	var v_d2_ms = p_date2.getTime();
	var v_diff_in_ms = v_d1_ms - v_d2_ms;
	switch(p_part)
	{
		case 'ms': return v_diff_in_ms; // Milliseconds
		case 's': return v_diff_in_ms / 1000; // Seconds
		case 'm': return v_diff_in_ms / (1000 * 60); // Minutes
		case 'h': return v_diff_in_ms / (1000 * 60 * 60); // Hours
		case 'd': return v_diff_in_ms / (1000 * 60 * 60 * 24); // Days
		case 'ww': throw Exception('Week of year is not supported yet.'); return 0; // Week of year
		case 'w': throw Exception('Weekdays are not supported yet.'); return 0; // Weekday
		case 'y': throw Exception('Day of year is not supported yet.'); return 0; // Day of year
		case 'm': throw Exception('Months are not supported yet.'); return 0; // Month
		case 'q': throw Exception('Quarters are not supported yet.'); return 0; // Quarter
		case 'yyyy': throw Exception('Years are not supported yet.'); return 0; // Years
		default: throw InvalidArgumentException('p_part'); return 0;
	}
}
Date.IsoWeekNumber = function(p_date)
{
	var v_date = p_date.Clone();
	var v_new_year = new Date(v_date.getFullYear(), 0, 1, 0, 0, 0, 0);
	var v_offset = 7 + 1 - v_new_year.getDay();
	if(v_offset == 8) { v_offset = 1; }
	var v_daynum = ((Date.UTC(v_date.getFullYear(), v_date.getMonth(), v_date.getDate(), 0, 0, 0, 0) - Date.UTC(v_date.getFullYear(), 0, 1, 0, 0, 0, 0)) / 1000 / 60 / 60 / 24) + 1;
	var v_weeknum = Math.floor((v_daynum - v_offset + 7) / 7);
	if(v_weeknum == 0)
	{
		v_date.AddYears(-1);
		var v_prev_new_year = new Date(v_date.getFullYear(), 0, 1, 0, 0, 0, 0);
		var v_prev_offset = 7 + 1 - v_prev_new_year.getDay();
		if(v_prev_offset == 2 || v_prev_offset == 8) { v_weeknum = 53; }
		else { v_weeknum = 52; }
	}
	return v_weeknum;
}
Date.DayOfYear = function(p_year, p_month, p_day)
{
	if(p_month == 0) { return p_day; }
	for(var i = 0; i < p_month; i++)
	{
		if(i == 1 && Date.IsLeapYear(p_year)) { p_day += 29; }
		else { p_day += Date.DaysInMonths[i]; }
	}
	return p_day;
}
Date.IsDate = function(p_value) { return !isNaN(Date.parse(p_value)); }
// ** Add some custom error handling methods to the javascript Error object. ** //
Error.prototype.GetType = function() { return 'Error'; }
Error.prototype.ToString = function() { return this.toString(); }
Error.prototype.ToErrorString = function()
{
	function __get_string(p_string)
	{
		switch(TypeOf(p_string))
		{
			case 'String': return p_string;
			case 'Number': return p_string.toString();
			case 'Boolean': return p_string.toString();
			default: return '';
		}
	}
    // TODO: Parse the stack string so it is more readable.
    var v_string = 'Message: ' + __get_string(this.message)
		+ '\nDesc: ' + __get_string(this.description)
        + '\nName: ' + __get_string(this.name)
		+ '\nNumber: ' + __get_string(this.number)
        + '\nLine: ' + __get_string(this.lineNumber)
        + '\nFile: ' + __get_string(this.fileName)
        + '\nStack Trace:\n' + __get_string(this.stack).replace(/@/g, '\n\tat ');//.replace(/:/g, ' on line ');
    return v_string;
}
Error.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'Error' && this.message == p_object.message && this.name == p_object.name && this.lineNumber == p_object.lineNumber && this.stack == p_object.stack; }
Error.prototype.CompareTo = function(p_error) { return Error.Compare(this, p_error); }
Error.prototype.ShowAlert = function() { alert(this.ToErrorString()); return; }
Error.Compare = function(p_error1, p_error2) { return 0; }
// ** Add some number formatting functionality to the javascript Number object, since none are provided by default. ** //
Number.prototype.GetType = function() { return 'Number'; }
Number.prototype.ToString = function() { return this.toString(); }
Number.prototype.ToCurrencyString = function() { return this.Format(2, '.', ','); }
Number.prototype.ToCssString = function() { return String(this) + 'px'; }
Number.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'Number' && this == p_object; }
Number.prototype.CompareTo = function(p_number) { return Number.Compare(this, p_number); }
Number.prototype.Format = function(p_formatString)
{
	var v_int_part = parseInt(this);
	var v_dec_part = this.toString().indexOf('.') > 0 ? parseInt(this.toString().split('.')[1]) : 0;
	
	var v_int_string = '';
	var v_dec_string = '';
	
	var v_parts = p_formatString.split('.');
	var v_fs_array = v_parts[0].split('').reverse();
	var v_ip_array = v_int_part.toString().split('').reverse();
	if(v_fs_array.length >= v_ip_array.length)
	{
		for(var i = 0; i < v_ip_array.length; i++)
		{
			if(v_fs_array[i] == ',') { continue; }
			v_fs_array[i] = v_ip_array[i];
		}
		v_int_string = v_fs_array.join('').replace(/#/g, '');
	}
	else { v_int_string = v_int_part.toString(); }

	// Do we have a decimal part to format?
	if(v_parts.length > 1 && v_parts[1].length > 0)
	{
		v_fs_array = v_parts[1].split('');
		v_ip_array = v_dec_part.toString().split('');
		if(v_ip_array.length > 0)
		{
			var v_length = v_fs_array.length;
			for(var i = 0; i < v_ip_array.length; i++)
			{
				if(i >= v_length) { break; }
				v_fs_array[i] = v_ip_array[i];
			}
			v_dec_string = v_fs_array.join('').replace(/#/g, '');
		}
		else { v_dec_string = v_dec_part.toString(); }
		return v_int_string + '.' + v_dec_string;
	}
	
	return v_int_string;
}
Number.prototype.RoundLeft = function(p_numberOfSignificantDigits) { var v_pow = Math.pow(10, p_numberOfSignificantDigits); return Math.round(this / v_pow) * v_pow; }
Number.prototype.RoundRight = function(p_numberOfDecimals) { var v_pow = Math.pow(10, p_numberOfDecimals); return Math.round(this * v_pow) / v_pow; }
Number.prototype.Pad = function(p_numberOfDigits)
{
	var v_string = this.toString();
	var v_s_len = v_string.length;
	if(v_s_len < p_numberOfDigits) { for(var i = v_s_len; i < p_numberOfDigits; i++) { v_string = '0' + v_string; } }
	return v_string;
}
Number.prototype.PadRight = function(p_numberOfDigits)
{
	var v_string = this.toString();
	var v_s_len = v_string.length;
	if(v_s_len < p_numberOfDigits) { for(var i = v_s_len; i < p_numberOfDigits; i++) { v_string = v_string + '0'; } }
	return v_string;
}
Number.prototype.PadDecimals = function(p_numberOfDecimals)
{
	var v_int = parseInt(this);
	var v_dec = this - v_int;
	return v_int.toString() + '.' + (v_dec * Math.pow(10, p_numberOfDecimals)).toString();
}
Number.prototype.GetOrdinal = function()
{
	if(this > 100) { return (this % 100).GetOrdinal(); }
	if(this >= 11 && this <= 19) { return 'th'; }
	switch(this % 10)
	{
		case 1: return 'st';
		case 2: return 'nd';
		case 3: return 'rd';
	}
	return 'th';
}
Number.Compare = function(p_number1, p_number2) { return p_number1 == p_number2 ? 0 : p_number1 < p_number2 ? -1 : 1; }
// ** Added functionality to the javascript core Object class ** //
Object.prototype.GetType = function() { return 'Object'; }
Object.prototype.ToString = function() { return this.toString(); }
Object.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'Object' && this == p_object; }
Object.prototype.CompareTo = function(p_object) { return Object.Compare(this, p_object); }
Object.Compare = function(p_object1, p_object2) { return 0; }
Object.Equals = function(p_object1, p_object2) { if(TypeOf(p_object1) == TypeOf(p_object2)) { try { return p_object1.Equals(p_object2); } catch(e) { return false; } } return false; }
Object.ToString = function(p_object)
{
	var v_string = '[Object: ' + TypeOf(p_object) + ']\n(\n';
	for(var v_name in p_object)
	{
		if(typeof(p_object[v_name]) != 'function')
		{
			v_string += '    ' + v_name + ' (' + TypeOf(p_object[v_name]) + ') -> ' + p_object[v_name].toString() + '\n'
		}
	}
	return v_string + ')'
}
// ** Added functionality to the javascript core String class ** //
String.prototype.GetType = function() { return 'String'; }
String.prototype.ToString = function() { return this.toString(); }
String.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'String' && this == p_object; }
String.prototype.CompareTo = function(p_string) { return String.Compare(this, p_string); }
String.prototype.Trim = function() { return this.replace(/^\s+|\s+$/g, ''); }
function __WordToProperCase(p_word) { if(p_word.length <= 3 && p_word.match(/[A-Z]+/)) { return p_word; } return p_word.charAt(0).toUpperCase() + p_word.substr(1).toLowerCase(); }
String.prototype.ToProperCase = function() { return this.replace(/\w+/g, __WordToProperCase); }
String.prototype.IsNumeric = function() { var v_regex = /^[0-9,.]*$|^-[0-9,.]*$/; return v_regex.test(this); }
String.prototype.IsAlphaNumeric = function() { var v_regex = /^[0-9a-zA-Z,. -]*$/; return v_regex.test(this); }
String.prototype.IsEmpty = function() { var v_regex = /^\s*$/; return v_regex.test(this); }
String.prototype.Reverse = function() { return this.split('').reverse().join(''); }
String.prototype.HtmlEncode = function() { return String.HtmlEncode(this); }
String.prototype.HtmlDecode = function() { return String.HtmlDecode(this); }
String.Compare = function(p_string1, p_string2) { return p_string1 == p_string2 ? 0 : p_string1 < p_string2 ? -1 : 1; }
String.HtmlEncode = function(p_object)
{
	if(p_object == undefined || p_object == null) { return ''; }
	var v_div = document.createElement('div');
	var v_text = document.createTextNode(p_object.toString()); // Let the browsers encoding engine do all the work.
	v_div.appendChild(v_text);
	return v_div.innerHTML;
}
String.HtmlDecode = function(p_object)
{
	if(p_object == undefined || p_object == null) { return ''; }
	var v_string = p_object.toString();
	var v_retval = new StringBuilder();
	for (var i = 0; i < v_string.length; i++)
	{
		var v_char = v_string.charAt(i);
		if(v_char == '&')
		{
			var v_sc_index = v_string.indexOf(';', i + 1);
			if(v_sc_index > 0)
			{
				var v_entity = v_string.substring(i + 1, v_sc_index);
				if(v_entity.length > 1 && v_entity.charAt(0) == '#')
				{
					if(v_entity.charAt(1) == 'x' || v_entity.charAt(1) == 'X') { v_retval.Append(String.fromCharCode(eval('0' + v_entity.substring(1)))); }
					else { v_retval.Append(String.fromCharCode(eval(v_entity.substring(1)))); }
				}
				else
				{
					switch (v_entity)
					{
						case 'quot': v_retval.Append(String.fromCharCode(0x0022)); break;
						case 'amp': v_retval.Append(String.fromCharCode(0x0026)); break;
						case 'lt': v_retval.Append(String.fromCharCode(0x003c)); break;
						case 'gt': v_retval.Append(String.fromCharCode(0x003e)); break;
						case 'nbsp': v_retval.Append(String.fromCharCode(0x00a0)); break;
						case 'iexcl': v_retval.Append(String.fromCharCode(0x00a1)); break;
						case 'cent': v_retval.Append(String.fromCharCode(0x00a2)); break;
						case 'pound': v_retval.Append(String.fromCharCode(0x00a3)); break;
						case 'curren': v_retval.Append(String.fromCharCode(0x00a4)); break;
						case 'yen': v_retval.Append(String.fromCharCode(0x00a5)); break;
						case 'brvbar': v_retval.Append(String.fromCharCode(0x00a6)); break;
						case 'sect': v_retval.Append(String.fromCharCode(0x00a7)); break;
						case 'uml': v_retval.Append(String.fromCharCode(0x00a8)); break;
						case 'copy': v_retval.Append(String.fromCharCode(0x00a9)); break;
						case 'ordf': v_retval.Append(String.fromCharCode(0x00aa)); break;
						case 'laquo': v_retval.Append(String.fromCharCode(0x00ab)); break;
						case 'not': v_retval.Append(String.fromCharCode(0x00ac)); break;
						case 'shy': v_retval.Append(String.fromCharCode(0x00ad)); break;
						case 'reg': v_retval.Append(String.fromCharCode(0x00ae)); break;
						case 'macr': v_retval.Append(String.fromCharCode(0x00af)); break;
						case 'deg': v_retval.Append(String.fromCharCode(0x00b0)); break;
						case 'plusmn': v_retval.Append(String.fromCharCode(0x00b1)); break;
						case 'sup2': v_retval.Append(String.fromCharCode(0x00b2)); break;
						case 'sup3': v_retval.Append(String.fromCharCode(0x00b3)); break;
						case 'acute': v_retval.Append(String.fromCharCode(0x00b4)); break;
						case 'micro': v_retval.Append(String.fromCharCode(0x00b5)); break;
						case 'para': v_retval.Append(String.fromCharCode(0x00b6)); break;
						case 'middot': v_retval.Append(String.fromCharCode(0x00b7)); break;
						case 'cedil': v_retval.Append(String.fromCharCode(0x00b8)); break;
						case 'sup1': v_retval.Append(String.fromCharCode(0x00b9)); break;
						case 'ordm': v_retval.Append(String.fromCharCode(0x00ba)); break;
						case 'raquo': v_retval.Append(String.fromCharCode(0x00bb)); break;
						case 'frac14': v_retval.Append(String.fromCharCode(0x00bc)); break;
						case 'frac12': v_retval.Append(String.fromCharCode(0x00bd)); break;
						case 'frac34': v_retval.Append(String.fromCharCode(0x00be)); break;
						case 'iquest': v_retval.Append(String.fromCharCode(0x00bf)); break;
						case 'Agrave': v_retval.Append(String.fromCharCode(0x00c0)); break;
						case 'Aacute': v_retval.Append(String.fromCharCode(0x00c1)); break;
						case 'Acirc': v_retval.Append(String.fromCharCode(0x00c2)); break;
						case 'Atilde': v_retval.Append(String.fromCharCode(0x00c3)); break;
						case 'Auml': v_retval.Append(String.fromCharCode(0x00c4)); break;
						case 'Aring': v_retval.Append(String.fromCharCode(0x00c5)); break;
						case 'AElig': v_retval.Append(String.fromCharCode(0x00c6)); break;
						case 'Ccedil': v_retval.Append(String.fromCharCode(0x00c7)); break;
						case 'Egrave': v_retval.Append(String.fromCharCode(0x00c8)); break;
						case 'Eacute': v_retval.Append(String.fromCharCode(0x00c9)); break;
						case 'Ecirc': v_retval.Append(String.fromCharCode(0x00ca)); break;
						case 'Euml': v_retval.Append(String.fromCharCode(0x00cb)); break;
						case 'Igrave': v_retval.Append(String.fromCharCode(0x00cc)); break;
						case 'Iacute': v_retval.Append(String.fromCharCode(0x00cd)); break;
						case 'Icirc': v_retval.Append(String.fromCharCode(0x00ce )); break;
						case 'Iuml': v_retval.Append(String.fromCharCode(0x00cf)); break;
						case 'ETH': v_retval.Append(String.fromCharCode(0x00d0)); break;
						case 'Ntilde': v_retval.Append(String.fromCharCode(0x00d1)); break;
						case 'Ograve': v_retval.Append(String.fromCharCode(0x00d2)); break;
						case 'Oacute': v_retval.Append(String.fromCharCode(0x00d3)); break;
						case 'Ocirc': v_retval.Append(String.fromCharCode(0x00d4)); break;
						case 'Otilde': v_retval.Append(String.fromCharCode(0x00d5)); break;
						case 'Ouml': v_retval.Append(String.fromCharCode(0x00d6)); break;
						case 'times': v_retval.Append(String.fromCharCode(0x00d7)); break;
						case 'Oslash': v_retval.Append(String.fromCharCode(0x00d8)); break;
						case 'Ugrave': v_retval.Append(String.fromCharCode(0x00d9)); break;
						case 'Uacute': v_retval.Append(String.fromCharCode(0x00da)); break;
						case 'Ucirc': v_retval.Append(String.fromCharCode(0x00db)); break;
						case 'Uuml': v_retval.Append(String.fromCharCode(0x00dc)); break;
						case 'Yacute': v_retval.Append(String.fromCharCode(0x00dd)); break;
						case 'THORN': v_retval.Append(String.fromCharCode(0x00de)); break;
						case 'szlig': v_retval.Append(String.fromCharCode(0x00df)); break;
						case 'agrave': v_retval.Append(String.fromCharCode(0x00e0)); break;
						case 'aacute': v_retval.Append(String.fromCharCode(0x00e1)); break;
						case 'acirc': v_retval.Append(String.fromCharCode(0x00e2)); break;
						case 'atilde': v_retval.Append(String.fromCharCode(0x00e3)); break;
						case 'auml': v_retval.Append(String.fromCharCode(0x00e4)); break;
						case 'aring': v_retval.Append(String.fromCharCode(0x00e5)); break;
						case 'aelig': v_retval.Append(String.fromCharCode(0x00e6)); break;
						case 'ccedil': v_retval.Append(String.fromCharCode(0x00e7)); break;
						case 'egrave': v_retval.Append(String.fromCharCode(0x00e8)); break;
						case 'eacute': v_retval.Append(String.fromCharCode(0x00e9)); break;
						case 'ecirc': v_retval.Append(String.fromCharCode(0x00ea)); break;
						case 'euml': v_retval.Append(String.fromCharCode(0x00eb)); break;
						case 'igrave': v_retval.Append(String.fromCharCode(0x00ec)); break;
						case 'iacute': v_retval.Append(String.fromCharCode(0x00ed)); break;
						case 'icirc': v_retval.Append(String.fromCharCode(0x00ee)); break;
						case 'iuml': v_retval.Append(String.fromCharCode(0x00ef)); break;
						case 'eth': v_retval.Append(String.fromCharCode(0x00f0)); break;
						case 'ntilde': v_retval.Append(String.fromCharCode(0x00f1)); break;
						case 'ograve': v_retval.Append(String.fromCharCode(0x00f2)); break;
						case 'oacute': v_retval.Append(String.fromCharCode(0x00f3)); break;
						case 'ocirc': v_retval.Append(String.fromCharCode(0x00f4)); break;
						case 'otilde': v_retval.Append(String.fromCharCode(0x00f5)); break;
						case 'ouml': v_retval.Append(String.fromCharCode(0x00f6)); break;
						case 'divide': v_retval.Append(String.fromCharCode(0x00f7)); break;
						case 'oslash': v_retval.Append(String.fromCharCode(0x00f8)); break;
						case 'ugrave': v_retval.Append(String.fromCharCode(0x00f9)); break;
						case 'uacute': v_retval.Append(String.fromCharCode(0x00fa)); break;
						case 'ucirc': v_retval.Append(String.fromCharCode(0x00fb)); break;
						case 'uuml': v_retval.Append(String.fromCharCode(0x00fc)); break;
						case 'yacute': v_retval.Append(String.fromCharCode(0x00fd)); break;
						case 'thorn': v_retval.Append(String.fromCharCode(0x00fe)); break;
						case 'yuml': v_retval.Append(String.fromCharCode(0x00ff)); break;
						case 'ndash': v_retval.Append(String.fromCharCode(0x2013)); break;
						case 'mdash': v_retval.Append(String.fromCharCode(0x2014)); break;
						case 'lsquo': v_retval.Append(String.fromCharCode(0x2018)); break;
						case 'rsquo': v_retval.Append(String.fromCharCode(0x2019)); break;
						case 'sbquo': v_retval.Append(String.fromCharCode(0x201a)); break;
						case 'ldquo': v_retval.Append(String.fromCharCode(0x201c)); break;
						case 'rdquo': v_retval.Append(String.fromCharCode(0x201d)); break;
						case 'bdquo': v_retval.Append(String.fromCharCode(0x201e)); break;
						case 'dagger': v_retval.Append(String.fromCharCode(0x2020)); break;
						case 'Dagger': v_retval.Append(String.fromCharCode(0x2021)); break;
						case 'permil': v_retval.Append(String.fromCharCode(0x2030)); break;
						case 'lsaquo': v_retval.Append(String.fromCharCode(0x2039)); break;
						case 'rsaquo': v_retval.Append(String.fromCharCode(0x203a)); break;
						case 'oline': v_retval.Append(String.fromCharCode(0x203e)); break;
						case 'frasl': v_retval.Append(String.fromCharCode(0x2044)); break;
						case 'larr': v_retval.Append(String.fromCharCode(0x2190)); break;
						case 'uarr': v_retval.Append(String.fromCharCode(0x2191)); break;
						case 'rarr': v_retval.Append(String.fromCharCode(0x2192)); break;
						case 'darr': v_retval.Append(String.fromCharCode(0x2193)); break;
						case 'trade': v_retval.Append(String.fromCharCode(0x2122)); break;
						case 'spades': v_retval.Append(String.fromCharCode(0x2660)); break;
						case 'clubs': v_retval.Append(String.fromCharCode(0x2663)); break;
						case 'hearts': v_retval.Append(String.fromCharCode(0x2665)); break;
						case 'diams': v_retval.Append(String.fromCharCode(0x2666)); break;
						default: v_retval.Append('&').Append(v_entity).Append(';'); break;
					}
				}
				i = v_sc_index;
			}
			else { v_retval.Append(v_char); }
		}
		else { v_retval.Append(v_char); }
	}
	return v_retval.ToString();
}