﻿

// -----------------
// Browser detection
// -----------------

if (window.browser == null)
{
    window.browser           = new Object();
    window.browser.ie        = (navigator.userAgent.toLowerCase().indexOf("msie") >= 0);
    window.browser.mozilla   = (!this.attachEvent);
    window.browser.chrome    = (navigator.userAgent.toLowerCase().indexOf("chrome") >= 0);
    window.browser.netscape  = (navigator.appName.toLowerCase() == "netscape");
    window.browser.mac       = (navigator.userAgent.toLowerCase().indexOf("mac") >= 0)
    window.browser.opera     = (navigator.userAgent.toLowerCase().indexOf("opera") >= 0);
    window.browser.gecko     = (navigator.userAgent.toLowerCase().indexOf("gecko") >= 0) || window.browser.chrome;
    window.browser.w3c       = ((document.getElementById) ? true : false);
}

// --------------
// String methods
// --------------

String.toCharCode = function(ch)
{
    // restrict input to a single character
    ch = ch.charAt(0);

    // loop through all possible ASCII values
    var i;
    
    for (i = 0; i < 256; ++ i)
    {
        // convert i into a 2-digit hex string
        var h = i.toString(16);
	    
        if (h.length == 1)
	        h = "0" + h;

        // insert a % character into the string
        h = "%" + h;

        // determine the character represented by the escape code
        h = unescape(h);

        // if the characters match, we've found the ASCII value
        if (h == c)
	        break;
    }
    
    return i;
};

String.ltrim = function(value)
{
    if (value != null)
    {
        value = value.toString();
        
        while (value.charAt(0) == " ")
            value = value.replace(value.charAt(0), "");
    }
    
    return value;
};

String.rtrim = function(value)
{
    if (value != null)
    {
        value = value.toString();
        
        while (value.charAt(value.length - 1) == " ")
            value = value.substring(0, value.length - 1);
    }
    
    return value;
};

String.lpad = function(value, character, length)
{
    if (value != null)
    {
        value = value.toString();

        while (value.length < length)
        {
            value = character + value;
        }
    }
        
    return value;
};

String.rpad = function(value, character, length)
{
    if (value != null)
    {
        value = value.toString();

        while (value.length < length)
        {
            value += character;
        }
    }
    
    return value;
};

String.duplicate = function(value, number)
{
    var str = "";
    
    if ((value != null) && (number != null))
    {
        for (var i = 0; i < number; i++)
        {
            str += value;
        }
    }
    
    return str;
};

String.trim = function(value) { return String.ltrim(String.rtrim(value)); };
    
String.prototype.ltrim = function() { return String.ltrim(this); };
    
String.prototype.rtrim = function() { return String.rtrim(this); };
    
String.prototype.trim = function() { return String.trim(this); };

String.prototype.rpad = function(character, length) { return String.rpad(this, character, length); };

String.prototype.lpad = function(character, length) { return String.lpad(this, character, length); };

String.prototype.duplicate = function(number) { return String.duplicate(this, number); };

// -------------
// Array methods
// -------------

Array.prototype.contains = function(value)
{
    var result = false;
    
    for (var i = 0; i < this.length; i++)
    {
        if (this[i] == value)
        {
            result = true;
            break;
        }
    }
    
    return result;
};

Array.prototype.clear = function()
{
    while (this.length > 0)
    {
        this.pop();
    }
};

Array.prototype.indexOf = function(value)
{
    var index = -1;

    for (var i = 0; i < this.length; i++)
    {
        if (this[i] == value)
        {
            index = i;
            break;
        }
    }
            
    return index;
};

Array.prototype.copy = function()
{
    var copyOf = null;
    
    if (this.length == 0)
        copyOf = new Array();
    else
        copyOf = this.slice(0, this.length - 1);
        
    return copyOf;
};

Array.prototype.remove = function(value)
{
    var index = this.indexOf(value);

    if (index >= 0)
        this.splice(index, 1);
}

// ---------------------------------
// Mozilla behaviour for IE browsers
// ---------------------------------

if (window.browser.ie)
{
    // ----
    // Node
    // ----
    
    window.Node = 
    {
        ELEMENT_NODE:           1,
        ATTRIBUTE_NODE:         2,
        TEXT_NODE:              3,
        COMMENT_NODE:           8,
        DOCUMENT_NODE:          9,
        DOCUMENT_FRAGMENT_NODE: 11
    };
}

// ---------------------------------
// IE behaviour for Mozilla browsers
// ---------------------------------

if (window.browser.gecko || window.browser.chrome)
{
    // -----------
    // HTMLElement
    // -----------

    HTMLElement.prototype.__defineGetter__("all", function() 
    {
	    return this.getElementsByTagName("*");
    });

    HTMLElement.prototype.__defineGetter__("parentElement", function() 
    {
	    return (this.parentNode == this.ownerDocument) ? null : this.parentNode;
    });

    HTMLElement.prototype.__defineGetter__("uniqueID", function() 
    {
	    // a global counter is stored privately as a property of this getter function.
	    // initialise the counter
	    if (!arguments.callee.count) arguments.callee.count = 0;
	    // create the id and increment the counter
	    var uniqueID = "moz_id" + arguments.callee.count++;
	    // creating a unique id, creates a global reference
	    window[uniqueID] = this;
	    // we don't want to increment next time, so redefine the getter
	    this.__defineGetter__("uniqueID", function(){return uniqueID; });
	    return uniqueID;
	});

//	function HTMLCurrentStyle(element)
//	{
//	    this.element = element;
//	};
//	
//	HTMLCurrentStyle.prototype.__defineGetter__("borderWidth", function() { return getComputedStyle(this.element, "borderWidth"); });
//	HTMLCurrentStyle.prototype.__defineGetter__("borderLeftWidth", function() { return getComputedStyle(this.element, "borderLeftWidth"); });
//	HTMLCurrentStyle.prototype.__defineGetter__("borderTopWidth", function() { return getComputedStyle(this.element, "borderTopWidth"); });
//	HTMLCurrentStyle.prototype.__defineGetter__("borderRightWidth", function() { return getComputedStyle(this.element, "borderRightWidth"); });
//	HTMLCurrentStyle.prototype.__defineGetter__("borderBottomWidth", function() { return getComputedStyle(this.element, "borderBottomWidth"); });

//	HTMLElement.prototype.__defineGetter__("currentStyle", function()
//	{
//	    return new HTMLCurrentStyle(this);
//	});

	HTMLElement.prototype.__defineGetter__("currentStyle", function()
	{
	    return getComputedStyle(this, null);
	});

    HTMLElement.prototype.__defineGetter__("innerText", function() 
    {
	    return this.textContent;
    });
    
    HTMLElement.prototype.__defineSetter__("innerText", function(value) 
    {
	    this.textContent = value;
    });

    HTMLElement.prototype.attachEvent = function(name, handler) 
    {
	    this.addEventListener(name.slice(2), handler, false);
    };

    HTMLElement.prototype.removeEvent = function(name, handler) 
    {
	    this.removeTeleWare.EventListener(name.slice(2), handler, false);
    };

    HTMLElement.prototype.createEventObject = function() 
    {
	    return this.ownerDocument.createEventObject();
    };

    HTMLElement.prototype.fireEvent = function(name, event) 
    {
	    if (!event) 
	        event = this.ownerDocument.createEventObject();
	        
	    event.initEvent(name.slice(2), false, false);
	    this.dispatchEvent(event);
	    
	    // not sure that this should be here??
	    if (typeof this[name] == "function") 
	        this[name]();
	    else if (this.getAttribute(name)) 
	        eval(this.getAttribute(name));
    };
    
    HTMLElement.prototype.contains = function(element) 
    {
	    return Boolean(element == this || (element && this.contains(element.parentElement)));
    };

    // for older versions of gecko we need to use getPropertyValue() to
    // access css properties returned by getComputedStyle().
    // we don't want this so we fix it.
    try 
    {
        var computedStyle = getComputedStyle(this, null);
        // the next line will throw an error for some versions of mozilla
        var test = computedStyle.display;
    } 
    catch (ignore) 
    {
        // the previous line will throw an error for some versions of mozilla
    } 
    finally 
    {
        if (!test) 
        {
	        // the above code didn't work so we need to fix CSSStyleDeclaration
	        var UPPER_CASE = /[A-Z]/g;
	        
	        function ___dashLowerCase(match) { return "-" + match.toLowerCase(); }
	        
	        function ___cssName(propertyName) { return propertyName.replace(UPPER_CASE, ___dashLowerCase(propertyName)); }
	        
	        function ___assignStyleGetter(propertyName) 
	        {
		        var cssName = ___cssName(propertyName);
		        
		        CSSStyleDeclaration.prototype.__defineGetter__(propertyName, function() 
		        {
			        return this.getPropertyValue(cssName);
		        });
	        }
	        
	        for (var propertyName in document.style) 
	        {
		        if (typeof document.style[propertyName] == "string")
			        ___assignStyleGetter(propertyName);
	        }
        }
    }
    
    // -------------------
    // CSSStyleDeclaration
    // -------------------
    
    CSSStyleDeclaration.prototype.__defineGetter__("styleFloat", function() 
    {
	    return this.cssFloat;
    });
    
    CSSStyleDeclaration.prototype.__defineSetter__("styleFloat", function(value) 
    {
	    this.cssFloat = value;
    });
    
    // mimic microsoft's pixel representations of left/top/width/height
    // the getters only work for values that are already pixels
    CSSStyleDeclaration.prototype.__defineGetter__("pixelLeft", function() 
    {
	    return parseInt(this.left, 10) || 0;
    });
    
    CSSStyleDeclaration.prototype.__defineSetter__("pixelLeft", function(value) 
    {
	    this.left = value + "px";
    });
    
    CSSStyleDeclaration.prototype.__defineGetter__("pixelHeight", function() 
    {
	    return parseInt(this.height, 10) || 0;
    });
    
    CSSStyleDeclaration.prototype.__defineSetter__("pixelHeight", function(value) 
    {
	    this.height = value + "px";
    });
    
    CSSStyleDeclaration.prototype.__defineGetter__("pixelTop", function() 
    {
	    return parseInt(this.top, 10) || 0;
    });
    
    CSSStyleDeclaration.prototype.__defineSetter__("pixelTop", function(value) 
    {
	    this.top = value + "px";
    });
    
    CSSStyleDeclaration.prototype.__defineGetter__("pixelWidth", function() 
    {
	    return parseInt(this.width, 10) || 0;
    });
    
    CSSStyleDeclaration.prototype.__defineSetter__("pixelWidth", function(value) 
    {
	    this.width = value + "px";
    });
    
    // -----
    // Event
    // -----
    
    Event.prototype.__defineGetter__("srcElement", function()
    { 
        var element = null;
        
        if (this.target.nodeType == Node.ELEMENT_NODE)
            element = this.target;
        else
            element = this.target.parentNode;
        
        return element;
    });
    
    Event.prototype.__defineGetter__("returnValue", function()
    {
        return true;
    });

    Event.prototype.__defineSetter__("returnValue", function(value)
    {
        if (this.cancelable && !value) 
        {
            // Once set to true this can't be set back to false like in IE
            this.preventDefault();
            this.__defineGetter__("returnValue", function() 
            {
	            return false;
            });
        }
    });

    Event.prototype.__defineSetter__("cancelBubble", function(value)
    {
        // Once set to true this can't be set back to false like in IE
        if (value) this.stopPropagation();
    });

    Event.prototype.__defineGetter__("offsetX", function() 
    {
        return this.layerX;
    });

    Event.prototype.__defineGetter__("offsetY", function()
    {
        return this.layerY;
    });
    
    Event.prototype.__defineGetter__("fromElement", function()
    {
        var element = null;
        
        if (this.type == "mouseout")
            element = this.target;
        else if (this.type == "mouseover")
            element = this.relatedTarget;

        return element;
    });

    Event.prototype.__defineGetter__("toElement", function()
    {
        var element = null;
        
        if (this.type == "mouseout")
            element = this.relatedTarget;
        else if (this.type == "mouseover")
            element = this.target;

        return element;
    });

    Event.prototype.__defineGetter__("button", function()
    {
        var btn = 0;
        
        if (this.which == 1)
            btn = 1;
        else if (this.which == 2)
            btn = 4;
        else
            btn = 2;

        return btn;
    });
    
    // Event.prototype.make
    
    // --------
    // Document
    // --------
    
    Document.prototype.loadXML = function(xml)
    {
        var domParser = new DOMParser();
        xmlDoc = domParser.parseFromString(xml, "text/xml");
            
        if (xmlDoc.documentElement.nodeName == "parseerror")
            throw new Error("An exception occured loading xml {" + xml + "}.[Document.loadXML]");
    
        while (this.hasChildNodes())
        {
            this.removeChild(this.lastChild);
        }
        
        for (var i = 0; i < xmlDoc.childNodes.length; i++) 
        {
            this.appendChild(this.importNode(xmlDoc.childNodes[i], true));
        }
    };

    Document.prototype.selectNodes = function(xpath, node) 
    {
        if (!node) 
            node = this;
        
        var nodes       = new Array();
        var nsResolver  = this.createNSResolver(this.documentElement);
        var result      = this.evaluate(xpath, node, nsResolver, 9, null);
        
        if (result)
        {
            var node = result.iterateNext();
            
            while (node != null)
            {
                nodes.push(node);
                node = result.iterateNext();
            }
        }
        
        return nodes;
    };
 
    Document.prototype.selectSingleNode = function(xpath, node)
    {
        var result = null;
        var nodes  = this.selectNodes(xpath, node);
        
        if (nodes.length > 0)
            result = nodes[0];
            
        return result;
    };
    
    // -------
    // Element
    // -------

    Element.prototype.selectNodes = function(xpath)
    {
        return this.ownerDocument.selectNodes(xpath, this);       
    };

    Element.prototype.selectSingleNode = function(xpath)
    {
        return this.ownerDocument.selectSingleNode(xpath, this);       
    };
    
    // ----
    // Node
    // ----

    Node.prototype.__defineGetter__("xml", function()
    {
        var serializer = new XMLSerializer();
        return serializer.serializeToString(this); 
    });

    Node.prototype.__defineGetter__("outerHTML", function()
    {
         return this.xml;
    });
}


// ------------------------------------------------
// Global methods for browser independent behaviour
// ------------------------------------------------

window.$getId = function(id)
{
    var element = null;
    
    if (document.getElementById)
        element = document.getElementById(id);
    else if (document.all)
        element = document.all[id];

    return ___extendElement(element);
};

window.$getClass = function(className, exact)
{
    var root = document.body;
    
    if (!root.extended)
        ___extendElement(root);

    return root.selectDescendantsByCssClass(className, exact);
};

window.$getDescendants = function(name)
{
    var root = document.body;

    if (!root.extended)
        ___extendElement(root);

    return root.selectDescendants(name);
}

window.$getDescendantOrSelf = function(name)
{
    var root = document.body;

    if (!root.extended)
        ___extendElement(root);

    return root.selectDescendantOrSelf(name);
}

window.$extend = function(element)
{
    return ___extendElement(element);
};

window.createXMLDocument = function()
{
    var xmlDoc = null;

    if (document.implementation && document.implementation.createDocument)
    {
        xmlDoc = document.implementation.createDocument("", "", null);
    }
    else if (window.ActiveXObject)
    {
        try
        {
            xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
        }
        catch (e)
        {
            xmlDoc = new ActiveXObject("Msxml.DOMDocument");
        }
    }
    
    if (xmlDoc != null && typeof xmlDoc.load == "undefined")
        xmlDoc = null;
        
    return xmlDoc;
};

window.loadXMLDocument = function(xml)
{
    var xmlDoc;
    
    if (browser.chrome)
    {
        var domParser = new DOMParser();
        xmlDoc = domParser.parseFromString(xml, "text/xml");
    }
    else
    {
        xmlDoc = window.createXMLDocument();

        if (xmlDoc == null)
            throw new Error("Null argument \'xmlDocument\'.[window.loadXml]");
        else if (xml == "")
            throw new Error("Empty string argument \'xml\'.[window.loadXml]");
            
        xmlDoc.loadXML(xml);
    }
    
    return xmlDoc;
};

window.createXMLHttpRequest = function()
{
    var request = null;
    
    if (window.XMLHttpRequest && !window.browser.ie)
        request = new XMLHttpRequest();
    else if (window.ActiveXObject)
        request = new ActiveXObject("Microsoft.XMLHTTP");
    
    return request;
};

window.createHTMLElement = function ___createHTMLElement(xhtml)
{
    if (typeof xhtml == "string")
        xhtml = window.loadXMLDocument(xhtml).documentElement;

    var NODE_ELEMENT = 1;
    var NODE_ATTRIBUTE = 2;
    var NODE_TEXT = 3;

    var elmXml = xhtml;
    var elmHtml = null;
    var attXml = null;
    var elmXmlChild = null;
    var elmHtmlChild = null;

    if (elmXml.nodeType == Node.ELEMENT_NODE)
    {
        elmHtml = ___extendElement(document.createElement(elmXml.nodeName));
    }
    else if (elmXml.nodeType == Node.TEXT_NODE)
    {
        if (!browser.gecko)
            elmHtml = document.createTextNode(elmXml.text);
        else
            elmHtml = document.createTextNode(elmXml.textContent);
    }

    if (elmXml.attributes != null)
    {
        for (var i = 0; i < elmXml.attributes.length; i++)
        {
            // Note: IE doesn't update styles if using setAttribute to define css class.
            
            attXml = elmXml.attributes[i];

            if (attXml.name == "class")
                elmHtml.className = attXml.value;
            else
                attHtml = elmHtml.setAttribute(attXml.name, attXml.value);
        }
    }

    if (elmXml.childNodes != null)
    {
        for (var i = 0; i < elmXml.childNodes.length; i++)
        {
            elmXmlChild = elmXml.childNodes[i];
            elmHtmlChild = ___createHTMLElement(elmXmlChild);

            if (elmHtmlChild != null)
                elmHtml.appendChild(elmHtmlChild);
        }
    }

    return elmHtml;
};

EventRegister = function() { return this.construct.apply(this, arguments); };

EventRegister.prototype =
{
    construct: function()
    {
        var m_registry = new Array();
        var m_log = new Array();

        this.addHandler = function(element, eventName, object, handler, capture)
        {
            // If element is a string, assume it's an id
            if (typeof element == "string")
                element = $getId(element);
            else if ((!element.extended) && (element != window))
                element = $extend(element);

            if (typeof handler == "string")
                handler = object[handler];

            // This function invokes the specified event handler
            var callback = function(e)
            {
                if (!e)
                    e = window.event;

                e.keycode = ___keycode(e);
                e.unicode = ___unicode(e);
                e.character = ___character(e);
                e.alpha = ___alpha(e);
                e.numeric = ___numeric(e);
                e.alphanumeric = ___alphanumeric(e);
                e.navigation = ___navigation(e);
                e.fn = ___fn(e);
                e.arrow = ___arrow(e);
                e.leftArrow = ___leftArrow(e);
                e.upArrow = ___upArrow(e);
                e.rightArrow = ___rightArrow(e);
                e.downArrow = ___downArrow(e);
                e.space = ___space(e);
                e.backspace = ___backspace(e);
                e.del = ___delete(e);
                e.tab = ___tab(e);
                e.enter = ___enter(e);
                e.escape = ___escape(e);
                e.modifier = ___modifier(e);
                e.control = ___control(e);
                e.home = ___home(e);
                e.end = ___end(e);
                e.text = ___text(e);

                if ((e.srcElement != null) && (!e.srcElement.extended))
                    $extend(e.srcElement);

                return handler.call(object, e);
            };

            // Register event handler with browser's event system
            if (element.addEventListener)
            {
                element.addEventListener(eventName, callback, capture);
            }
            else
            {
                var onevent = eventName;

                if (onevent.substring(0, 2).toLowerCase() != "on")
                    onevent = "on" + onevent;

                if (element.attachEvent)
                    element.attachEvent(onevent, callback);
                else
                    element[onevent] = callback;
            }

            // Store event info in registry so that the handler can be removed later

            var entry =
            {
                element: element,
                eventName: eventName,
                handler: callback,
                ownerWindow: window,
                object: object,
                method: handler,
                capture: (capture) ? capture : false
            }

            m_registry.push(entry);
        };

        this.dispose = function()
        {
            var count = m_registry.length;

            for (var i = count - 1; i >= 0; i--)
            {
                var entry = m_registry[i];

                if (entry.element.removeEventListener)
                {
                    entry.element.removeEventListener(entry.eventName, entry.handler, entry.capture);
                }
                else
                {
                    var onevent = entry.eventName;

                    if (onevent.substring(0, 2).toLowerCase() != "on")
                        onevent = "on" + onevent;

                    if (entry.element.detachEvent)
                        entry.element.detachEvent(onevent, entry.handler);
                    else
                        entry.element[onevent] = null;
                }

                //_purge(entry.element);    

                entry.element = null;
                entry.object = null;
                entry.handler = null;

                m_registry.splice(i, 1);
            }
        };

        this.removeHandler = function(element, eventName, object, handler)
        {
            var count = m_registry.length;

            if (typeof handler == "string")
                handler = object[handler];

            for (var i = count - 1; i >= 0; i--)
            {
                var entry = m_registry[i];

                if (entry.element == element
                && entry.eventName == eventName
                && entry.object == object
                && entry.method == handler)
                {
                    if (entry.element.removeEventListener)
                    {
                        entry.element.removeEventListener(entry.eventName, entry.handler, entry.capture);
                    }
                    else
                    {
                        var onevent = eventName;

                        if (onevent.substring(0, 2).toLowerCase() != "on")
                            onevent = "on" + onevent;

                        if (entry.element.detachEvent)
                            entry.element.detachEvent(onevent, entry.handler);
                        else
                            entry.element[onevent] = null;
                    }

                    //_purge(entry.element);    

                    entry.element = null;
                    entry.object = null;
                    entry.handler = null;

                    m_registry.splice(i, 1);

                    break;
                }
            }
        }

        function _purge(element)
        {
            var a = element.attributes, i, l, n;

            if (a)
            {
                l = a.length;

                for (i = 0; i < l; i += 1)
                {
                    n = a[i].name;

                    if (typeof element[n] == 'function')
                        element[n] = null;
                }
            }

            a = element.childNodes;

            if (a)
            {
                l = a.length;

                for (i = 0; i < l; i += 1)
                {
                    _purge(element.childNodes[i]);
                }
            }
        }
    }
};

window.events = new EventRegister();
window.events.addHandler(window, "unload", window.events, window.events.dispose);

// ----------------
// Helper functions
// ----------------

function ___parseQueryString()
{
    var params = new Array();
    
    if (window.location.search.length > 0)
    {
        var query = window.location.search.substring(1);
        var items = query.split("&");
        
        for (var i = 0; i < items.length; i++) 
        {
            var item = items[i].split("=");
            params[item[0]] = item[1];
        }
    }
    
    return params;
}

function ___extendElement(element)
{
    if (element != null && !element.extended)
    {  
        element.selectChildren              = ___selectChildren;
        element.selectChildrenByCssClass    = ___selectChildrenByCssClass;
        element.selectChild                 = ___selectChild;
        element.selectFirstChild            = ___selectFirstChild;
        element.selectLastChild             = ___selectLastChild;
        element.selectChildByCssClass       = ___selectChildByCssClass;
        element.selectChildrenByCssClass    = ___selectChildrenByCssClass;
        element.selectDescendants           = ___selectDescendants;
        element.selectDescendantsByCssClass = ___selectDescendantsByCssClass;
        element.selectDescendant            = ___selectDescendant;
        element.selectDescendantOrSelf      = ___selectDescendantOrSelf;
        element.selectDescendantByCssClass  = ___selectDescendantByCssClass;
        element.selectAncestor              = ___selectAncestor;
        element.selectAncestorOrSelf        = ___selectAncestorOrSelf;
        element.selectNextSibling           = ___selectNextSibling;
        element.selectPreviousSibling       = ___selectPreviousSibling;
        element.replaceClass                = ___replaceClass;
        element.addClass                    = ___addClass;
        element.removeClass                 = ___removeClass;
        element.getAbsolutePosition         = ___getAbsolutePosition;
        element.getCssClasses               = ___getCssClasses;
        element.behaviours                  = new Array();
        element.hasBehaviour                = ___hasBehaviour;
        element.addBehaviour                = ___addBehaviour;
        element.removeBehaviour             = ___removeBehaviour;
        element.get_behaviour               = ___getBehaviour;
        element.get_index                   = ___getIndex;
        
        if (element.nodeName.toLowerCase() == "input")
        {
            if (!element.getCursorPosition)
                element.getCursorPosition = ___getSelectionStart;
            
            if (!element.getSelectionStart)
                element.getSelectionStart = ___getSelectionStart;
            
            if (!element.getSelectionEnd)
                element.getSelectionEnd = ___getSelectionEnd;
                
            if (!element.getSelection)
                element.getSelection = ___getSelection;
        
            if (!element.setSelection)
                element.setSelection = ___setSelection;
        }
        
        element.extended = true;
    }
    
    return element;
}

function ___selectChildren(name)
{
    var elements = new Array();
    
    if (this.childNodes != null)
    {
        name = (name == null || name == "") ? "*" : name.toLowerCase();

        for (var i = 0; i < this.childNodes.length; i++)
        {
            var item = this.childNodes[i];
            
            if (item.nodeType == Node.ELEMENT_NODE)
                if (name == "*" || name == item.nodeName.toLowerCase())
                    elements.push(___extendElement(item));
        }
    }
    
    return elements;
}

function ___selectChildrenByCssClass(className, exact)
{
    var elements = new Array();

    if (this.childNodes != null)
    {
        for (var i = 0; i < this.childNodes.length; i++)
        {
            var item = this.childNodes[i];
            
            if (item.nodeType == Node.ELEMENT_NODE)
            {
                if (exact)
                {   
                    if (item.className.trim().toLowerCase() == className.trim().toLowerCase())
                        elements.push(___extendElement(item));
                }
                else
                {
                    if (!item.extended)
                        item = ___extendElement(item);
                
                    var classes = item.getCssClasses();
                    
                    if (classes.contains(className.trim().toLowerCase()))
                        elements.push(item);
                }
            }
        }
    }
    
    return elements;
}

function ___selectChild(name)
{
    var el  = null;
    var els = this.selectChildren(name);
        
    if (els.length > 0)
        el = els[0];
    
    return el;
}

function ___selectFirstChild(name)
{
    return this.selectChild(name);
}

function ___selectLastChild(name)
{
    var element  = null;
    var elements = this.selectChildren(name);
        
    if (elements.length > 0)
        element = elements[elements.length - 1];
    
    return element;
}

function ___selectChildByCssClass(className, exact)
{
    var element  = null;
    var elements = this.selectChildrenByCssClass(className, exact);
        
    if (elements.length > 0)
        element = elements[0];
    
    return element;
}

function ___selectAncestor(name)
{
    var ancestor    = null;
    var currElement = this;
    
    name = (name == null || name == "") ? "*" : name.toLowerCase();

    while (ancestor == null && currElement.parentNode != null)
    {
        if ((currElement.parentNode.nodeType == Node.ELEMENT_NODE)
        && (name == "*" || name == currElement.parentNode.nodeName.toLowerCase()))
            ancestor = currElement.parentNode;
        else
            currElement = currElement.parentNode;
    }
    
    return ___extendElement(ancestor);
}

function ___selectAncestorOrSelf(name)
{
    var element = null;
    
    name = (name == null || name == "") ? "*" : name.toLowerCase();
    
    if (name == "*" || name == this.nodeName.toLowerCase()) 
        element = this;
    else
        element = this.selectAncestor(name);
        
    return element;
}

function ___selectDescendants(name)
{
    var elements = new Array();

    if (this.childNodes != null)
    {
        name = (name == "" || name == null) ? "*" : name.toLowerCase();

        for (var i = 0; i < this.childNodes.length; i++)
        {
            var item  = this.childNodes[i];
            var descs = null;
            
            if (item.nodeType == Node.ELEMENT_NODE)
            {
                if (!item.extended)
                    item = ___extendElement(item);
                
                if (name == "*" || name == item.nodeName.toLowerCase())
                    elements.push(item);
                
                descs = item.selectDescendants(name);
                
                if (descs.length > 0)
                    elements = elements.concat(descs);
            }
        }
    }
    
    return elements;
}

function ___selectDescendantsByCssClass(className, exact)
{
    var elements = new Array();
    
    className = (className == null) ? "" : className.trim().toLowerCase();

    if (this.childNodes != null && className.length > 0)
    {
        for (var i = 0; i < this.childNodes.length; i++)
        {
            var item    = this.childNodes[i];
            var classes = null;
            var descs   = null;

            if (item.nodeType == Node.ELEMENT_NODE)
            {
                if (!item.extended)
                    item = ___extendElement(item);
                        
                if (exact)
                {   
                    if (className == item.className.trim().toLowerCase())
                        elements.push(item);
                }
                else
                {
                    classes = item.getCssClasses();
                    
                    for (var j = 0; j < classes.length; j++)
						classes[j] = classes[j].trim().toLowerCase();
                    
                    if (classes.contains(className))
                        elements.push(item);
                }
                
                descs = item.selectDescendantsByCssClass(className, exact);
                
                if (descs.length > 0)
                    elements = elements.concat(descs);
            }
        }
    }
    
    return elements;
}

function ___selectDescendant(name)
{
    var element  = null;
    var elements = this.selectDescendants(name);
        
    if (elements.length > 0)
        element = elements[0];
    
    return element;
}

function ___selectDescendantOrSelf(name)
{
    var element = null;
    
    name = (name == null || name == "") ? "*" : name.toLowerCase();
    
    if (name == "*" || name == this.nodeName.toLowerCase()) 
        element = this;
    else
        element = this.selectDescendant(name);
        
    return element;
}

function ___selectDescendantByCssClass(className, exact)
{
    var element  = null;
    var elements = this.selectDescendantsByCssClass(className, exact);
        
    if (elements.length > 0)
        element = elements[0];
    
    return element;
}

function ___selectNextSibling(name)
{
    var sibling = this.nextSibling;
    
    name = (name == null || name == "") ? "*" : name.toLowerCase();

    while (sibling != null)
    {
        if ((sibling.nodeType == Node.ELEMENT_NODE)
        && (name == "*" || name == sibling.nodeName.toLowerCase()))
            break;
        else
            sibling = sibling.nextSibling;
    }
    
    return ___extendElement(sibling);
}

function ___selectPreviousSibling(name)
{
    var sibling = this.previousSibling;
    
    name = (name == null || name == "") ? "*" : name.toLowerCase();

    while (sibling != null)
    {
        if ((sibling.nodeType == Node.ELEMENT_NODE)
        && (name == "*" || name == sibling.nodeName.toLowerCase()))
            break;
        else
            sibling = sibling.previousSibling;
    }
    
    return ___extendElement(sibling);
}

function ___getCssClasses()
{
    var classes = null;
    
    if (this.className == null || this.className.trim().length == 0)
        classes = new Array();
    else
        classes = this.className.trim().split(" ");
    
    return classes;
}

function ___addClass(name)
{
    if (name != null && name.length > 0)
    {
        var names = null;
        var exists = false;

        if (this.className == null || this.className.trim().length == 0)
            names = new Array();
        else
            names = this.className.split(" ");

        for (var i = 0; i < names.length; i++)
        {
            if (names[i] == name)
            {
                exists = true;
                break;
            }
        }

        if (!exists)
            this.className = (this.className + " " + name).trim();
    }
}

function ___replaceClass(from, to)
{
    if (from != null && from.length > 0)
    {
        if (this.className == null || this.className.length == 0)
            names = new Array();
        else
            names = this.className.split(" ");

        for (var i = 0; i < names.length; i++)
        {
            if (names[i] == from)
            {
                names[i] = to;
                break;
            }
        }

        this.className = names.join(" ");
    }
}

function ___removeClass(name)
{
    this.replaceClass(name, "");
}

function ___cssUnit(value)
{
    var result      = 0;
    var stringValue = String(value);
    
    if (stringValue != "")
    {
        if (stringValue.indexOf("px") == stringValue.length - 2)
            result = parseInt(stringValue.substr(0, stringValue.indexOf("p")), 10);
        else if (stringValue.indexOf("%") == stringValue.length - 1)
            result = parseInt(stringValue.substr(0, stringValue.indexOf("%")), 10);
        else if (stringValue.indexOf("em") == stringValue.length - 2)
            result = parseInt(stringValue.substr(0, stringValue.indexOf("e")), 10);
        else if (!isNaN(stringValue))
            result = parseInt(stringValue, 10);
    }
    
    return result;  
}

function ___getAbsolutePosition(includeWindowScroll)
{
    var element = this;
    var top     = 0;
    var left    = 0;
    var width   = this.offsetWidth;
    var height  = this.offsetHeight;
    var cwidth  = this.clientWidth;
    var cheight = this.clientHeight;

    // Calculate upper left position...

    while (element != null)
    {
        $extend(element);

        var nodeName = element.nodeName.toLowerCase();
        var position = "";

        top += element.offsetTop - element.scrollTop;
        left += element.offsetLeft - element.scrollLeft;

        if (element.currentStyle.position != null)
            position = element.currentStyle.position.toLowerCase();

        if (position == "absolute" || position == "relative")
            break;

        var addBorders = false;

        if (browser.ie && nodeName == "div")
            addBorders = true;
        else if (nodeName == "td" || nodeName == "th")
            addBorders = true;
        else if (nodeName == "table")
            addBorders = true;

        if (addBorders)
        {
            var bx1 = ___cssUnit(element.currentStyle.borderLeftWidth);
            var by1 = ___cssUnit(element.currentStyle.borderTopWidth);

            if (nodeName == "div")
            {
                // All divs except the most outer one need a correction for border width...
                //
                // NOTES: Not sure about if they aren't floated and clear-fixed though,
                //        Only accounts for IE at the moment too...........................

                var container = element.selectAncestor("div");

                if (container != null)
                {
                    left += (bx1 * 2);
                    top += (by1 * 2);
                }
            }
            else
            {
                var collapsed = element.currentStyle.borderCollapse == "collapse";

                if (!collapsed)
                {
                    // Separate border model...

                    if (browser.chrome
                    || nodeName == "td" || nodeName == "th")
                    {
                        left += bx1;
                        top += by1;
                    }
                }
                else if (nodeName == "td" || nodeName == "th")
                {
                    // Collapsed border model...

                    if (bx1 % 2 != 0) bx1 += (browser.mozilla) ? -1 : 1;
                    if (by1 % 2 != 0) by1 += (browser.mozilla) ?  1 : 0;

                    if (browser.chrome)
                    {
                        left += bx1;
                        top += by1;

                        if (window.FIX_X_GOO) left += window.FIX_X_GOO;
                        if (window.FIX_Y_GOO) top += window.FIX_Y_GOO;
                    }
                    else if (browser.mozilla)
                    {
                        left += (bx1 * 2);
                        top += (by1 * 2);

                        if (window.FIX_X_MOZ) left += window.FIX_X_MOZ;
                        if (window.FIX_Y_MOZ) top += window.FIX_Y_MOZ;
                    }
                    else
                    {
                        // left += (bx1 / 2);

                        var tbl = element.selectAncestor("table");
                        var bdr = ___cssUnit(tbl.currentStyle.borderTopWidth);

                        if (bdr == 0)
                            top += by1;

                        if (window.FIX_X_IE7 != null) left += window.FIX_Y_IE7;
                        if (window.FIX_Y_IE7 != null) top += window.FIX_Y_IE7;
                    }
                }
            }
        }

        element = element.offsetParent;
    }

    if (includeWindowScroll)
    {
        // If the window is scrolled make scroll position adjustments...
        top -= document.body.scrollTop;
        left -= document.body.scrollLeft;
    }

    return {
                "top":          top,
                "left":         left,
                "width":        width,
                "height":       height,
                "bottom":       (top + height),
                "right":        (left + width),
                "clientWidth":  cwidth,
                "clientHeight": cheight
          };
}

function ___getSelectionStart() 
{
    var position = -1;
    
    if (this.selectionStart)
	    position = this.selectionStart;
	else
	    position = Math.abs(document.selection.createRange().moveStart("character", -1000000));
    
    return position;
}

function ___getSelectionEnd()
{
    var position = -1;
    
    if (this.selectionEnd)
	    position = this.selectionEnd;
	else
	    position = Math.abs(document.selection.createRange().moveEnd("character", -1000000));
    
    return position;
}

function ___getSelection()
{
    var seltext = "";

    if (window.getSelection)
        seltext = window.getSelection();
    else if (document.getSelection)
        seltext = document.getSelection();
    else if (document.selection)
        seltext = document.selection.createRange().text;
    
    return seltext;
}

function ___setSelection(start, end)
{
    if (window.browser.gecko) 
    {
	    if (end == null)
		    end = start;

	    this.setSelectionRange(start, end);
    } 
    else 
    {
	    var range = this.createTextRange();
	    range.collapse(true);
	    range.moveStart("character", start);
	    range.moveEnd("character", end - start);
	    range.select();
    }
}

function ___getIndex()
{
    var index = 0;

    var sibling = this.selectPreviousSibling();

    while (sibling != null)
    {
        sibling = sibling.selectPreviousSibling();
        index++;
    }

    return index;
}

function ___indexOfBehaviour(element, name)
{
    var index = -1;
    var count = element.behaviours.length;
    
    for (var i = 0; i < count; i++)
    {
        if (element.behaviours[i].toString() == name)
        {
            index = i;
            break;
        }
    }
    
    return index;
}

function ___hasBehaviour(name)
{
    return ___indexOfBehaviour(this, name) >= 0;
}

function ___addBehaviour(behaviour)
{
    this.behaviours.push(behaviour);
}

function ___removeBehaviour(behaviour)
{
    var index = ___indexOfBehaviour(this, behaviour.toString());
    
    if (index >= 0)
        this.behaviours.splice(index, 1);
}

function ___getBehaviour(name)
{
    var behaviour = null;
    var index = ___indexOfBehaviour(this, name);
    
    if (index >= 0)
        behaviour = this.behaviours[index];
    
    return behaviour;
}

function ___keycode(e)
{
    var value = null;
    
    if (e.type != "keypress")
        value = e.keyCode;
    else if (e.charCode)
        value = ___unicodeToKeyCode(e.charCode);
    else
        value = ___unicodeToKeyCode(e.keyCode);

    return value;
}

function ___unicode(e)
{
    var value = null;
    
    switch (true)
    {
        case e.type.toLowerCase() == "keyup":
        case e.type.toLowerCase() == "keydown":
        
            value = ___keyCodeToUnicode(e.keyCode, e.shiftKey);
            break;
            
        case !e.charCode:
        
            value = e.keyCode;
            break;
            
        default:
        
            value = e.charCode;
            break;
    }
        
    return value;
}

function ___character(e)
{
    var character = "";

    if (e.unicode)
        character = String.fromCharCode(e.unicode);
    
    return character;
}

function ___alpha(e)
{
    var result = false;
    
    if (e.unicode)
    {
        result = (
                     (e.unicode >= 65 && e.unicode <= 90) 
                  || (e.unicode >= 97 && e.unicode <= 122)
                 );
    }
        
    return result;
}

function ___numeric(e)
{
    var result = false;
    
    if (e.unicode)
        result = (e.unicode >= 48 && e.unicode <= 57);
        
    return result;
}

function ___alphanumeric(e)
{
    return (e.alpha || e.numeric);
}

function ___navigation(e)
{
    var result = false;
    
    if (e.keycode)
    {
        result = (
                  (e.keycode == 8 ||                    // Backspace
                   e.keycode == 9 ||                    // Tab
                   e.keycode == 46)   ||                // Delete
                  (e.keycode >= 35 && e.keycode <= 40)  // Home, End, Arrows
                 );
    }
    
    return result;
}

function ___fn(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode >= 112 && e.keycode <= 123);
        
    return result;
}

function ___arrow(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode >= 37 && e.keycode <= 40);
        
    return result;
}

function ___leftArrow(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 37);
        
    return result;
}

function ___upArrow(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 38);
        
    return result;
}

function ___rightArrow(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 39);
        
    return result;
}

function ___downArrow(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 40);
        
    return result;
}

function ___backspace(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 8);
        
    return result;
}

function ___space(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 32);
        
    return result;
}

function ___delete(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 46);
        
    return result;
}

function ___tab(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 9);
        
    return result;
}

function ___enter(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 13);
        
    return result;
}

function ___escape(e)
{
    var result = false;
    
    if (e.keycode)
        result = (e.keycode == 27);
        
    return result;
}

function ___modifier(e)
{
    var result = false;
    
    switch (e.keycode)
    {
        case 16: // Shift
        case 17: // Ctrl
        case 18: // Alt
            result = true;
            break;
    }
    
    return result;
}

function ___control(e)
{
    var result = false;
    
    if (e.unicode)
        result = (e.unicode < 32);
        
    return result;
}

function ___home(e)
{
    var result = false;
    
    if (e.keyCode)
        result = (e.keyCode == 36);
        
    return result;
}

function ___end(e)
{
    var result = false;
    
    if (e.keyCode)
        result = (e.keyCode == 35);
        
    return result;
}

function ___text(e)
{
    return (!(e.ctrlKey) && !(___navigation(e) || ___modifier(e) || ___control(e) || ___fn(e)));
}

function ___keyCodeToUnicode(value, shiftKey)
{
    var unicode = 0;
    
    if (value >= 65 && value <= 90) // A-Z
    {
        unicode = (shiftKey) ? value : value + 32;
    }
    else if (value == 32) // SPACE
    {
        unicode = 32;
    }
    else if (value == 8) // Backspace
    {
        unicode = 8;
    }
    else if (value == 9) // Tab
    {
        unicode = 9;
    }
    else if (value == 13) // Enter
    {
        unicode = 13;
    }
    else if (value == 27) // Esc
    {
        unicode = 27;
    }
    else if (value == 46) // Delete
    {
        unicode = 127;
    }
    else if (value == 109 || value == 189)  // - _
    {
        unicode = (shiftKey) ? 95 : 45;
    }
    else if (value == 107 || value == 61)  // = +
    {
        unicode = (shiftKey) ? 43 : 61;
    }
    else if (value == 219) // [ {
    {
        unicode = (shiftKey) ? 123 : 91;
    }
    else if (value == 221) // ] }
    {
        unicode = (shiftKey) ? 125 : 93;
    }
    else if (value == 16 || value == 186) // ; :
    {
        unicode = (shiftKey) ? 58 : 59;
    }
    else if (value == 192) // ' @
    {
        unicode = (shiftKey) ? 64 : 39;
    }
    else if (value == 222) // # ~
    {
        unicode = (shiftKey) ? 126 : 35;
    }
    else if (value == 188) // , <
    {
        unicode = (shiftKey) ? 60 : 44;
    }
    else if (value == 190) // . >
    {
        unicode = (shiftKey) ? 62 : 46;
    }
    else if (value == 191) // / ?
    {
        unicode = (shiftKey) ? 63 : 47;
    }
    else if (value == 220) // \ |
    {
        unicode = (shiftKey) ? 124 : 92;
    }
    else if (value >= 96 && value <= 105) // 0-9 (numeric keypad)
    {
        unicode = value - 48;
    }
    else if (value == 106) // * (numeric keypad)
    {
        unicode = 42;
    }
    else if (value == 107) // - (numeric keypad)
    {
        unicode = 43;
    }
    else if (value == 110) // . (numeric keypad)
    {
        unicode = 46;
    }
    else if (value == 111) // / (numeric keypad)
    {
        unicode = 47;
    }
    else if (value >= 48 && value <= 57)
    {
        if (!shiftKey)
        {
            unicode = value;  // 0-9
        }
        else
        {
            // English keyboard layout
            // These values are incorrect if US layout keyboard
            switch (value)
            {
                case 48:
                    unicode = 41;   // )
                    break;
                case 49:
                    unicode = 33;   // !
                    break;
                case 50:
                    unicode = 34;   // "
                    break;
                case 51:
                    unicode = 163;  // �
                    break;
                case 52:
                    unicode = 36;   // 
                    break;
                case 53:
                    unicode = 37;   // %
                    break;
                case 54:
                    unicode = 94;   // ^
                    break;
                case 55:
                    unicode = 38;   // &
                    break;
                case 56:
                    unicode = 42;   // *
                    break;
                case 57:
                    unicode = 40;   // (
                    break; 
            }
        }
    }
    
    return unicode;
}

function ___unicodeToKeyCode(value)
{
    var keycode = null;
    
    if (value >= 65 && value <= 90)         // A-Z
    {
        keycode = value;
    }
    else if (value >= 97 && value <= 122)   // a-z
    {
        keycode = value - 32;
    }
    else if (value >= 48 && value <= 57)    // 0-9
    {
        keycode = value;
    }
    else
    {
        switch (value)
        {
            case 32:
                keycode = 32;   // SPACE
                break;          
            case 13:
                keycode = 13;   // Enter
                break;          
            case 8:
                keycode = 8;    // Backspace
                break;          
            case 127:
                keycode = 46;   // Delete
                break;          
            case 9:
                keycode = 9;    // Tab
                break;          
            case 27:
                keycode = 27;   // Esc
                break;          
            case 41:
                keycode = 48;   // )
                break;
            case 33:
                keycode = 49;   // !
                break;
            case 34:
                keycode = 50;   // "
                break;
            case 163:
                keycode = 51;   // �
                break;
            case 36:
                keycode = 52;   // 
                break;
            case 37:
                keycode = 53;   // %
                break;
            case 94:
                keycode = 54;   // ^
                break;
            case 38:
                keycode = 55;   // &
                break;
            case 42:
                keycode = 56;   // *
                break;
            case 40:
                keycode = 57;   // (
                break;
            case 91:            // [
            case 123:           // {
                keycode = 219;
                break;
            case 93:            // ]
            case 125:           // }
                keycode = 221;
                break;
            case 39:            // '
            case 64:            // @
                keycode = 192;
                break;
            case 35:            // #
            case 126:           // ~
                keycode = 222;
                break;
            case 44:            // ,
            case 60:            // <
                keycode = 188;
                break;
            case 46:            // .
            case 62:            // >
                keycode = 190;
                break;
            case 47:            // /
            case 63:            // ?
                keycode = 191;
                break;
            case 92:            // \
            case 124:           // |
                keycode = 220;
                break;
        }
    }

    return keycode;
}
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();