// ** 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 new String(typeof(p_object)); }
	try { return new String(p_object.GetType()); }
	catch(e) { return new String(typeof(p_object)).ToProperCase(); }
}
// ** Common javascript object library. ** //
Utils = {};

// Browser detection
Utils.UserAgent = navigator.userAgent.toLowerCase();
Utils.AppVersion = navigator.appVersion.toLowerCase();
Utils.IsOpera = Utils.UserAgent.indexOf('opera') != -1;
Utils.IsKonqueror = Utils.UserAgent.indexOf('konqueror') != -1;
Utils.IsSafari = Utils.UserAgent.indexOf('safari') != -1;
Utils.IsKhtml = Utils.IsKonqueror || Utils.IsSafari;
Utils.IsGecko = !Utils.IsKhtml && navigator.product && navigator.product.toLowerCase() == 'gecko' ? true : false;
Utils.IsFirebird = Utils.UserAgent.indexOf('mozilla/5') != -1 && Utils.UserAgent.indexOf('spoofer') == -1 && Utils.UserAgent.indexOf('compatible') == -1 && Utils.UserAgent.indexOf('opera') == -1 && Utils.UserAgent.indexOf('webtv') == -1 && Utils.UserAgent.indexOf('hotjava') == -1 && Utils.IsGecko && navigator.vendor == 'Firebird';
Utils.IsFirefox = Utils.UserAgent.indexOf('mozilla/5') != -1 && Utils.UserAgent.indexOf('spoofer') == -1 && Utils.UserAgent.indexOf('compatible') == -1 && Utils.UserAgent.indexOf('opera') == -1 && Utils.UserAgent.indexOf('webtv') == -1 && Utils.UserAgent.indexOf('hotjava') == -1 && Utils.IsGecko && (navigator.vendor == 'Firefox' || Utils.UserAgent.indexOf('firefox') != -1);
Utils.IsMozilla = Utils.UserAgent.indexOf('mozilla/5') != -1 && Utils.UserAgent.indexOf('spoofer') == -1 && Utils.UserAgent.indexOf('compatible') == -1 && Utils.UserAgent.indexOf('opera') == -1 && Utils.UserAgent.indexOf('webtv') == -1 && Utils.UserAgent.indexOf('hotjava') == -1 && Utils.IsGecko && !Utils.IsFirebird && !Utils.IsFirefox && (navigator.vendor == '' || navigator.vendor == 'Mozilla' || navigator.vendor == 'Debian');
Utils.IsNetscape = Utils.UserAgent.indexOf('mozilla') != -1 && Utils.UserAgent.indexOf('spoofer') == -1 && Utils.UserAgent.indexOf('compatible') == -1 && Utils.UserAgent.indexOf('opera') == -1 && Utils.UserAgent.indexOf('webtv') == -1 && Utils.UserAgent.indexOf('hotjava') == -1 && !Utils.IsKhtml && !Utils.IsMozilla && !Utils.IsFirebird && !Utils.IsFirefox;
Utils.IsIE = Utils.AppVersion.indexOf('msie') != -1 && !Utils.IsOpera && !Utils.IsKhtml;
Utils.IsAOL = Utils.UserAgent.indexOf("aol") != -1;
Utils.IsWebTV = Utils.UserAgent.indexOf("webtv") != -1;
Utils.IsTVNavigator = Utils.UserAgent.indexOf("navio") != -1 || Utils.UserAgent.indexOf("navio_aoltv") != -1;
Utils.IsHotJava = Utils.UserAgent.indexOf("hotjava") != -1;

Utils.IsEmail = function(p_string)
{
    var v_regex = /^[A-Z][\w\.\+\-]+[A-Z0-9]@[A-Z0-9][\w\.-]*[A-Z0-9]\.[A-Z][A-Z\.]*[A-Z]$/i;
    return v_regex.test(p_string);
}
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 || Utils.IsOpera || Utils.IsKhtml || Utils.IsGecko) { 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 new Error('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.CancelEventBubble = function(evt)
{
    try
    {
        if(evt.stopPropagation) { evt.stopPropagation(); }
        evt.cancelBubble = true;
    }
    catch(err) { }
    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 new Error('p_link is NULL or empty!'); }
	p_handle = String(p_handle);
	if(!p_handle || p_handle.IsEmpty()) { throw new Error('p_handle is NULL or empty!'); }
	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);
}
Utils.AddScrollPosition = function(p_query)
{
    var v_scroll = Utils.GetPageScrollOffest();
	if(v_scroll.X != 0 || v_scroll.Y != 0)
	{
	    p_query.Add('x', v_scroll.X.toString(), true);
	    p_query.Add('y', v_scroll.Y.toString(), true);
	}
	else
	{
	    p_query.Remove('x');
	    p_query.Remove('y');
	}
    return;
}
Utils.SetScrollPosition = function()
{
    var v_qs = QueryString.Load();
    try { window.scrollTo(Utils.GetIntValue(v_qs.Item('x')), Utils.GetIntValue(v_qs.Item('y'))); }
    catch(e) { }
    return;
}

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 new Error('p_url is NULL or empty!'); return null; }
	if(typeof(DOMParser) != 'undefined' && typeof(ActiveXObject) != 'undefined') // Mozilla, Firefox, Internet Explorer, and related browsers
	{
	    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;
	}
	else // Attempt to load the XML document via XMLHTTP. This is supposed to work in Safari.
	{
	    var v_async = false;
	    var v_request = new XMLHttpRequest();
	    if(p_callback)
	    {
	        v_request.onreadystatechange = function() { if(v_request.readyState == 4) { p_callback(v_request.responseXML); } return; }
	        v_async = true;
	    }
		v_request.open('GET', p_url, v_async);
		v_request.send(null);
		return v_request.responseXML;
	}
}
Xml.LoadXml = function(p_xml)
{
	if(!p_xml || p_xml.length <= 0) { throw new Error('p_xml is NULL or empty!'); 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 v_request.responseXML;
	}
}
Xml.SelectSingleNode = function(p_doc, p_xpath, p_ieNameSpaces)
{
    if(p_doc == null || p_doc == undefined) { throw new Error('p_doc must be an XML document object.'); }
    if(TypeOf(p_xpath) != 'String' || p_xpath.length <= 0) { throw new Error('Null or empty XPath specified.'); }
	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.SelectSingleFromNode = function(p_node, p_xpath, p_ieNameSpaces)
{
    if(p_node == null || p_node == undefined) { throw new Error('p_node must be an XML node object.'); }
    if(p_node.ownerDocument == null) { throw new Error('The node does not have an owner XML document defined (p_node.ownerDocument is null).'); }
    if(TypeOf(p_xpath) != 'String' || p_xpath.length <= 0) { throw new Error('Null or empty XPath specified.'); }
	try // IE
	{
		if(TypeOf(p_ieNameSpaces) == 'String' && p_ieNameSpaces.length > 0) { p_node.ownerDocument.setProperty('SelectionNamespaces', p_ieNameSpaces); }
		return p_node.selectSingleNode(p_xpath);
	}
	catch(e) // Mozilla
	{
		var v_ns_resolver = p_node.ownerDocument.createNSResolver(p_node.ownerDocument.documentElement);
		var v_response_node = p_node.ownerDocument.evaluate(p_xpath, p_node, 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.GetHashCode = function() { return this.List.GetHashCode(); }
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 new Error('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) { this.List.push(p_value); this.Count++; return this.Count - 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 Object.Compare(p_left, p_right); }

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 = 0; } 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.GetHashCode = function() { return this.ToString(); }
StringBuilder.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'StringBuilder' && String.Equals(this.ToString(), p_object.ToString()); }
StringBuilder.prototype.CompareTo = function(p_object) { return String.Compare(this.ToString(), p_object.ToString()); }

/* NOTE: The built-in Image object is not supported as a key by the HashArray, since IE does not allow us to define custom methods on the Image prototype so we can't define a hashing function. */
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.GetHashCode = function() { return Object.GetHashCode(this.List); }
HashArray.prototype.CompareFunction = function(p_left, p_right) { return Object.Compare(p_left, p_right); }
HashArray.prototype.Item = function(p_keyOrIndex, p_value)
{
	if(TypeOf(p_keyOrIndex) != 'Number')
	{
		if(p_keyOrIndex == null) { throw new Error('The key can not be null.'); return null; }
		var v_keyhash = Object.GetHashCode(p_keyOrIndex);
		if(this.List[v_keyhash] != undefined)
		{
			try {
			if(p_value == undefined) { return this.List[v_keyhash].Value; }
			this.List[v_keyhash].Value = p_value;
			return;
			} catch(e) { }
		}
		throw new Error('Key does not exist "' + Object.ToString(p_keyOrIndex) + '".');
	}
	else
	{
		if(p_keyOrIndex < 0) { throw new Error('Index out of range (' + p_keyOrIndex + ').'); return null; }
		var v_count = 0;
		for(var v_keyhash in this.List)
		{
			if(v_count == p_keyOrIndex)
			{
				try {
				if(p_value == undefined) { return this.List[v_keyhash].Value; }
				this.List[v_keyhash].Value = p_value;
				return;
				} catch(e) { break; }
			}
			v_count++;
		}
		throw new Error('Index out of range (' + p_keyOrIndex + ').');
	}
}
HashArray.prototype.KeyAt = function(p_index)
{
	if(p_index < 0) { throw new Error('Index out of range (' + p_index + ').'); return null; }
	var v_count = 0;
	for(var v_keyhash in this.List)
	{
		try { if(v_count == p_index && this.List[v_keyhash].Value != undefined) { return v_keyhash; } }
		catch(e) { }
		v_count++;
	}
	throw new Error('Index out of range (' + p_index + ').');
	return null;
}
HashArray.prototype.KeyHashes = function()
{
	var v_hashes = new Array();
	for(var v_keyhash in this.List)
	{
		if(typeof(this.List[v_keyhash]) != 'function') { v_hashes.push(v_keyhash); }
	}
	return v_hashes;
}
HashArray.prototype.Keys = function()
{
	var v_keys = new Array();
	for(var v_keyhash in this.List)
	{
		var v_item = this.List[v_keyhash];
		if(typeof(v_item) != 'function')
		{
			try { v_keys.push(v_item.Key); }
			catch(e) { }
		}
	}
	return v_keys;
}
HashArray.prototype.Values = function()
{
	var v_values = new Array();
	for(var v_keyhash in this.List)
	{
		var v_item = this.List[v_keyhash];
		if(typeof(v_item) != 'function')
		{
			try { v_values.push(v_item.Value); }
			catch(e) { }
		}
	}
	return v_values;
}
HashArray.prototype.Add = function(p_key, p_value)
{
	if(p_key == null) { throw new Error('The key can not be null.'); return -1; }
	var v_keyhash = Object.GetHashCode(p_key);
	if(this.List[v_keyhash] == undefined)
	{
		this.List[v_keyhash] = { Key: p_key, Value: p_value };
		this.Count++;
	}
	else { this.List[v_keyhash] = { Key: p_key, Value: p_value }; }
	return;
}
HashArray.prototype.Remove = function(p_key)
{
	if(p_key == null) { throw new Error('The key can not be null.'); return; }
	var v_hash = Object.GetHashCode(p_key);
	if(this.List[v_hash] != undefined)
	{
		delete this.List[v_hash];
		this.Count--;
		if(this.Count < 0) { this.Count = 0; }
		return true;
	}
	return false;
}
HashArray.prototype.RemoveAt = function(p_index) { return this.Remove(this.KeyAt(p_index)); }
HashArray.prototype.Clear = function()
{
	this.List = new Object();
	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 new Error('The key can not be null.'); return -1; }
	var v_index = 0;
    for(var v_keyhash in this.List)
	{
		try { if(this.List[v_keyhash].Key === p_key) { return v_index; } }
		catch(e) { }
		v_index++;
	}
    return -1;
}
HashArray.prototype.IndexOfValue = function(p_value)
{
    if(p_value == null) { throw new Error('The value can not be null.'); return -1; }
    var v_index = 0;
    for(var v_keyhash in this.List)
	{
		try { if(this.CompareFunction(this.List[v_keyhash].Value, p_value) == 0) { return v_index; } }
		catch(e) { }
		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_keyhash in this.List)
	{
		var v_item = this.List[v_keyhash];
		if(typeof(v_item) != 'function')
		{
			if(v_count != 0) { v_sb.Append(',\n'); }
			v_sb.Append('    [').Append(v_count).Append('] ').Append(v_item.Key).Append(' => ');
			Object._ToStringRecursive(v_sb, v_item.Value, '    ');
			v_count++;
		}
	}
	v_sb.Append('\n)')
	return v_sb.ToString();
}

function QueryString(p_string) { QueryString.baseConstructor.call(this); if(TypeOf(p_string) == 'String' && p_string.length > 0) { this.Load(p_string); } return; }
Extend(QueryString, HashArray);
QueryString.prototype.GetType = function() { return 'QueryString'; }
QueryString.prototype.GetHashCode = function() { return this.ToString(); }
QueryString.prototype.ToString = function()
{
	var v_retval = '';
	for(var v_keyhash in this.List)
	{
		var v_item = this.List[v_keyhash];
		try { if(typeof(v_item) != 'function') { v_retval += encodeURIComponent(v_item.Key) + '=' + encodeURIComponent(v_item.Value) + '&'; } }
		catch(e) { }
	}
	return v_retval.substring(0, v_retval.length - 1);
}
QueryString.prototype.Add = function(p_key, p_value, p_overwrite)
{
	if(p_key == null) { throw new Error('The key can not be null.'); return -1; }
	var v_keyhash = Object.GetHashCode(p_key);
	if(this.List[v_keyhash] == undefined)
	{
		this.List[v_keyhash] = { Key: p_key, Value: p_value };
		this.Count++;
	}
	else if(p_overwrite) { this.List[v_keyhash] = { Key: p_key, Value: p_value }; }
	else
	{
	    try { this.List[v_keyhash].Value += ',' + p_value; }
	    catch(e) { this.List[v_keyhash] = { Key: p_key, Value: p_value }; }
	}
	return;
}
QueryString.prototype.Equals = function(p_object) { return TypeOf(p_object) == this.GetType() && this.ToString() == p_object.ToString(); }
QueryString.prototype.Load = function(p_string, p_overwrite)
{
    if(TypeOf(p_overwrite) != 'Boolean') { p_overwrite = true; }
    if(TypeOf(p_string) == 'Object')
    { // Handle JSON object parsing.
        for(var v_key in p_string) { this.Add(v_key, p_string[v_key], p_overwrite); }
        return;
    }
	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)), p_overwrite); }
	}
	return;
}
QueryString.prototype.MergeWith = function(p_query, p_mergeMode) // p_mergeMode: 1 = overwrite duplicated keys, 2 = merge duplicated keys, all other values = don't copy duplicated keys
{
    if(TypeOf(p_query) == 'String') { p_query = new QueryString(p_query); }
    else if(TypeOf(p_query) != 'QueryString') { p_query = QueryString.Load(); }
    for(var v_keyhash in p_query.List)
    {
        var v_item = p_query.List[v_keyhash];
        if(this.List[v_keyhash] == undefined)
        {
            this.List[v_keyhash] = { Key: v_item.Key, Value: v_item.Value };
		    this.Count++;
        }
        else if(p_mergeMode == 1) { this.List[v_keyhash] = { Key: v_item.Key, Value: v_item.Value }; }
        else if(p_mergeMode == 2)
        {
            try { this.List[v_keyhash].Value += ',' + v_item.Value; }
	        catch(e) { this.List[v_keyhash] = { Key: v_item.Key, Value: v_item.Value }; }
        }
    }
    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();
	for(var v_key in p_variableObject) { v_qs.Add(v_key, p_variableObject[v_key]); }
	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.GetHashCode = function() { return this.ToString(); }
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) == this.GetType() && 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) == this.GetType() && 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_keyhash in this.List) { HttpCookies.SetCookie(this.List[v_keyhash].Key, 'null', v_date); }
	HttpCookies.superClass.Clear.call(this);
	return;
}
HttpCookies.SetCookie = function(p_key, p_value, p_expires) { document.cookie = encodeURIComponent(p_key.toString()) + '=' + encodeURIComponent(p_value.toString()) + (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.GetHashCode = function()
{
	var v_hash = new StringBuilder();
	for(var i = 0; i < this.length; i++) { v_hash.Append(Object.GetHashCode(this[i])); }
	return v_hash.ToString();
}
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 Object.Compare(p_left, p_right); }
Array.prototype.InternalToString = function(p_type)
{
	var v_retval = new StringBuilder();
	v_retval.Append(p_type).Append(' [').Append(this.length).Append(' item(s)]\n(\n');
	if(this.length > 0)
	{
		for(var i = 0; i < this.length; i++)
		{
			v_retval.Append('    [').Append(i).Append('] => (').Append(TypeOf(this[i])).Append(') => ');
			Object._ToStringRecursive(v_retval, this[i], '    ');
			if(i < this.length - 1)
			{
				v_retval.Append(',');
			}
			v_retval.Append('\n');
		}
	}
	v_retval.Append(')');
	return v_retval.ToString();
}
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.GetHashCode = function() { return this ? 'true' : 'false'; }
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.GetHashCode = function() { return this.getTime().toString(); }
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.GetHashCode = function() { return this.message + this.name + this.lineNumber; }
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.GetHashCode = function() { return this.toString(); }
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.toString = function() { return Object.ToString(this); }
Object.Compare = function(p_object1, p_object2)
{
	if(p_object1 == null || p_object1 == undefined) { return 1; }
	if(p_object2 == null || p_object2 == undefined) { return -1; }
	try { return p_object1.CompareTo(p_object2); }
	catch(e) { throw new Error('CompareTo is not defined on type: ' + TypeOf(p_object1) + '.'); }
	return 0;
}
Object.Equals = function(p_object1, p_object2)
{
	try { return p_object1.Equals(p_object2); }
	catch(e) { return p_object1 === p_object2; }
	return false;
}
Object.ToString = function(p_object)
{
	var v_string = new StringBuilder();
	Object._ToStringRecursive(v_string, p_object, '');
	return v_string.ToString();
}
Object._ToStringRecursive = function(p_sb, p_object, p_indent)
{
	try { p_sb.Append(p_object.ToString().replace(/\n/g, '\n' + p_indent)); }
	catch(e)
	{
		p_sb.Append('[Object: ').Append(TypeOf(p_object)).Append(']\n').Append(p_indent).Append('(\n');
		for(var v_name in p_object)
		{
			var v_obj = p_object[v_name];
			if(typeof(v_obj) != 'function')
			{
				p_sb.Append(p_indent).Append('    ').Append(v_name).Append(' (').Append(TypeOf(v_obj)).Append(') -> ').Append(Object._ToStringRecursive(p_sb, v_obj, p_indent + '    ')).Append('\n');
			}
		}
		p_sb.Append(p_indent).Append(')');
	}
	return;
}
Object.GetHashCode = function(p_object)
{
	if(p_object == undefined || p_object == null) { return ''; }
	try { return p_object.GetHashCode().toString(); }
	catch(e)
	{
		var v_flag = false;
		var v_hash = new StringBuilder();
		for(var v_name in p_object)
		{
			var v_obj = p_object[v_name];
			if(typeof(v_obj) != 'function')
			{
				if(v_flag) { v_hash.Append(';'); }
				v_hash.Append(v_name).Append('=[').Append(Object.GetHashCode(v_obj)).Append(']');
				v_flag = true;
			}
		}
		return v_hash.ToString();
	}
}
// ** Added functionality to the javascript core RegExp class ** //
RegExp.prototype.GetType = function() { return 'RegExp'; }
RegExp.prototype.GetHashCode = function() { return this.source; }
RegExp.prototype.toString = function() { return '[RegExp: ' + this.source + ']'; }
RegExp.prototype.ToString = function() { return this.toString(); }
RegExp.prototype.Equals = function(p_object) { return TypeOf(p_object) == 'RegExp' && this.source == p_object.source; }
RegExp.prototype.CompareTo = function(p_object) { return RegExp.Compare(this, p_object); }
RegExp.Compare = function(p_object1, p_object2) { return String.Compare(p_object1.source, p_object2.source); }
// ** Added functionality to the javascript core String class ** //
String.prototype.GetType = function() { return 'String'; }
String.prototype.GetHashCode = function() { return this.toString(); }
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();
}