String.format = function(format, args) {
    var index = 0;
    var result = [];
    while (index < format.length) {
        var open = format.indexOf('{', index);
        var close = format.indexOf('}', index);
        if ((open == -1) && (close == -1)) {
            result.push(format.slice(index));
            break;
        }
        if ((close > 0) && ((close < open) || (open == -1))) {
            if (format.charAt(close + 1) != '}') {
                throw new Error("Input string was not in a correct format.");
            }
            result.push(format.slice(index, close + 1));
            index = close + 2;
            continue;
        }
        result.push(format.slice(index, open));
        index = open + 1;
        if (format.charAt(index) == '{') {
            result.push("{");
            index++;
            continue;
        }
        if (close == -1) {
            throw new Error("Input string was not in a correct format.");
        }
        var num = parseInt(format.substring(index, close), 10);
        if (isNaN(num)) {
            throw new Error("Input string was not in a correct format.");
        }
        var arg = args[num];
        result.push((!arg) ? "" : arg.toString());
        index = close + 1;
    }
    return result.join("");
};
String.prototype.endsWith = function(value) {
    if (this.length && !value.length) {
        return false;
    }
    return (this.substring(this.length - value.length) == value);
};
String.prototype.insert = function(startIndex, value) {
    return (this.substring(0, startIndex) + value + this.substring(startIndex));
};
String.prototype.remove = function(startIndex, length) {
    var value = this.substring(0, startIndex);
    if (typeof length != "number") {
        return value;
    }
    return (value + this.substring(startIndex + length));
};
String.prototype.startsWith = function(value) {
    if (this.length && !value.length) {
        return false;
    }
    return (this.substring(0, value.length) == value);
};
String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, "");
};
String.prototype.trimEnd = function() {
    return this.replace(/\s+$/, "");
};
String.prototype.trimStart = function() {
    return this.replace(/^\s+/, "");
};
Number.parse = function(value, startIndex) {
    if (!value || (value.length <= startIndex)) {
        return 0;
    }
    var str = "";
    for (var num = startIndex; num < value.length; num++) {
        var charCode = value.charCodeAt(num);
        if ((charCode < 48) || (charCode > 57)) {
            break;
        }
        str += value.charAt(num);
    }
    if (!str.length) {
        return 0;
    }
    return parseInt(str, 10);
};
Array.prototype.contains = function(value) {
    return (this.indexOf(value) != -1);
};
Array.prototype.indexOf = function(value, startIndex, length) {
    if (value === undefined) {
        return -1;
    }
    if (typeof startIndex != "number") {
        startIndex = 0;
    }
    if (typeof length != "number") {
        length = this.length;
    } else {
        length = startIndex + length;
    }
    for (var num = startIndex; num < length; num++) {
        if (this[num] == value) {
            return num;
        }
    }
    return -1;
};
window.decodeHTML = function(value) {
    if ((value === undefined) || (value === null)) {
        return null;
    }
    var escape = { "&quot;": "\"", "&lt;": "<", "&gt;": ">", "&amp;": "&" };
    return value.replace(/&quot;|&amp;|&lt;|&gt;|&#\d{3};/g, function(match) { var code = escape[match]; if (code) { return code; } return String.fromCharCode(parseInt(match.substring(2, 5), 10)); });
};
window.encodeHTML = function(value) {
    if ((value === undefined) || (value === null)) {
        return null;
    }
    var escape = { "\"": "&quot;", "<": "&lt;", ">": "&gt;", "&": "&amp;" };
    return value.replace(new RegExp("[\\xa0-\\xff\"<>&]", "g"), function(match) { var code = escape[match]; if (code) { return code; } return "&#" + match.charCodeAt() + ";"; });
};
window.encodeURI = function(value) {
    if ((value === undefined) || (value === null)) {
        return null;
    }
    if (encodeURIComponent) {
        return encodeURIComponent(value);
    }
    return escape(value);
};
window.decodeURI = function(value) {
    if ((value === undefined) || (value === null)) {
        return null;
    }
    if (decodeURIComponent) {
        return decodeURIComponent(value.replace(/\+/g, "%20"));
    }
    return unescape(value.replace(/\+/g, "%20"));
};
window.serializeObject = function(value) {
    if ((value === undefined) || (value === null)) {
        return "null";
    }
    var ctor = value.constructor;
    if (ctor == Number) {
        return isFinite(value) ? value.toString() : "null";
    } else if (ctor == Boolean) {
        return value.toString();
    } else if (ctor == String) {
        var escape = { "\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f", "\r": "\\r", "\"": "\\\"", "\\": "\\\\" };
        return ("\"" + value.replace(new RegExp("([\\x00-\\x1f\\\\\"])", "g"), function(match) { var code = escape[match]; if (code) { return code; } code = match.charCodeAt(); return "\\u00" + Math.floor(code / 16).toString(16) + (code % 16).toString(16); }) + "\"");
    } else if (ctor == Array) {
        var array = [];
        for (var num = 0; num < value.length; num++) {
            array.push(window.serializeObject(value[num]));
        }
        return "[" + array.join(", ") + "]";
    }
    if (typeof value.toJSON == "function") {
        return value.toJSON();
    }
    if (typeof value == "object") {
        var array = [];
        for (var attr in value) {
            if (typeof value[attr] != "function") {
                array.push("\"" + attr + "\":" + window.serializeObject(value[attr]));
            }
        }
        return "{" + array.join(", ") + "}";
    }
    return value.toString();
};
window.createXMLHttpRequest = function() {
    try {
        return new XMLHttpRequest();
    } catch (e) { }
    try {
        return new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) { }
    return null;
};
window.browser = {
    version: (/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/i.exec(navigator.userAgent)[1]),
    safari: (/webkit/i.test(navigator.userAgent)),
    opera: (/opera/i.test(navigator.userAgent)),
    msie: (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)),
    mozilla: (/mozilla/i.test(navigator.userAgent) && !/(compatible|webkit)/i.test(navigator.userAgent))
};
function EventHandler(object, method) {
    this.object = object;
    this.method = method;
}
EventHandler.prototype.invoke = function(sender, e) {
    if (typeof this.method == "function") {
        if (this.object) {
            this.method.call(this.object, sender, e);
        } else {
            this.method(sender, e);
        }
    } else if (this.object[this.method] !== undefined) {
        this.object[this.method](sender, e);
    } else {
        throw new Error("No method found with name \"" + this.method + "\".");
    }
};
function EventArgs(event, attr) {
    this.type = event.type;
    if (event.target) {
        this.target = event.target;
    } else {
        this.target = event.srcElement;
    }
    this.button = 0;
    this.altKey = event.altKey;
    this.ctrlKey = event.ctrlKey;
    this.shiftKey = event.shiftKey;
    this.keyCode = (event.charCode || event.keyCode);
    if (!window.browser.msie) {
        this.pageX = event.pageX;
        this.pageY = event.pageY;
    } else {
        this.pageX = (event.clientX + (document.documentElement ? document.documentElement.scrollLeft : document.body.scrollLeft));
        this.pageY = (event.clientY + (document.documentElement ? document.documentElement.scrollTop : document.body.scrollTop));
    }
    if (event.button !== undefined) {
        if ((event.which !== undefined) || (event.button == 2)) {
            this.button = event.button;
        } else if (event.button == 4) {
            this.button = 1;
        }
    }
    this.source = event;
    if (attr !== undefined) {
        for (var name in attr) {
            this[name] = attr[name];
        }
    }
}
EventArgs.prototype.preventDefault = function() {
    if (window.browser.msie) {
        this.source.returnValue = false;
    } else {
        this.source.preventDefault();
    }
};
EventArgs.prototype.stopPropagation = function() {
    if (window.browser.msie) {
        this.source.cancelBubble = true;
    } else {
        this.source.stopPropagation();
    }
};
function EventHandlerList() {
    this.handlers = {};
}
EventHandlerList.prototype.contains = function(key) {
    return (this.handlers[key] !== undefined && this.handlers[key] !== null);
};
EventHandlerList.prototype.add = function(key, element, type, target, argument) {
    if (this.contains(key)) {
        throw new Error("Key \"" + key + "\" has already been registered.");
    }
    var method = function(event) {
        if (!event && window.browser.msie) {
            var owner = element.ownerDocument || element.document || element;
            event = (owner.defaultView || owner.parentWindow).event;
        }
        target.invoke(element, new EventArgs(event, { name: key, argument: (argument || {}) }));
    };
    var handler = { element: element, type: type, method: method };
    if (element.addEventListener) {
        element.addEventListener(type, method, false);
    } else {
        element.attachEvent("on" + type, method);
    }
    this.handlers[key] = handler;
};
EventHandlerList.prototype.remove = function(key) {
    if (this.contains(key)) {
        var handler = this.handlers[key];
        if (handler.element.removeEventListener) {
            handler.element.removeEventListener(handler.type, handler.method, false);
        } else {
            handler.element.detachEvent("on" + handler.type, handler.method);
        }
        delete this.handlers[key];
    }
};
EventHandlerList.prototype.dispose = function() {
    for (var key in this.handlers) {
        this.remove(key);
    }
};
function TimerHandlerList() {
    this.handlers = {};
}
TimerHandlerList.prototype.contains = function(key) {
    return (this.handlers[key] !== undefined && this.handlers[key] !== null);
};
TimerHandlerList.prototype.add = function(key, interval, target, argument) {
    if (this.contains(key)) {
        throw new Error("Key \"" + key + "\" has already been registered.");
    }
    this.handlers[key] = { interval: interval, method: function() { target.invoke(target.object, { name: key, argument: (argument || {}) }); } };
};
TimerHandlerList.prototype.remove = function(key) {
    if (this.contains(key)) {
        this.stop(key);
        delete this.handlers[key];
    }
};
TimerHandlerList.prototype.start = function(key) {
    if (!this.contains(key)) {
        throw new Error("Key \"" + key + "\" was not found.");
    }
    var handler = this.handlers[key];
    if (handler.timer) {
        this.stop(key);
    }
    if (handler.interval < 10) {
        handler.interval = 10;
    }
    handler.timer = window.setInterval(handler.method, handler.interval);
};
TimerHandlerList.prototype.stop = function(key) {
    if (this.contains(key)) {
        var handler = this.handlers[key];
        if (handler.timer) {
            window.clearInterval(handler.timer);
        }
    }
};
TimerHandlerList.prototype.dispose = function() {
    for (var key in this.handlers) {
        this.remove(key);
    }
};
function MethodInfo(declaringType, methodName) {
    this.declaringType = declaringType;
    this.methodName = methodName;
}
MethodInfo.prototype.invoke = function(parameters) {
    var request = window.createXMLHttpRequest();
    if (request && typeof request.setRequestHeader != "undefined") {
        this.send(request, parameters, false);
        return this.invokeComplete(request.responseText);
    }
    return null;
};
MethodInfo.prototype.invokeAsync = function(parameters, callback, state) {
    var request = window.createXMLHttpRequest();
    if (request && (typeof request.setRequestHeader != "undefined")) {
        var method = this;
        if ((callback !== undefined) && (callback !== null)) {
            request.onreadystatechange = function() {
                if (this.readyState == 4) {
                    callback(method.invokeComplete(this.responseText), state);
                }
            };
        }
        this.send(request, parameters, true);
    } else {
        if ((callback !== undefined) && (callback !== null)) {
            callback(null, state);
        }
    }
};
MethodInfo.prototype.send = function(request, parameters, async) {
    var message = ["__METHODNAME=", window.encodeURI(this.methodName)];
    for (var num = 0; num < parameters.length; num++) {
        message.push("&__PARAMETER" + num + "=" + window.encodeURI(window.serializeObject(parameters[num])));
    }
    request.open("POST", this.declaringType.action, async);
    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
    request.send(message.join(""));
};
MethodInfo.prototype.invokeComplete = function(value) {
    if (value.charAt(0) == "e") {
        this.debug(value.substring(1));
    } else {
        if (value.charAt(0) == "s") {
            try {
                return eval("(" + value.substring(1) + ")");
            } catch (e) {
                throw new Error("The data does not correspond to valid JSON.");
            }
        }
    }
    return null;
};
MethodInfo.prototype.debug = function(message) {
    if (!document.debuger) {
        document.debuger = document.createElement("DIV");
        var ondblclick = function(event) {
            document.debuger.style.display = "none";
        };
        if (document.debuger.addEventListener) {
            document.debuger.addEventListener("dblclick", ondblclick, false);
        } else {
            document.debuger.attachEvent("ondblclick", ondblclick);
        }
        if (!document.body.firstChild) {
            document.body.appendChild(document.debuger);
        } else {
            document.body.insertBefore(document.debuger, document.body.firstChild);
        }
    }
    document.debuger.innerHTML = message.replace(/\r\n/g, "<br />");
    document.debuger.style.display = "";
};
window.defineRemoteType = function(typeName, methods, action) {
    var start = typeName.indexOf('.');
    var baseName = ((start == -1) ? typeName : typeName.substring(0, start));
    if (window[baseName] === undefined) {
        window[baseName] = { action: action, name: baseName };
    }
    var definedType = window[baseName];
    while (start != -1) {
        var end = typeName.indexOf('.', start + 1);
        var name = ((end != -1) ? typeName.substring(start + 1, end) : typeName.substring(start + 1));
        if (definedType[name] === undefined) {
            definedType[name] = { action: action, name: ((end != -1) ? typeName.substring(0, end) : typeName) };
        }
        definedType = definedType[name];
        start = end;
    }
    for (var num = 0; num < methods.length; num++) {
        window.defineRemoteMethod(definedType, methods[num]);
    }
    return definedType;
};
window.defineRemoteMethod = function(declaringType, methodName) {
    if (declaringType[methodName] === undefined) {
        var methodInfo = new MethodInfo(declaringType, methodName);
        declaringType[methodName] = function() {
            return methodInfo.invoke(arguments);
        };
        declaringType[methodName].async = function(args, callback, asyncState) {
            return methodInfo.invokeAsync(args, callback, asyncState);
        };
    }
};
function HTMLDomReference(element) {
    this.element = element;
}
HTMLDomReference.prototype.attr = function(attr, value) {
    if (typeof attr == "string") {
        if (value !== undefined) {
            this.element[attr] = value;
            return this;
        }
        return this.element[attr];
    }
    if (attr !== undefined) {
        for (var name in attr) {
            this.element[name] = attr[name];
        }
        return this;
    }
    attr = {};
    for (var name in this.element) {
        attr[name] = this.element[name];
    }
    return attr;
};
HTMLDomReference.prototype.removeAttr = function(name) {
    if (this.element[name] !== undefined) {
        this.element[name] = null;
        try {
            delete this.element[name];
        } catch (e) { }
    }
    return this;
};
HTMLDomReference.prototype.css = function(css, value) {
    if (typeof css == "string") {
        if (value !== undefined) {
            this.element.style[css] = value;
            return this;
        }
        return this.element.style[css];
    }
    if (css !== undefined) {
        for (var name in css) {
            if ((name == "cssFloat") && window.browser.msie) {
                this.element.style["styleFloat"] = css[name];
            } else {
                this.element.style[name] = css[name];
            }
        }
        return this;
    }
    css = {};
    for (var name in this.element.style) {
        if ((name == "styleFloat") && window.browser.msie) {
            css["cssFloat"] = this.element.style[name];
        } else {
            css[name] = this.element.style[name];
        }
    }
    return css;
};
HTMLDomReference.prototype.event = function(name, target) {
    var element = this.element;
    var handler = function(event) {
        target.call(element, new EventArgs(event || window.event));
    };
    if (element.addEventListener) {
        element.addEventListener(name, handler, false);
    } else {
        element.attachEvent("on" + name, handler);
    }
    return this;
};
HTMLDomReference.prototype.position = function(position) {
    if ((position !== undefined) && ((position.left !== undefined) || (position.top !== undefined))) {
        if (typeof (position.left) == "number") {
            this.element.style.left = position.left + "px";
        }
        if (typeof (position.top) == "number") {
            this.element.style.top = position.top + "px";
        }
        return this;
    }
    var output = { left: 0, top: 0 };
    if (this.element.offsetParent) {
        output.left = this.element.offsetLeft;
        output.top = this.element.offsetTop;
        var parent = this.element.offsetParent;
        while (parent) {
            output.left += parent.offsetLeft;
            output.top += parent.offsetTop;
            var tagName = parent.tagName.toLowerCase();
            if ((tagName != "table") && (tagName != "body") && (tagName != "html") && (tagName != "div") && parent.clientTop && parent.clientLeft) {
                output.left += parent.clientLeft;
                output.top += parent.clientTop;
            }
            parent = parent.offsetParent;
        }
    } else {
        output.left = this.element.left || this.element.x;
        output.top = this.element.top || this.element.y;
    }
    if (position === undefined) {
        return output;
    }
    position.left = output.left;
    position.top = output.top;
    return this;
};
HTMLDomReference.prototype.scroll = function(scroll) {
    if ((scroll !== undefined) && ((scroll.left !== undefined) || (scroll.top !== undefined))) {
        if (typeof (scroll.left) == "number") {
            this.element.scrollLeft = scroll.left;
        }
        if (typeof (scroll.top) == "number") {
            this.element.scrollTop = scroll.top;
        }
        return this;
    }
    var output = { left: this.element.scrollLeft, top: this.element.scrollTop };
    if (this.element.nodeType == 9) {
        if (!window.browser.msie) {
            output.left = window.pageXOffset;
            output.top = window.pageYOffset;
        } else if (document.documentElement) {
            output.left = document.documentElement.scrollLeft;
            output.top = document.documentElement.scrollTop;
        } else {
            output.left = document.body.scrollLeft;
            output.top = document.body.scrollTop;
        }
    }
    if (scroll === undefined) {
        return output;
    }
    scroll.left = output.left;
    scroll.top = output.top;
    return this;
};
HTMLDomReference.prototype.size = function(size) {
    if ((size !== undefined) && ((size.height !== undefined) || (size.width !== undefined))) {
        if (typeof (size.height) == "number") {
            this.element.style.height = size.height + "px";
        }
        if (typeof (size.width) == "number") {
            this.element.style.width = size.width + "px";
        }
        return this;
    }
    var output = { height: this.element.offsetHeight, width: this.element.offsetWidth };
    if (size === undefined) {
        return output;
    }
    size.height = output.height;
    size.width = output.width;
    return this;
};
HTMLDomReference.prototype.html = function(html) {
    return this.attr("innerHTML", html);
};
HTMLDomReference.prototype.value = function(value) {
    return this.attr("value", value);
};
HTMLDomReference.prototype.expand = function() {
    return this.css("display", "");
};
HTMLDomReference.prototype.collapse = function() {
    return this.css("display", "none");
};
HTMLDomReference.prototype.show = function() {
    return this.css("visibility", "");
};
HTMLDomReference.prototype.hide = function() {
    return this.css("visibility", "hidden");
};
HTMLDomReference.prototype.toggle = function(name, values) {
    if (typeof this.element[name] == "boolean") {
        this.element[name] = !this.element[name];
    } else {
        if ((name !== undefined) && (values !== undefined)) {
            this.element[name] = ((this.element[name] == values[0]) ? values[1] : values[0]);
        }
    }
    return this;
};
HTMLDomReference.prototype.toggleCss = function(name, values) {
    if ((name !== undefined) && (values !== undefined)) {
        this.element.style[name] = ((this.element.style[name] == values[0]) ? values[1] : values[0]);
    }
    return this;
};
HTMLDomReference.prototype.opacity = function(opacity) {
    if (opacity !== undefined) {
        this.element.style.opacity = opacity;
        if (window.browser.msie) {
            if (typeof this.element.filters.alpha == "undefined") {
                this.element.style.filter = "alpha()";
            }
            this.element.filters.alpha.opacity = opacity * 100;
        }
        return this;
    }
    return (!window.browser.msie ? (this.element.style.opacity === undefined ? 1 : this.element.style.opacity) : ((typeof this.element.filters.alpha == "undefined") ? 1 : (this.element.filters.alpha.opacity / 100)));
};
HTMLDomReference.prototype.contains = function(selector) {
    while (selector) {
        if (selector == this.element) {
            return true;
        }
        selector = selector.parentNode;
    }
    return false;
};
HTMLDomReference.prototype.current = function(element) {
    if (element !== undefined) {
        if (element.nodeType) {
            if (this.element.parentNode) {
                this.element.parentNode.replaceChild(element, this.element);
            }
            this.element = element;
        }
        return this;
    }
    return this.element;
};
HTMLDomReference.prototype.parent = function(element) {
    if (element !== undefined) {
        if (element.nodeType) {
            this.element.parentNode.removeChild(this.element);
            element.appendChild(this.element);
        }
        return this;
    }
    return this.element.parentNode;
};
HTMLDomReference.prototype.before = function(element) {
    if (element !== undefined) {
        if (element.nodeType) {
            this.element.parentNode.insertBefore(element, this.element);
        }
        if (typeof element == "string") {
            this.element.parentNode.insertBefore(document.createTextNode(element), this.element);
        }
        return this;
    }
    var selector = this.element.previousSibling;
    while (selector && (selector.nodeType != 1)) {
        selector = selector.previousSibling;
    }
    return (selector || this.element);
};
HTMLDomReference.prototype.after = function(element) {
    if (element !== undefined) {
        if (element.nodeType) {
            this.element.parentNode.insertBefore(element, this.element.nextSibling);
        }
        if (typeof element == "string") {
            this.element.parentNode.insertBefore(document.createTextNode(element), this.element.nextSibling);
        }
        return this;
    }
    var selector = this.element.nextSibling;
    while (selector && (selector.nodeType != 1)) {
        selector = selector.nextSibling;
    }
    return (selector || this.element);
};
HTMLDomReference.prototype.empty = function() {
    while (this.element.firstChild) {
        this.element.removeChild(this.element.firstChild);
    }
    return this;
};
window.$ = function(selector) {
    if (!selector) {
        return new HTMLDomReference(window);
    }
    if (!HTMLDomReference.cache) {
        HTMLDomReference.cache = {};
    }
    if (typeof selector == "string") {
        var element = (document.getElementById(selector) || document.getElementsByName(selector).item(0) || document);
        if (!HTMLDomReference.cache[selector]) {
            HTMLDomReference.cache[selector] = new HTMLDomReference(element);
        } else {
            HTMLDomReference.cache[selector].element = element;
        }
        return HTMLDomReference.cache[selector];
    }
    var name = (selector.id || selector.name);
    if (selector.nodeType && name) {
        if (!HTMLDomReference.cache[name]) {
            HTMLDomReference.cache[name] = new HTMLDomReference(selector);
        } else {
            HTMLDomReference.cache[name].element = selector;
        }
        return HTMLDomReference.cache[name];
    }
    return new HTMLDomReference(selector);
};