// ** Provides exception style error handling. ** //
// These methods are depricated, since using them makes debuging the javascript more difficult.
function Exception(p_message) { return new Error(p_message); }
function ArgumentNullException(p_argument) { return new Error('Missing or NULL value for the argument: ' + p_argument); }
function InvalidArgumentException(p_argument) { return new Error('Invalid value for the argument: ' + p_argument); }
// ** Common javascript functions library. ** //
function Extend(p_subClass, p_baseClass)
{
	inheritance = function() { }
	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(); }
}
$ = function(p_id) { return document.getElementById(p_id); }
function Alert(text, options, okCallback, imageFolderPath)
{
    if (typeof (JavaWindow) != 'undefined') { JavaWindow.Alert(text, options, okCallback, imageFolderPath); }
    else { alert(text); if (okCallback) { okCallback(null); } }
    return;
}
function Confirm(text, options, buttonTypes, yesOkCallback, noCancelCallback, imageFolderPath)
{
    if (typeof (JavaWindow) != 'undefined') { JavaWindow.Confirm(text, options, buttonTypes, yesOkCallback, noCancelCallback, imageFolderPath); }
    else
    {
        var v_result = confirm(text);
        if (v_result && yesOkCallback) { yesOkCallback(null, v_result); }
        else if (noCancelCallback) { noCancelCallback(null); }
    }
    return;
}
function Prompt(text, defaultValue, options, okCallback, cancelCallback, imageFolderPath)
{
    if (typeof (JavaWindow) != 'undefined') { JavaWindow.Prompt(text, defaultValue, options, okCallback, cancelCallback, imageFolderPath); }
    else
    {
        var v_result = prompt(text, defaultValue);
        if (v_result != null && okCallback) { okCallback(null, v_result); }
        else if (cancelCallback) { cancelCallback(null); }
    }
    return;
}
// ** 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.IsIE6 = Utils.IsIE && parseFloat(Utils.AppVersion.substring(Utils.AppVersion.indexOf('msie') + 5)) == 6;
Utils.IsIE7 = Utils.IsIE && parseFloat(Utils.AppVersion.substring(Utils.AppVersion.indexOf('msie') + 5)) == 7;
Utils.IsIE8 = Utils.IsIE && parseFloat(Utils.AppVersion.substring(Utils.AppVersion.indexOf('msie') + 5)) == 8;
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(emailToValidate) {
	/**
	 * Email Validation rules:
	 * - Local part:
	 *  -- No longer than 64 characters: [a-z A-Z 0-9 ! # $ % &amp; ' * + - / = ? ^ _ ` { | } ~ .] (no whitespace characters).
	 *  -- Cannot contain two or more "dots" (.) in a row.
	 *  -- Can not start or end with a "dot".
	 *
	 *  - Domain part:
	 *  -- No longer than 255 characters and no less than 1 character
	 *  -- Can contain any of the following characters: [a-z A-Z 0-9 0 .] (no whitespace characters).
	 *  -- Does not contain two or more consecutive "dots" (.).
	 *  -- Does not start or end with a hyphen or a "dot" character.
	 */
	var emailRegex = /^(?=.{0,256}$)(?=[^@]{1,64}@)[\w!#$%&'*+\/=?^`{|}~-]+(?:\.[\w!#$%&'*+\/=?^`{|}~-]+)*@(?=[^@]{1,255}$)(?:[a-zA-Z\d](?:[a-zA-Z\d-]*[a-zA-Z\d])?\.)+[a-zA-Z\d](?:[a-zA-Z\d-]*[a-zA-Z\d])?$/;

	if (null == emailToValidate || !emailRegex.test(emailToValidate)) {
		return false;
	}
	return true;
}
Utils.IsValidDomain = function(domainToValidate) {
	/**
		* The following rules must be true for this to pass validation:
		* - No longer than 255 characters and no less than 1 character.
		* - Contains only the following characters: [a-z A-Z 0-9 - .] (no whitespace characters).
		* - Does not contain two or more "dots" (.) in a row.
		* - Does not start or end with a hyphen or "dot" character.
	  */
	var domainRegex = /^(?=[^@]{1,255}$)(?:[a-zA-Z\d](?:[a-zA-Z\d-]*[a-zA-Z\d])?\.)+[a-zA-Z\d](?:[a-zA-Z\d-]*[a-zA-Z\d])?$/;

	if (null == domainToValidate || !domainRegex.test(domainToValidate)) {
		return false;
	}
	return true;
}
Utils.CheckPassword = function(value)
{
    if (!value)
    {
        return { Score: 0, Complexity: 'No Password', Color: { R: 255, G: 0, B: 0} };
    }

    // Constants
    var MIN_PASSWORD_LENGTH = 8;
    var LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var KEYBOARD = ['01234567890', '!@#$%^&*()', 'QWERTYUIOP', 'ASDFGHJKL', 'ZXCVBNM'];

    var v_retval = {
        Score: 0,
        Complexity: '',
        Color: { R: 255, G: 0, B: 0 },

        // Additions
        NumberOfCharacters: { Count: value.length, Bonus: value.length * 4 },
        UpperCaseLetters: { Count: 0, Bonus: 0 },
        LowerCaseLetters: { Count: 0, Bonus: 0 },
        Numbers: { Count: 0, Bonus: 0 },
        Symbols: { Count: 0, Bonus: 0 },
        MiddleNumbersOrSymbols: { Count: 0, Bonus: 0 },
        Requirements: { Count: 0, Bonus: 0 },

        // Deductions
        LettersOnly: { Count: 0, Bonus: 0 },
        NumbersOnly: { Count: 0, Bonus: 0 },
        RepeatCharacters: { Count: 0, Bonus: 0 },
        ConsecutiveUpperCaseLetters: { Count: 0, Bonus: 0 },
        ConsecutiveLowerCaseLetters: { Count: 0, Bonus: 0 },
        ConsecutiveNumbers: { Count: 0, Bonus: 0 },
        SequentialLetters: { Count: 0, Bonus: 0 },
        SequentialKeyboard: { Count: 0, Bonus: 0 }
    };

    // Temp variables used in the process.
    var v_password_array = value.replace(/\s+/g, '').split(/\s*/);
    var v_repeat_character_increment = 0;
    var v_temp_alpha_uppercase_counter = -1;
    var v_temp_alpha_lowercase_counter = -1;
    var v_temp_number_counter = -1;

    // Loop through password to check for Symbol, Numeric, Lowercase and Uppercase pattern matches.
    for (var i = 0; i < v_password_array.length; i++)
    {
        if (v_password_array[i].match(/[A-Z]/g))
        {
            // The current character is an upper case letter.
            if (v_temp_alpha_uppercase_counter != -1 && v_temp_alpha_uppercase_counter + 1 == i)
                v_retval.ConsecutiveUpperCaseLetters.Count++;
            v_temp_alpha_uppercase_counter = i;
            v_retval.UpperCaseLetters.Count++;
        }
        else if (v_password_array[i].match(/[a-z]/g))
        {
            // The current character is a lower case letter.
            if (v_temp_alpha_lowercase_counter != -1 && v_temp_alpha_lowercase_counter + 1 == i)
                v_retval.ConsecutiveLowerCaseLetters.Count++;
            v_temp_alpha_lowercase_counter = i;
            v_retval.LowerCaseLetters.Count++;
        }
        else if (v_password_array[i].match(/[0-9]/g))
        {
            // The current character is a number.
            if (i > 0 && i < v_password_array.length - 1)
                v_retval.MiddleNumbersOrSymbols.Count++;
            if (v_temp_number_counter != -1 && v_temp_number_counter + 1 == i)
                v_retval.ConsecutiveNumbers.Count++;
            v_temp_number_counter = i;
            v_retval.Numbers.Count++;
        }
        else if (v_password_array[i].match(/[^a-zA-Z0-9_]/g))
        {
            // The current character is a symbol.
            if (i > 0 && i < v_password_array.length - 1)
                v_retval.MiddleNumbersOrSymbols.Count++;
            v_retval.Symbols.Count++;
        }

        // Internal loop through password to check for repeat characters.
        var v_repeat_char_exists = false;
        for (var j = 0; j < v_password_array.length; j++)
        {
            if (v_password_array[i] == v_password_array[j] && i != j)
            {
                // Repeat character exists.
                v_repeat_char_exists = true;
                // Calculate icrement deduction based on proximity to identical characters. Deduction is incremented each time a new
                // match is discovered. Deduction amount is based on total password length divided by the difference of distance between
                // currently selected match.
                v_repeat_character_increment += Math.abs(v_password_array.length / (j - i));
            }
        }
        if (v_repeat_char_exists)
        {
            v_retval.RepeatCharacters.Count++;
            var v_unique_char = v_password_array.length - v_retval.RepeatCharacters.Count;
            v_repeat_character_increment = Math.ceil(v_unique_char > 0 ? v_repeat_character_increment / v_unique_char : v_repeat_character_increment);
        }
    }

    // Check for sequential alpha string patterns (forward and reverse).
    var v_password_as_uppercase = value.toUpperCase();
    for (var i = 0; i < LETTERS.length - 2; i++)
    {
        var v_forward = LETTERS.substring(i, i + 3);
        if (v_password_as_uppercase.indexOf(v_forward) != -1 || v_password_as_uppercase.indexOf(v_forward.Reverse()) != -1)
            v_retval.SequentialLetters.Count++;
    }

    // Check for sequential keyboard string patterns (forward and reverse).
    for (var i = 0; i < KEYBOARD.length; i++)
    {
        for (var j = 0; j < KEYBOARD[i].length - 2; j++)
        {
            var v_forward = KEYBOARD[i].substring(j, j + 3);
            if (v_password_as_uppercase.indexOf(v_forward) != -1 || v_password_as_uppercase.indexOf(v_forward.Reverse()) != -1)
                v_retval.SequentialKeyboard.Count++;
        }
    }

    // General point assignment.

    // Upper case letters (but not all upper case letters).
    if (v_retval.UpperCaseLetters.Count > 0 && v_retval.UpperCaseLetters.Count < value.length)
        v_retval.UpperCaseLetters.Bonus = (value.length - v_retval.UpperCaseLetters.Count) * 2;

    // Lower case letters (but not all lower case letters).
    if (v_retval.LowerCaseLetters.Count > 0 && v_retval.LowerCaseLetters.Count < value.length)
        v_retval.LowerCaseLetters.Bonus = (value.length - v_retval.LowerCaseLetters.Count) * 2;

    // Numbers (but not all numbers).
    if (v_retval.Numbers.Count > 0 && v_retval.Numbers.Count < value.length)
        v_retval.Numbers.Bonus = v_retval.Numbers.Count * 4;

    // Symbols (but not all symbols).
    if (v_retval.Symbols.Count > 0)
        v_retval.Symbols.Bonus = v_retval.Symbols.Count * 6;

    // Number of numerical and symbolic characters in the middle of the password.
    if (v_retval.MiddleNumbersOrSymbols.Count > 0)
        v_retval.MiddleNumbersOrSymbols.Bonus = v_retval.MiddleNumbersOrSymbols.Count * 2;

    // Point deductions for poor practices.

    // Only Letters.
    if ((v_retval.LowerCaseLetters.Count > 0 || v_retval.UpperCaseLetters.Count > 0) && v_retval.Numbers.Count == 0 && v_retval.Symbols.Count == 0)
        v_retval.LettersOnly = { Count: value.length, Bonus: -value.length };

    // Only Numbers.
    if (v_retval.LowerCaseLetters.Count == 0 && v_retval.UpperCaseLetters.Count == 0 && v_retval.Symbols.Count == 0 && v_retval.Numbers.Count > 0)
        v_retval.NumbersOnly = { Count: value.length, Bonus: -value.length };

    // Same character exists more than once.
    if (v_retval.RepeatCharacters.Count > 0)
        v_retval.RepeatCharacters.Bonus = -v_retval.RepeatCharacters.Count;

    if (v_retval.ConsecutiveUpperCaseLetters.Count > 0) // Consecutive Uppercase Letters exist.
        v_retval.ConsecutiveUpperCaseLetters.Bonus = -v_retval.ConsecutiveUpperCaseLetters.Count * 2;

    // Consecutive Lowercase Letters exist.
    if (v_retval.ConsecutiveLowerCaseLetters.Count > 0)
        v_retval.ConsecutiveLowerCaseLetters.Bonus = -v_retval.ConsecutiveLowerCaseLetters.Count * 2;

    // Consecutive Numbers exist.
    if (v_retval.ConsecutiveNumbers.Count > 0)
        v_retval.ConsecutiveNumbers.Bonus = -v_retval.ConsecutiveNumbers.Count * 2;

    // Sequential alpha strings exist (3 characters or more).
    if (v_retval.SequentialLetters.Count > 0)
        v_retval.SequentialLetters.Bonus = -v_retval.SequentialLetters.Count * 3;

    // Sequential keyboard strings exist (3 characters or more).
    if (v_retval.SequentialKeyboard.Count > 0)
        v_retval.SequentialKeyboard.Bonus = -v_retval.SequentialKeyboard.Count * 3;

    // Determine if mandatory requirements have been met.

    // Minimum number of characters requirement.
    if (v_retval.NumberOfCharacters.Count >= MIN_PASSWORD_LENGTH)
        v_retval.Requirements.Count++;

    // Has at least one upper case letter requirement.
    if (v_retval.UpperCaseLetters.Count > 0)
        v_retval.Requirements.Count++;

    // Has at least one lower case letter requirement.
    if (v_retval.LowerCaseLetters.Count > 0)
        v_retval.Requirements.Count++;

    // Has at least one number requirement.
    if (v_retval.Numbers.Count > 0)
        v_retval.Requirements.Count++;

    // Has at least one symbol requirement.
    if (v_retval.Symbols.Count > 0)
        v_retval.Requirements.Count++;

    v_retval.Requirements.Bonus = v_retval.Requirements.Count * 2;

    // Calculate the final score.
    for (var item in v_retval)
    {
        if (typeof v_retval[item] != 'function' && item != 'Score' && item != 'Complexity' && v_retval[item].Bonus)
            v_retval.Score += v_retval[item].Bonus;
    }

    // Make sure the score is a value between 0 and 100.
    if (v_retval.Score > 100)
        v_retval.Score = 100;
    else if (v_retval.Score < 0)
        v_retval.Score = 0;

    // Determine complexity based on overall score.
    if (v_retval.Score < 20)
        v_retval.Complexity = 'Very Weak';
    else if (v_retval.Score >= 20 && v_retval.Score < 40)
        v_retval.Complexity = 'Weak';
    else if (v_retval.Score >= 40 && v_retval.Score < 60)
        v_retval.Complexity = 'Good';
    else if (v_retval.Score >= 60 && v_retval.Score < 80)
        v_retval.Complexity = 'Strong';
    else if (v_retval.Score >= 80)
        v_retval.Complexity = 'Very Strong';

    // Figure out the RGB color associated with the strength of the password.

    // Red.
    if (v_retval.Score == 0)
        v_retval.Color = { R: 255, G: 0, B: 0 };

    // Yellow.
    else if (v_retval.Score == 50)
        v_retval.Color = { R: 255, G: 255, B: 0 };

    // Green.
    else if (v_retval.Score == 100)
        v_retval.Color = { R: 0, G: 255, B: 0 };

    // Some shade between red and yellow.
    else if (v_retval.Score < 50)
        v_retval.Color = { R: 255, G: Math.ceil((v_retval.Score * 2 * 255) / 100), B: 0 };

    // Some shade between yellow and green.
    else
        v_retval.Color = { R: 255 - Math.ceil((v_retval.Score * 255) / 100), G: 255, B: 0 };

    return v_retval;
}
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;
}
// This method is depreicated, since using it makes debuging the javascript more difficult.
Utils.GetElement = function(p_elementId)
{
	if(p_elementId == null || p_elementId.length <= 0) { throw new Error('p_elementId is null!'); 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.GetEventTarget = function(e)
{
    var v_target;
    if (!e)
    {
        var e = window.event;
    }
    if (e.target) // All browsers but IE
    {
        v_target = e.target;
    }
    else if (e.srcElement) // IE
    {
        v_target = e.srcElement;
    }
    if (v_target.nodeType == 3) // Safari bug work around
    {
        v_target = v_target.parentNode;
    }
    return v_target;
}
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.RenderSelect = function(attr, optionsArrayOrLength, addOne, getValue)
{
    var html = '<select';
    if (attr)
    {
        for (var a in attr)
        {
            if (typeof attr[a] != 'function')
                html += ' ' + a + '="' + attr[a] + '"';
        }
    }
    html += '>';
    if (TypeOf(optionsArrayOrLength) == 'Number')
    {
        for (var i = 0; i < optionsArrayOrLength; i++)
        {
            var v = i + (addOne ? 1 : 0);
            html += '<option value="' + v + '">' + (typeof getValue == 'function' ? getValue(v) : v) + '<\/option>';
        }
    }
    else if (TypeOf(optionsArrayOrLength) == 'Array')
    {
        for (var i = 0; i < optionsArrayOrLength.length; i++)
            html += '<option value="' + (i + (addOne ? 1 : 0)) + '">' + optionsArrayOrLength[i] + '<\/option>';
    }
    else
    {
        for (var o in optionsArrayOrLength)
        {
            if (typeof optionsArrayOrLength[o] != 'function')
                html += '<option value="' + o + '">' + optionsArrayOrLength[o] + '<\/option>';
        }
    }
    return html + '<\/select>';
}
Utils.SetAttributes = function(idsOrElements, attr)
{
    if (TypeOf(idsOrElements) != 'Array')
        idsOrElements = [idsOrElements];

    for (var i = 0; i < idsOrElements.length; i++)
    {
        var e = TypeOf(idsOrElements[i]) == 'String' ? $(idsOrElements[i]) : idsOrElements[i];
        if (e != null)
        {
            for (var a in attr)
            {
                if (typeof attr[a] != 'function')
                    e[a] = attr[a];
            }
        }
    }
}
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) { 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;
}
Utils.ParseFormToQuery = function(p_htmlElement, p_queryObj, p_skipNamesArray)
{
    if (TypeOf(p_skipNamesArray) != 'Array') { p_skipNamesArray = null; }
    for (var i = 0; i < p_htmlElement.childNodes.length; i++)
    {
        var v_element = p_htmlElement.childNodes[i];
        if (v_element.tagName == 'INPUT')
        {
            if (v_element.name.length <= 0 || Utils.__CheckSkipNames(p_skipNamesArray, v_element.name)) { continue; }
            if ((v_element.type == 'text' || v_element.type == 'hidden' || v_element.type == 'password') && v_element.value.length > 0) { p_queryObj.Add(v_element.name, v_element.value, true); }
            else if (v_element.type == 'checkbox') { if (v_element.checked) { p_queryObj.Add(v_element.name, v_element.value, false); } }
            else if (v_element.type == 'radio') { if (v_element.checked) { p_queryObj.Add(v_element.name, v_element.value, true); } }
        }
        else if (v_element.tagName == 'SELECT')
        {
            if (v_element.name.length <= 0 || Utils.__CheckSkipNames(p_skipNamesArray, v_element.name)) { continue; }
            if (v_element.multiple)
            {
                for (var j = 0; j < v_element.options.length; j++)
                {
                    if (v_element.options[j].selected) { p_queryObj.Add(v_element.name, v_element.options[j].value, false); }
                }
            }
            else if (v_element.selectedIndex > -1) { p_queryObj.Add(v_element.name, v_element.options[v_element.selectedIndex].value, true); }
        }
        else if (v_element.tagName == 'TEXTAREA' && v_element.value.length > 0)
        {
            if (v_element.name.length <= 0 || Utils.__CheckSkipNames(p_skipNamesArray, v_element.name)) { continue; }
            p_queryObj.Add(v_element.name, v_element.value, true);
        }
        else { Utils.ParseFormToQuery(v_element, p_queryObj, p_skipNamesArray); }
    }
    return;
}
Utils.AddEnterKeyEvent = function(p_elementId, p_eventCallback)
{
    var v_element = $(p_elementId);
    if (v_element == null || p_eventCallback == null)
    {
        return;
    }
    Utils.AddListener(v_element, "keypress", function(p_event) { if (Utils.GetKeyCode(p_event) == 13 && p_eventCallback) { p_eventCallback(p_event); } return; }, false);
}
Utils.CalcHourPart = function(totalMinutes)
{
    return (Utils.GetIntValue(totalMinutes) / 60).Format('0');
}
Utils.CalcMinutePart = function(totalMinutes)
{
    return Utils.GetIntValue(totalMinutes) % 60;
}
Utils.__CheckSkipNames = function(p_skipNamesArray, p_elementName)
{
    if(p_skipNamesArray != null)
    {
        for(var i = 0; i < p_skipNamesArray.length; i++)
        {
            if(p_skipNamesArray[i] == p_elementName) { return true; }
        }
    }
    return false;
}

Xml = {};
Xml._GetXmlHttpObject = function()
{
	if(typeof(ActiveXObject) != 'undefined')
	{
		return new ActiveXObject('Microsoft.XMLHTTP');
	}
	else if(typeof(XMLHttpRequest) != 'undefined')
	{
		var v_xmlhttp = new XMLHttpRequest();
		// Some versions of Mozilla do not support the readyState property and the onreadystate event so we patch it!
		if(v_xmlhttp.readyState == null)
		{
			v_xmlhttp.readyState = 1;
			v_xmlhttp.addEventListener("load", function() { v_xmlhttp.readyState = 4; if(typeof(v_xmlhttp.onreadystatechange) == "function") { v_xmlhttp.onreadystatechange(); } return; }, false);
		}
		return v_xmlhttp;
	}
	alert('Your browser does not fully support the technology used on this page. Some features may not work the way they were intended to.');
	return null;
}
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') && !Utils.IsKhtml) // 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 = Xml._GetXmlHttpObject();
	    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 = Xml._GetXmlHttpObject();
		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.AppendFormat = function() { return this.Append(String.Format(arguments)); }
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, p_isObject) { QueryString.baseConstructor.call(this); this.Load(p_string, true, p_isObject); 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, p_isObject)
{
    if (TypeOf(p_overwrite) != 'Boolean') { p_overwrite = true; }
    if (p_isObject || TypeOf(p_string) == 'Object')
    { // Handle JSON object parsing.
        for (var v_key in p_string)
        {
            if (typeof (p_string[v_key]) != 'function')
            {
                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, p_isObject) { var v_qs = new QueryString(); v_qs.Load(p_string, true, p_isObject); return v_qs; }
QueryString.Create = function(p_variableObject)
{
	var v_qs = new QueryString();
	for (var v_key in p_variableObject)
	{
	    if (typeof (p_variableObject[v_key]) != 'function')
	    {
	        v_qs.Add(v_key, p_variableObject[v_key], true);
	    }
	}
	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.Join = function(separator, format)
{
    if (TypeOf(format) != 'String' || format.length <= 0)
    {
        return this.join(separator);
    }
    else if (this.length <= 0)
    {
        return '';
    }
    var v_retval = new StringBuilder();
    for (var i = 0; i < this.length; i++)
    {
        if (i > 0)
        {
            v_retval.Append(separator);
        }
        v_retval.Append(this[i].ToString(format));
    }
    return v_retval.ToString();
}
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.prototype.Filter = function(p_function)
{
    var len = this.length;
    if (typeof(p_function) != 'function') { throw new Error('p_function must be a function!'); return null; }
    var v_retval = new Array();
    for (var i = 0; i < len; i++)
    {
        if (i in this)
        {
            var v_value = this[i]; // in case p_function mutates this
            if (p_function(v_value, i, this)) { v_retval.push(v_value); }
        }
    }
    return v_retval;
}
Array.prototype.Clean = function()
{
    function p_function(p_element, p_index, p_array) { return (p_element != null && TypeOf(p_element) != 'Undefined'); }
    return this.Filter(p_function);
}
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(format) { if(format != undefined) { return this.Format(format); } return this.toString(); }
Date.prototype.Equals = function(obj) { return this.getTime() == obj.getTime(); }
Date.prototype.CompareTo = function(date) { return Date.Compare(this, date); }
Date.prototype.AddYears = function(value) { this.setFullYear(this.getFullYear() + value); return; }
Date.prototype.AddMonths = function(value) { this.setMonth(this.getMonth() + value); return; }
Date.prototype.AddDays = function(value) { this.setDate(this.getDate() + value); return; }
Date.prototype.AddHours = function(value) { this.setHours(this.getHours() + value); return; }
Date.prototype.AddMinutes = function(value) { this.setMinutes(this.getMinutes() + value); return; }
Date.prototype.AddSeconds = function(value) { this.setSeconds(this.getSeconds() + value); return; }
Date.prototype.AddMilliseconds = function(value) { this.setMilliseconds(this.getMilliseconds() + 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(date) { return this.getTime() < date.getTime(); }
Date.prototype.IsGreaterThan = function(date) { return this.getTime() > date.getTime(); }
Date.prototype.IsLessThanOrEqualTo = function(date) { return this.getTime() <= date.getTime(); }
Date.prototype.IsGreaterThanOrEqualTo = function(date) { return this.getTime() >= date.getTime(); }
Date.prototype.Format = function(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 && (format.indexOf('hhh') >= 0 || format.indexOf('HHH') >= 0))
	{
		format = format.replace('f', '');
		format = format.replace('F', '');
		format = format.replace('s', '');
		format = format.replace('m', '');
		format = format.replace('T', '');
		format = format.replace('t', '');
		format = format.replace(':', '');
	}
	while(i < format.length)
	{
		v_char = format.charAt(i);
		v_token = '';
		if(!v_in_html && v_char == '<') { v_in_html = true; }
		if(!v_in_html)
		{
			while((format.charAt(i) == v_char) && (i < format.length)) { v_token += 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.prototype.UTCAddYears = function(value) { this.setUTCFullYear(this.getUTCFullYear() + value); return; }
Date.prototype.UTCAddMonths = function(value) { this.setUTCMonth(this.getUTCMonth() + value); return; }
Date.prototype.UTCAddDays = function(value) { this.setUTCDate(this.getUTCDate() + value); return; }
Date.prototype.UTCAddHours = function(value) { this.setUTCHours(this.getUTCHours() + value); return; }
Date.prototype.UTCAddMinutes = function(value) { this.setUTCMinutes(this.getUTCMinutes() + value); return; }
Date.prototype.UTCAddSeconds = function(value) { this.setUTCSeconds(this.getUTCSeconds() + value); return; }
Date.prototype.UTCAddMilliseconds = function(value) { this.setUTCMilliseconds(this.getUTCMilliseconds() + value); return; }
Date.prototype.UTCDateValue = function() { var v_date = this.UTCClone(); v_date.setUTCHours(0, 0, 0, 0); return v_date; }
Date.prototype.UTCTimeValue = function() { var v_date = this.UTCClone(); v_date.setUTCFullYear(1970, 0, 1); return v_date; }
Date.prototype.UTCClone = function() { return new Date(this.getUTCFullYear(), this.getUTCMonth(), this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds(), this.getUTCMilliseconds()); }
Date.prototype.UTCFormat = function(format) { return this.UTCClone().Format(format); }

Date.Compare = function(date1, date2) { return date1.IsLessThan(date2) ? -1 : (date1.Equals(date2) ? 0 : 1); }
Date.Today = function() { var v_date = new Date(); v_date.setHours(0, 0, 0, 0); return v_date; }
Date.UTCToday = function() { var v_date = new Date(); v_date.setUTCHours(0, 0, 0, 0); return v_date; }
Date.Now = function() { return new Date(); }
Date.DaysInMonths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
Date.LongMonthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
Date.ShortMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Date.LongWeekDayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
Date.ShortWeekDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
Date.WeekDayLetters = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
Date.IsLeapYear = function(year) { if(year % 400 == 0) { return true; } else if(year % 100 == 0) { return false; } else if(year % 4 == 0) { return true; } return false; }
Date.DaysInMonth = function(year, month) { if(month > 11 || month < 0) { throw new Error('month is an invalid value.'); return 0; } if(month == 1) { return Date.IsLeapYear(year) ? 29 : 28; } return Date.DaysInMonths[month]; }
Date.LongMonthName = function(month) { if(month > 11 || month < 0) { throw new Error('month is an invalid value.'); return 'Invalid month'; } return Date.LongMonthNames[month]; }
Date.ShortMonthName = function(month) { if(month > 11 || month < 0) { throw new Error('month is an invalid value.'); return 'Invalid month'; } return Date.ShortMonthNames[month]; }
Date.LongWeekDayName = function(weekday) { if(weekday > 6 || weekday < 0) { throw new Error('weekday is an invalid value.'); return 'Invalid weekday'; } return Date.LongWeekDayNames[weekday]; }
Date.ShortWeekDayName = function(weekday) { if(weekday > 6 || weekday < 0) { throw new Error('weekday is an invalid value.'); return 'Invalid weekday'; } return Date.ShortWeekDayNames[weekday]; }
Date.WeekDayLetter = function(weekday) { if(weekday > 6 || weekday < 0) { throw new Error('weekday is an invalid value.'); return 'Invalid weekday'; } return Date.WeekDayLetters[weekday]; }
Date.DateDiff = function(part, date1, date2)
{
	var v_d1_ms = date1.getTime();
	var v_d2_ms = date2.getTime();
	var v_diff_in_ms = v_d1_ms - v_d2_ms;
	switch(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 new Error('Week of year is not supported yet.'); return 0; /* Week of year */
		case 'w': throw new Error('Weekdays are not supported yet.'); return 0; /* Weekday */
		case 'y': throw new Error('Day of year is not supported yet.'); return 0; /* Day of year */
		case 'm': throw new Error('Months are not supported yet.'); return 0; /* Month */
		case 'q': throw new Error('Quarters are not supported yet.'); return 0; /* Quarter */
		case 'yyyy': throw new Error('Years are not supported yet.'); return 0; /* Years */
		default: throw new Error('part is not a regonized token.'); return 0;
	}
}
Date.IsoWeekNumber = function(date)
{
	var v_date = 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(year, month, day)
{
	if(month == 0) { return day; }
	for(var i = 0; i < month; i++)
	{
		if(i == 1 && Date.IsLeapYear(year)) { day += 29; }
		else { day += Date.DaysInMonths[i]; }
	}
	return day;
}
Date.IsDate = function(value) { return !isNaN(Date.parse(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(p_format) { if(p_format != undefined) { return this.Format(p_format); } 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, separator)
{
    separator = TypeOf(separator) == 'String' && separator.length > 0 ? separator : '.';
    var v_str_this = this.toString();
    var v_int_part = parseInt(this).toString();
    var v_dec_part = v_str_this.indexOf(separator) > 0 ? v_str_this.split(separator)[1] : '0';

    var v_int_string = '';
    var v_dec_string = '';

    var v_parts = p_formatString.split(separator);
    var v_fs_array = v_parts[0].split('').reverse();
    var v_ip_array = v_int_part.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; }

    // 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.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; }
        return v_int_string + separator + 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 ** //
// -- WARNING: The following 4 lines are incompatible with some open source libraries, notably jquery and TinyMCE.
//Object.prototype.ToString = function() { return Object.ToString(this); }
//Object.prototype.toString = function() { return Object.ToString(this); }
//Object.prototype.GetHashCode = function() { return Object.GetHashCode(this); }
//Object.prototype.SetValue = function(value) { return Object.SetValue(this, value); }
// -- End warning.
Object.SetValue = function(obj, value)
{
    /// <summary modifiers="public">Sets the value of the current <see cref="Object"/>.</summary>
    /// <param name="value" optional="false">The value to set the <see cref="Object"/> to.</param>
    if (obj.tagName == 'INPUT' || obj.tagName == 'TEXTAREA')
    {
        /* If we have an textarea tag or an input tag that is not a checkbox or radio button set the value property. */
        if (obj.tagName == 'TEXTAREA' || (obj.type != 'checkbox' && obj.type != 'radio'))
        {
            obj.value = value;
        }
        /* For checkboxes and radio buttons check the input if the value property equals our passed value. */
        else if (obj.type == 'checkbox' || obj.type == 'radio')
        {
            if (TypeOf(value) == 'Boolean')
            {
                obj.checked = value;
            }
            else
            {
                obj.checked = (obj.value == value);
            }
        }
    }
    else if (obj.tagName == 'SELECT')
    {
        /* For select tags cycle through each option and select it if its value equals our passed value.
         * Only select the first one unless the select allows multiple selections. Be sure to unselect 
         * all other options since that is not the value we want set anymore.
         */
        var hasSelection = false;
        for (var i = 0; i < obj.options.length; i++)
        {
            if (obj.options[i].value == value)
            {
                obj.options[i].selected = (!hasSelection || obj.multiple);
                hasSelection = true;
            }
            else
            {
                obj.options[i].selected = false;
            }
        }
    }
    else
    {
        /* Otherwise just set the innerHTML of the element. */
        obj.innerHTML = value;
    }
}
Object.Compare = function(objLeft, objRight)
{
	if(objLeft == null || objLeft == undefined)
	{
	    return 1;
	}
	if(objRight == null || objRight == undefined)
	{
	    return -1;
	}
	try
	{
	    return objLeft.CompareTo(objRight);
	}
	catch(e)
	{
	    throw new Error('CompareTo is not defined on type: ' + TypeOf(objLeft) + '.');
	}
	return 0;
}
Object.Equals = function(objLeft, objRight)
{
	try
	{
	    return objLeft.Equals(objRight);
	}
	catch(e)
	{
	    return objLeft === objRight;
	}
	return false;
}
Object.ToString = function(obj)
{
	var v_string = new StringBuilder();
	Object._ToStringRecursive(v_string, obj, '', true);
	return v_string.ToString();
}
Object._ToStringRecursive = function(builder, obj, indent, isFirst)
{
    if (obj == null)
    {
        return 'null';
    }
    if (obj == undefined)
    {
        return 'undefined';
    }
    if (typeof (obj) == 'function')
    {
        return '';
    }

    if (isFirst || typeof (obj.ToString) != 'function')
    {
        builder.Append('[Object: ').Append(TypeOf(obj)).Append(']\n').Append(indent).Append('(\n');
        for (var v_name in obj)
        {
            var v_obj = obj[v_name];
            if (typeof (v_obj) != 'function')
            {
                builder.Append(indent).Append('    ').Append(v_name).Append(' (').Append(TypeOf(v_obj)).Append(') -> ').Append(Object._ToStringRecursive(builder, v_obj, indent + '    ', false)).Append('\n');
            }
        }
        builder.Append(indent).Append(')');
    }
    else
    {
        builder.Append(obj.ToString().replace(/\n/g, '\n' + indent));
    }
    return;
}
Object.GetHashCode = function(obj)
{
    if (obj == undefined || obj == null || typeof (obj) == 'function')
    {
        return '';
    }
    if (typeof (obj.GetHashCode) == 'function')
    {
        return obj.GetHashCode().toString();
    }
    else
    {
        var v_flag = false;
        var v_hash = new StringBuilder();
        for (var v_name in obj)
        {
            var v_obj = obj[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.prototype.Count = function(p_subString)
{
    var v_count = 0;
    for (var i = 0; i < this.length; i++)
    {
        if (p_subString == this.substr(i, p_subString.length))
        {
            v_count++;
        }
    }
    return v_count;
}
String.prototype.Replicate = function(p_count)
{
    if (TypeOf(p_count) != 'Number' || p_count < 1) { p_count = 1; }
    var v_retval = new StringBuilder();
    for (var i = 0; i < p_count; i++) { v_retval.Append(this); }
    return v_retval.ToString();
}
String.prototype.StartsWith = function(p_string)
{
    if (TypeOf(p_string) != 'String' || p_string.length <= 0)
    {
        throw new Error('p_string is not a string or is empty.');
    }
    return this.substr(0, p_string.length) == p_string;
}
String.prototype.EndsWith = function(p_string)
{
    if (TypeOf(p_string) != 'String' || p_string.length <= 0)
    {
        throw new Error('p_string is not a string or is empty.');
    }
    return this.substr(p_string.length - 1) == p_string;
}
String.IsNullOrEmpty = function(p_string)
{
    return TypeOf(p_string) != 'String' || p_string.length <= 0;
}
String.IsAllNullOrEmpty = function()
{
    if (arguments && arguments.length > 0)
    {
        for (var i = 0; i < arguments.length; i++)
        {
            if (!String.IsNullOrEmpty(arguments[i]))
            {
                return false;
            }
        }
    }
    return true;
}
String.CompositeFormattingRegExp = null;
String.Format = function()
{
    if (String.CompositeFormattingRegExp == null)
    {
        String.CompositeFormattingRegExp = new RegExp(/{\d+}|{\d+:[^\r\n{}]+}/);
    }
    var v_result = arguments[0];
    var v_regexp_result = null;
    while ((v_regexp_result = String.CompositeFormattingRegExp.exec(v_result)) != null)
    {
        v_regexp_result = v_regexp_result.toString();
        var v_colons_position = v_regexp_result.indexOf(":");
        var v_param_index = new Number(v_regexp_result.substr(1, v_colons_position - 1));
        var v_param_format = v_regexp_result.substr(v_colons_position + 1, v_regexp_result.length - 2 - v_colons_position);
        var v_obj = arguments[v_param_index + 1];
        v_result = v_result.replace(v_regexp_result, typeof(v_obj.ToString) == 'function' ? v_obj.ToString(v_param_format) : v_obj.toString());
    }
    return v_result;
}
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();
}