//Javascript functions used by the FamilyWare controls
var xmlhttpNameSearch;
var nameSearchTarget;
var divNameSearch, frameNameSearch;
var nsCount = 0;
String.prototype["trim"] = function() { return this.replace(/^\s+|\s+$/g, ''); }

var browserInfo = new function() {
    // Returns information about browser capabilities
    var _isInitialized = false;
    var _isIE = false;
    var _isWebkit = false;
    var _isGecko = false;
    var _isOpera = false;
    var _hasJava = false
    var _hasActiveX = false;
    var _flashVersion = null;

    this.isIE = function() {
        if (!_isInitialized) { init(); }
        return _isIE;
    }

    this.isWebkit = function() {
        if (!_isInitialized) { init(); }
        return _isWebkit;
    }

    this.isGecko = function() {
        if (!_isInitialized) { init(); }
        return _isGecko;
    }

    this.isOpera = function() {
        if (!_isInitialized) { init(); }
        return _isOpera;
    }

    this.hasJava = function() {
        if (!_isInitialized) { init(); }
        return _hasJava;
    }

    this.getScrollPos = function() {
        // Try IE (also works in FF and Opera)
        if (typeof (document.body.scrollTop) !== "undefined") {
            return [document.body.scrollLeft, document.body.scrollTop];
        }

        // Try Gecko and Webkit browsers
        if (typeof (window.pageXOffset) !== "undefined") {
            return [window.pageXOffset, window.pageYOffset];
        }

        // Try IE again with the documentElement object. This is available when IE is running in standards compliance mode.					
        if (typeof (document.documentElement.scrollTop) !== "undefined") {
            return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
        }
        return [0, 0];
    }

    this.getMousePos = function(evt) {
        if (typeof (window.event) !== "undefined") {
            var scrollPos = browserInfo.getScrollPos();
            return [event.clientX, event.clientY];
        }
        else {
            if (typeof (evt) !== "undefined" && typeof (evt.pageX) !== "undefined") {
                return [evt.pageX, evt.pageY];
            }
        }
        return [0, 0];
    }

    function init() {
        var agent = navigator.userAgent.toLowerCase();
        if (agent.indexOf("msie") > -1 && agent.indexOf("opera") === -1) {
            _isIE = true;
        }

        // Webkit browsers based on KHTML. 
        if ((agent.indexOf("khtml") > -1 || agent.indexOf("webkit") > -1) && (agent.indexOf("safari") > -1 || agent.indexOf("konqueror") > -1 || agent.indexOf("chrome") > -1)) {
            _isWebkit = true;
        }

        // Gecko browsers. Safari uses an user agent string very similar to Mozilla Firefox.
        if (agent.indexOf("mozilla") > -1 && agent.indexOf("gecko") > -1 && agent.indexOf("webkit") === -1 && agent.indexOf("khtml") === -1) {
            _isGecko = true;
        }

        if (agent.indexOf("opera") > -1) {
            _isOpera = true;
        }

        try {
            if (_isIE === false && navigator.javaEnabled) {
                if (navigator.javaEnabled()) { _hasJava = true; }
            }
        }
        catch (err) {
            // Try...catch is needed because if(navigator.javaEnabled) is not always
            // handled correctly in IE and thus may throw an Unexpected error.
            // window.alert(err.message);
        }

        if (typeof (ActiveXObject) !== "undefined") { _hasActiveX = true; }
        _isInitialized = true;
    }
    return this;
}

/**
* Adds an event listener to a given element.
* @param DOMElement|String Required. DOM element or element ID to add the event to.
* @param String Required. The name of the event to attach.
* @param Function Required. A pointer for the event handler.
* @param Boolean Not required. Set to true to enable event capturing.  
*/
function addEvent(el, evtName, fn, capture) {
    var _el = (typeof (el) === "string" ? $(el) : el);
    var _capture = (capture === true ? true : false);
    var _evtName = (typeof (evtName) === "string" ? evtName : "");

    if (_evtName === "") { return null; }
    if (_el && _el.attachEvent) {
        if (_evtName.substring(0, 2) !== "on") { _evtName = "on" + _evtName; }
        if (_capture) { _el.setCapture(); }
        _el.attachEvent(_evtName, fn);
    }
    if (_el && _el.addEventListener) {
        if (_evtName.substring(0, 2) === "on") { _evtName = _evtName.substring(2) };
        _el.addEventListener(_evtName, fn, _capture);
    }
}

/**
* Removes an event listener from a given element.
* @param DOMElement|String Required. The element the event was registered on.
* @param String Required. Event name to remove.
* @param Function Required. The pointer to the event handler.
* @param Boolean Not required. If event capturing was set for the event registration.
*/
function removeEvent(el, evtName, fn, capture) {
    var _el = (typeof (el) === "string" ? $(el) : el);
    var _evtName = (typeof (evtName) === "string" ? evtName : "");
    var _capture = (capture === true ? true : false);

    if (_evtName === "") { return null; }
    if (_el && _el.detachEvent) {
        if (_evtName.substring(0, 2) !== "on") { _evtName = "on" + _evtName; }
        if (_capture) { _el.releaseCapture(); }
        _el.detachEvent(_evtName, fn);
    }
    if (_el && _el.removeEventListener) {
        if (_evtName.substring(0, 2) === "on") { _evtName = _evtName.substring(2); }
        _el.removeEventListener(_evtName, fn, _capture);
    }
}

/**
* Creates a context menu. For a detailed description read http://wiki.yuki.nl/js_fn_ContextMenu.ashx
*/
var ContextMenu = function(config) {
    var _config = config;
    var _cmMainEl = null;
    var _cmWidth = 250;
    var _callerArgs = null;
    var _items = null;
    var _that = this;
    var _rendered = false;

    this.getElement = function() {
        return _cmMainEl;
    }

    this.show = function(callerArgs, evt) {
        var mousePos = browserInfo.getMousePos(evt);

        if (_cmMainEl) {
            if (!_rendered) {
                _rendered = true;
                document.body.appendChild(_cmMainEl);
                addEvent(document.body, "click", function() { _that.hide(); });
            }
            _callerArgs = callerArgs;

            // Horizontal position
            if (document.body.clientWidth - (mousePos[0] + _cmWidth) < 0) {
                if (!browserInfo.isGecko()) {
                    _cmMainEl.style.left = mousePos[0] - _cmWidth + browserInfo.getScrollPos()[0] + "px";
                }
                else {
                    _cmMainEl.style.left = mousePos[0] - _cmWidth + "px";
                }
            }
            else {
                if (!browserInfo.isGecko()) {
                    _cmMainEl.style.left = mousePos[0] + browserInfo.getScrollPos()[0] + "px";
                }
                else {
                    _cmMainEl.style.left = mousePos[0] + "px";
                }
            }

            // Vertical position
            if (!browserInfo.isGecko()) {
                _cmMainEl.style.top = mousePos[1] + browserInfo.getScrollPos()[1] + "px";
            }
            else {
                _cmMainEl.style.top = mousePos[1] + "px";
            }
            _cmMainEl.style.display = "block";
        }
        preventBubbling(evt);
    }

    this.hide = function(evt) {
        if (_cmMainEl) {
            _cmMainEl.style.display = "none";
        }
    }

    function init() {
        var tmpItem = null;
        if (typeof (_config) === "object") {
            _cmWidth = typeof (_config.width) === "number" ? _config.width : 250;
        }
        else {
            throw new Error("ContextMenu.init() failed. No valid configuration values found. Declare as follows: var t = new ContextMenu({ items: [{ labelText: 'test' },{ labelText: 'test' }] });");
        }

        // Create the context menu items place holder
        _cmMainEl = document.createElement("DIV");
        _cmMainEl.className = "contextMenu";
        _cmMainEl.style.width = _cmWidth + "px";
        _cmMainEl.style.display = "none";

        // Append items to the place holder
        if (_config.items instanceof Array) {
            for (x = 0; x < _config.items.length; x++) {
                tmpItem = createItem(_config.items[x], x);
                if (tmpItem !== null) {
                    // Add the new element to the object for later reference
                    _config.items[x].el = tmpItem;

                    // Append the item to the context menu placeholder
                    _cmMainEl.appendChild(tmpItem);
                }
            }
        }
    }

    function createItem(config, itemIndex) {
        // Creates an context menu item object. Not intended to be called directy. 'Config' must be a JSON object. The following properties are allowed:		
        // iconUrl. String. Not required. Url to the image of the icon you want displayed.
        // labelText. String. Required. The menu item text.
        // children. Object array. Not required. Child menu items.
        // onclick. Function pointer. Not required. The click event of the menu item.
        // tooltip. String. Not required. Tooltip text for the menu item.

        if (typeof (config) !== "object" && typeof (config) !== "string") {
            return null;
        }

        if (typeof (config) === "string" && config === "-") {
            // Add horizontal line to the context menu. Use a table to avoid horrible padding and margin nightmares in IE.			
            var tmp = document.createElement("TABLE");
            tmp.setAttribute("width", "100%");
            tmp.setAttribute("cellspacing", "0");
            tmp.setAttribute("cellpadding", "0");
            tmp.style.padding = "0px";
            tmp.style.margin = "0px";
            tmp.style.height = "1px";
            var tmp1 = document.createElement("TBODY");
            var tmp2 = document.createElement("TR");
            var tmp3 = document.createElement("TD");
            tmp3.style.width = "30px";
            var tmp4 = document.createElement("TD");
            tmp4.style.width = "auto";

            if (!browserInfo.isWebkit()) {
                tmp4.style.backgroundColor = "#BDBDBD";
            }
            else {
                tmp4.style.borderBottom = "1px inset #BDBDBD";
            }

            var tmp5 = document.createElement("TD");
            tmp5.className = "contextMenuExpand";
            tmp2.appendChild(tmp3);
            tmp2.appendChild(tmp4);
            tmp2.appendChild(tmp5);
            tmp1.appendChild(tmp2);
            tmp.appendChild(tmp1);
            return tmp;
        }

        var tmpContainer = document.createElement("DIV");
        var tmpTable = document.createElement("TABLE");
        var tmpTbody = document.createElement("TBODY");
        var tmpTRow = document.createElement("TR");
        var tmpTDIcon = document.createElement("TD");
        var tmpIcon = document.createElement("IMG");
        var tmpTDLabel = document.createElement("TD");
        var tmpTDExpd = document.createElement("TD");

        // Item container
        tmpContainer.className = "contextMenuItem";
        if (typeof (config.tooltip) === "string") {
            tmpContainer.setAttribute("title", config.tooltip);
        }

        tmpContainer.setAttribute("yukiCMItem", "true");
        addEvent(tmpContainer, "mouseover", cmItem_onMouseOver);
        addEvent(tmpContainer, "mouseout", cmItem_onMouseOut);

        if (typeof (config.onclick) === "function") {
            addEvent(tmpContainer, "click", function(event) {
                config.onclick(_callerArgs, _config.items[itemIndex], event);
            });
        }

        // Item content table
        tmpTable.setAttribute("border", "0");
        tmpTable.setAttribute("height", "20");
        tmpTable.setAttribute("width", "100%");
        tmpTable.setAttribute("cellspacing", "0");
        tmpTable.setAttribute("cellpadding", "0");
        tmpTable.style.margin = "0px 0px 0px 0px";
        tmpTable.style.padding = "0px 0px 0px 0px";

        // Icon
        tmpTDIcon.style.width = "24px";
        tmpTDIcon.style.verticalAlign = "top";
        if (typeof (config.iconUrl) === "string") {
            tmpTDIcon.appendChild(tmpIcon);
            tmpIcon.width = 16;
            tmpIcon.height = 16;
            tmpIcon.src = config.iconUrl;

            if (!browserInfo.isIE()) {
                tmpTDIcon.style.padding = "3px 2px 2px 2px";
            }

            // To avoid a browser not-found image, remove the image object altogether if the image was not found on the server.
            tmpIcon.onerror = function() { this.parentNode.removeChild(this); };
        }
        else { tmpTDIcon.innerHTML = "&nbsp;"; }

        // Label text
        tmpTDLabel.className = "contextMenuItemText";
        tmpTDLabel.innerHTML = typeof (config.labelText) === "string" ? config.labelText : "&nbsp;";

        // Arrow for hierarchical menu structures
        tmpTDExpd.style.width = "9px";
        if (typeof (config.children) !== "undefined") {
            tmpTDExpd.className = "contextMenuExpand contextMenuExpandIcon";
        }
        else {
            tmpTDExpd.className = "contextMenuExpand";
        }

        // Build the entire item								
        tmpTRow.appendChild(tmpTDIcon);
        tmpTRow.appendChild(tmpTDLabel);
        tmpTRow.appendChild(tmpTDExpd);
        tmpTbody.appendChild(tmpTRow);
        tmpTable.appendChild(tmpTbody);
        tmpContainer.appendChild(tmpTable);

        return tmpContainer;
    }

    function cmItem_onMouseOver(evt) {
        var el = typeof (window.event) !== "undefined" ? window.event.srcElement : evt.target;
        while (el.nodeName.toLowerCase() !== "div" && el.getAttribute("yukiCMItem") !== "true") {
            el = el.parentNode;
        }
        el.className = "contextMenuItem contextMenuItemOver";
    }

    function cmItem_onMouseOut(evt) {
        var el = typeof (window.event) !== "undefined" ? window.event.srcElement : evt.target;
        while (el.nodeName.toLowerCase() !== "div" && el.getAttribute("yukiCMItem") !== "true") {
            el = el.parentNode;
        }
        el.className = "contextMenuItem";
    }

    init();
    return this;
}

var popupFrame = new function() {
    // Hides all body content behind a semi-transparent layer and opens a page mid-center in an Iframe.
    // - Create the frame: popupFrame.show("http://www.yuki.nl");
    // - Remove the frame: popupFrame.close();
    // - Recalculate position and size: popupFrame.resize();
    // - or use auto resize: popupFrame.show("http://www.yuki.nl", true);
    var _autoResize = false;
    var _evtAttached = false
    var _resultValue = null;
    var _callbackFn = null;
    var _that = this;
    var _domEl = null;
    var _supportEl = null;
    var _isActive = false;

    this.showEl = function(el, autoResize, callbackFn) {
        _domEl = (typeof (el) === "string" ? $(el) : el);
        _ifr = document.createElement("IFRAME");

        if (autoResize === true) { _autoResize = true; }
        if (typeof (callbackFn) === "function") { _callbackFn = callbackFn; }

        // Check if there's already a popupFrame created:
        if (document.getElementById("maskLayer")) { this.close(); }

        _domEl.style.position = "absolute";
        var tmpLayer = getMaskLayer(true);
        var elWidth = extractNumbers(_domEl.style.width);
        var elHeight = extractNumbers(_domEl.style.height);

        if (elWidth == 0) { elWidth = Math.floor(document.body.clientWidth * .50); }
        if (elHeight == 0) { elHeight = Math.floor(document.body.clientHeight * .50); }

        var elTop = Math.floor(elHeight / 2) + parseInt(document.body.scrollTop);
        var elLeft = Math.floor(elWidth / 2) + parseInt(document.body.scrollLeft);

        _supportEl = $('ifr' + _domEl.id);
        if (!_supportEl) {
            _supportEl = document.createElement("IFRAME");
            _supportEl.id = 'ifr' + _domEl.id;
            document.body.appendChild(_supportEl);
        }
        _supportEl.style.display = "block";
        _supportEl.border = 0;
        _supportEl.style.position = "absolute";
        _supportEl.style.width = elWidth;
        _supportEl.style.height = elHeight;
        _supportEl.style.top = "50%";
        _supportEl.style.left = "50%";
        _supportEl.style.marginLeft = "-" + elLeft + "px";
        _supportEl.style.marginTop = "-" + elTop + "px";
        _supportEl.src = "blank.htm";
        _supportEl.style.zIndex = 50;
        _domEl.style.display = "block";
        _domEl.style.position = "absolute";
        _domEl.style.height = (elHeight + 2) + "px";
        _domEl.style.width = (elWidth + 2) + "px";
        _domEl.style.top = "50%";
        _domEl.style.left = "50%";
        _domEl.style.marginLeft = "-" + elLeft + "px";
        _domEl.style.marginTop = "-" + elTop + "px";
        _domEl.style.zIndex = 1000;
        // Attach event to document.body if auto resize is set.
        if (_autoResize && !_evtAttached) {
            addEvent(window, "resize", function(event) { _that.resize(event); });
            _evtAttached = true;
        }
        document.body.style.overflow = "hidden";
        document.body.appendChild(tmpLayer);

        // To prevent the focus is set on an underlying object
        // set the focus to the first input control we can find:
        var inputs = _domEl.getElementsByTagName("INPUT");
        if (inputs && inputs.length > 0) {
            try {
                inputs[0].focus();
            } catch (e) { }
        }
        _isActive = true;
    }

    this.show = function(url, autoResize, callbackFn, evt) {
        var theUrl = (url.indexOf("?") > -1 ? url + "&closePopupFrame=true" : url + "?closePopupFrame=true");
        if (autoResize === true) { _autoResize = true; }
        if (typeof (callbackFn) === "function") { _callbackFn = callbackFn; }

        // Check if there's already a popupFrame created:
        if (document.getElementById("maskLayer")) { this.close(); }

        // Create mask layer
        var tmpLayer = document.createElement("DIV");
        tmpLayer.id = "maskLayer";
        tmpLayer.style.width = "5000px";
        tmpLayer.style.height = "5000px";
        tmpLayer.style.backgroundImage = "url(images/transparent_50.png)";
        tmpLayer.style.backgroundRepeat = "repeat";
        tmpLayer.style.position = "absolute";
        tmpLayer.style.top = "0px";
        tmpLayer.style.left = "0px";
        tmpLayer.style.zIndex = 999;
        tmpLayer.style.textAlign = "left";
        tmpLayer.style.verticalAlign = "middle";
        tmpLayer.onclick = this.close;

        // Calculate visible area dimensions (IE)
        var ifrWidth = document.body.clientWidth * .95;
        var ifrHeight = document.body.clientHeight * .95;
        var ifrTop = (document.body.clientHeight - ifrHeight) / 2 + parseInt(document.body.scrollTop)
        var ifrLeft = (document.body.clientWidth - ifrWidth) / 2 + parseInt(document.body.scrollLeft);

        // Create and position the Iframe
        var tmpIFrame = document.createElement("IFRAME");
        tmpIFrame.id = "ifrMaskedPreview";
        tmpIFrame.frameBorder = "0";
        tmpIFrame.style.position = "absolute";
        tmpIFrame.style.zIndex = 9999;
        tmpIFrame.style.top = ifrTop + "px";
        tmpIFrame.style.left = ifrLeft + "px";
        tmpIFrame.style.width = ifrWidth + "px";
        tmpIFrame.style.height = ifrHeight + "px";
        tmpIFrame.style.border = "2px solid #FFCC00";
        tmpIFrame.src = theUrl;

        // Prevent scrolling and append object to the body.
        // Both the layer and iframe are absolute positioned
        // with an high z-index value to keep them on top of everything
        // in the document. Keep in mind to keep the z-index 
        // values of other HTML elements below 999
        document.body.style.overflow = "hidden";
        document.body.appendChild(tmpLayer);
        document.body.appendChild(tmpIFrame);

        // Attach event to document.body if auto resize is set.
        if (_autoResize && !_evtAttached) {
            addEvent(window, "resize", function() { _that.resize(event); });
            _evtAttached = true;
        }
        _isActive = true;
    }

    this.resize = function(event) {
        // Resizes and repositions the layer and frame element.
        var ifr = document.getElementById("ifrMaskedPreview");
        if (ifr) {
            var ifrWidth = document.body.clientWidth * .95;
            var ifrHeight = document.body.clientHeight * .95;
            var ifrTop = (document.body.clientHeight - ifrHeight) / 2 + parseInt(document.body.scrollTop);
            var ifrLeft = (document.body.clientWidth - ifrWidth) / 2 + parseInt(document.body.scrollLeft);

            ifr.style.top = ifrTop + "px";
            ifr.style.left = ifrLeft + "px";
            ifr.style.width = ifrWidth + "px";
            ifr.style.height = ifrHeight + "px";
        }
    }

    this.close = function() {
        // Method to destroy the popupFrame elements
        if (document.getElementById("maskLayer")) {
            document.body.removeChild(document.getElementById("maskLayer"));
            var ifr = $('ifrMaskedPreview');
            if (ifr) { document.body.removeChild(ifr); }
            if (_domEl) { _domEl.style.display = "none"; }
            if (_supportEl) { _supportEl.style.display = "none"; }
            document.body.style.overflow = "";
        }
        _isActive = false;
    }

    this.setResult = function(resultValue) {
        if (typeof (resultValue) !== "undefined") {
            _resultValue = resultValue;
            if (typeof (_callbackFn) === "function") { _callbackFn(resultValue); }
        }
        else { return _resultValue; }
        _that.close();
    }

    this.isActive = function() {
        return _isActive;
    }

    function getMaskLayer(autoClose) {
        // Create mask layer
        var tmpLayer = document.createElement("DIV");
        tmpLayer.id = "maskLayer";
        tmpLayer.style.width = "5000px";
        tmpLayer.style.height = "5000px";
        tmpLayer.style.backgroundImage = "url(images/transparent_50.png)";
        tmpLayer.style.backgroundRepeat = "repeat";
        tmpLayer.style.position = "absolute";
        tmpLayer.style.top = "0px";
        tmpLayer.style.left = "0px";
        tmpLayer.style.zIndex = 999;
        tmpLayer.style.textAlign = "left";
        tmpLayer.style.verticalAlign = "middle";
        if (autoClose === true) { tmpLayer.onclick = this.close; }
        return tmpLayer;
    }

    return this;
}

/**
* Determines whether a page was openen by the popupFrame object and should close.
* Returns true when a popupFrame instance was found and closed, false otherwise.
* Used by Toolbar.vb to determine default close action.
*/
function closePopupFrame() {
    var p = window.parent;
    if (p && typeof (p.popupFrame) != "undefined" && p.popupFrame.isActive()) {
        p.popupFrame.close();
        return true;
    }
    // We only go two levels deep, recursion is of no use in this situation.
    if (window.parent.parent) {
        var p = window.parent.parent;
        if (p && p.popupFrame && p.popupFrame.isActive()) {
            p.popupFrame.close();
            return true;
        }
    }
    return false;
}

/**
* Cross browser convenience function to prevent events from bubbling up the element hierarchy.
*   Also prevents the default value/action for that event.
* @param Event Not required. Normally this parameter is supplied by the browser.
* @usage <div onclick="javascript:moveSomeStuff(this);preventBubbling(event);">Click here</div>
*/
function preventBubbling(e) {
    if (typeof (window.event) === "undefined") {
        e.stopPropagation();
    }
    else {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
    }
    // Prevent the event from bubbling
    if (typeof (e.preventDefault) !== "undefined") { e.preventDefault(); }
}

/**
* Checks if a given element has a given CSS class defined or not.
* @param DOMElement|String The element to check its classname.
* @param String The classname to search for.
*/
function elementHasClassName(element, className) {
    var obj = (element.className ? element : (typeof (element) === "string" ? $(element) : ""));
    if (!obj || !obj.className) { return false; }
    var _names = element.className.split(/\s+/);
    for (x = 0; x < _names.length; x++) {
        if (_names[x] === className) { return true; }
    }
    return false;
}

/**
* Returns an array of nodes that match with a given CSS class name.
* @param String. The class name to search for.
* @param Boolean. True for a recursive search, false otherwise. Defaults to true.
* @param DOMElement|String. The element to start the search at. Defaults to document.body.
*/
function getElementsByClassName(className, recursive, startNode) {
    var _nodeBuilder = [];
    var _className = (typeof (className) === "string" && className !== "" ? className : "");
    var _recursive = (_recursive === false ? false : true);
    var _startNode = (startNode && startNode.nodeType === 1 ? startNode : document.body);
    if (_className !== "") { buildNodes(_startNode); }

    // Return the array
    return _nodeBuilder;

    // function to recursively look up the nodes
    function buildNodes(node) {
        if (node.nodeType && node.nodeType === 1) {
            for (var child = node.firstChild; child !== null; child = child.nextSibling) {
                if (child.nodeType === 1) {
                    if (elementHasClassName(child, _className)) { _nodeBuilder.push(child); }
                    if (_recursive && child.childNodes.length > 0) { buildNodes(child); }
                }
            }
        }
    }
}

/**
* Returns an array of nodes that match a given attribute name.
* @param String The attribute name to search for.
* @param Boolean Not required. Set to true for a recursive lookup. Defaults to true.
* @param DOMElement|String. Not required. The element to start. Defaults to document.body.
*/
function getElementsByAttribute(attr, recursive, startNode) {
    var _attr = (typeof (attr) === "string" && attr !== "" ? attr : "");
    var _recursive = (recursive === false ? false : true);
    var _startNode = (startNode && startNode.nodeType === 1 ? startNode : document.body);
    var _nodeBuilder = [];

    if (_attr !== "") { buildNodes(_startNode); }
    return _nodeBuilder;

    // function to retrieve nodes recursively    
    function buildNodes(node) {
        if (node && node.nodeType === 1) {
            for (var child = node.firstChild; child !== null; child = child.nextSibling) {
                if (child.nodeType === 1 && child.getAttribute(_attr, 0) !== null && child.getAttribute(_attr, 0) != undefined) { _nodeBuilder.push(child); }
                if (_recursive && child.childNodes.length > 0) { buildNodes(child); }
            }
        }
    }
}

/**
* Returns an array of nodes that match a given attribute name and attribute value.
* @param String Name of the attribute to look for.
* @param Mixed Attribute value to match.
* @param Boolean Not required. Set to true to do a recursive lookup. Defaults to true.
* @param DOMElement Not required. The element to start the search at. Defaults to document.body.
*/
function getElementsByAttrValue(attr, attrValue, recursive, startNode) {
    var _attr = (typeof (attr) === "string" && attr !== "" ? attr : "");
    var _attrValue = attrValue;
    var _recursive = (recursive === false ? false : true);
    var _startNode = (startNode && startNode.nodeType === 1 ? startNode : document.body);
    var _nodeBuilder = [];

    if (attr !== "") { buildNodes(_startNode); }
    return _nodeBuilder;

    // function to retrieve nodes recursively    
    function buildNodes(node) {
        if (node && node.nodeType === 1) {
            for (var child = node.firstChild; child !== null; child = child.nextSibling) {
                if (child.nodeType === 1 && child.getAttribute(_attr, 0) === _attrValue) {
                    _nodeBuilder.push(child);
                }
                if (_recursive && child.childNodes.length > 0) {
                    buildNodes(child);
                }
            }
        }
    }
}

/**
* Shorthand for creating DOM elements.
* @param string The element name to create, B or DIV for instance.
* @param Array|null Child elements to append. NB: Plain text is also, in fact, a child (text) node.
* @param Array|JSON|null An array of attribute names and values in the format: [["name","value"],["name","value"]]
* @usage
var divObj = makeNode("DIV", "Div Box", ["style","width:200px;"]);
var divObj2 = makeNode("DIV", "Div Box 2", [{ name: "style", value: "width:200px;"},{ name: "id", value: "divbox2"}]);
var divObj3 = makeNode("DIV", "Div Box 3", [["style", "width:225px;"],["id", "divbox3"]]);
var bObj = makeNode("B", "Text");
var ulObj = makeNode("UL", [makeNode("LI", "Option 1"),makeNode("LI", "Option 2")]); 
*/
function makeNode(nodeName, nodeChildren, nodeAttr) {
    var _name = nodeName;
    var _nodeAttr = (nodeAttr instanceof Array ? nodeAttr : null);
    var _children = (nodeChildren instanceof Array || typeof (nodeChildren) === "string" ? nodeChildren : null);
    var _obj = document.createElement(_name);

    if (_obj) {
        // set attributes:
        if (_nodeAttr) {
            if (_nodeAttr.length === 2 && (_nodeAttr[0] instanceof Array === false && !_nodeAttr[0].name)) {
                // Single attribute
                _obj.setAttribute(_nodeAttr[0], _nodeAttr[1]);
            } else {
                // Array of attributes:
                for (var x = 0; x < _nodeAttr.length; x++) {
                    // JSON object
                    if (_nodeAttr[x].name && _nodeAttr[x].value) {
                        _obj.setAttribute(_nodeAttr[x].name, _nodeAttr[x].value);
                    }

                    // Array element
                    if (_nodeAttr[x] instanceof Array && _nodeAttr[x].length === 2) {
                        _obj.setAttribute(_nodeAttr[x][0], _nodeAttr[x][1]);
                    }
                }
            }
        }

        // append child elements:
        if (_children) {
            if (typeof (_children) === "string") {
                _obj.appendChild(document.createTextNode(_children));
            } else if (_children instanceof Array) {
                for (var x = 0; x < _children.length; x++) {
                    if (typeof (_children[x]) === "string") {
                        _obj.appendChild(document.createTextNode(_children[x]));
                    }
                    else {
                        _obj.appendChild(_children[x]);
                    }
                }
            }
        }
    }
    return _obj;
}

var fadeAlpha = 100;
var fadeFrameTime = 15;
/**
* Fades out an element into full transparency, then hides the element (with display:none);
* @param String ID of the DOMElement to fade out.
* @param Function pointer|undefined Optional. Function to call when element is completely faded out.
* @usage fadeOutAndHide('myDiv', myFunction);
*    fadeOutAndHide('myDiv');
*/
function fadeOutAndHide(el, callback) {
    if (fadeAlpha > 0) {
        var timerFunc = "fadeOutAndHide('" + el + (typeof (callback) != "undefined" ? "'," + callback : "'") + ")";
        if (browserInfo.isIE()) {
            $(el).style.zoom = 1; // in IE this makes sure alpha is applied. Otherwise it must be explicitly positioned for it to work.
            $(el).style.filter = "alpha(opacity=" + fadeAlpha + ")";
            window.setTimeout(timerFunc, fadeFrameTime);
        }
        else if (browserInfo.isGecko()) {
            $(el).style.MozOpacity = fadeAlpha / 100;
            window.setTimeout(timerFunc, fadeFrameTime);
        }
        else if (browserInfo.isWebkit()) {
            $(el).style.WebkitOpacity = fadeAlpha / 100;
            window.setTimeout(timerFunc, fadeFrameTime);
        }
        else {
            try {
                // Css3 standard; might not be supported
                $(el).style.opacity = fadeAlpha / 100;
                window.setTimeout(timerFunc, fadeFrameTime);
            }
            catch (e) {
            }
        }
        fadeAlpha -= 10;
    }
    else {
        fadeAlpha = 100;
        $(el).style.display = "none";
        try {
            callback();
        }
        catch (e) {
        }
    }
}

/**
* Converts a string containing JSON to a JSON object instance.
* @param String Required. The string value containing the JSON to convert.
*/
function toJSON(jsonString) {
    var fn = null;
    try {
        var fn = new Function("return " + jsonString)();
    }
    catch (e) { fn = null; }
    return fn;
}

/**
* Checks if a given number is numeric or NaN (not a number).
* @return boolean True if the given string is a number, false otherwise.
* @param any The value to validate as an integer value.
*/
function isNumeric(num) {
    try {
        var nr = new Number(num);
    }
    catch (e) {
        return false;
    }
    return !isNaN(nr);
}

/**
* Extracts all numbers from a string.
* @return integer The numbers extracted from the given string.
* @param string The string to extract numbers from.
* @remarks This works for integers, do not attempt to use it for float values. Float values will become integers without conversion: 2.50 will become 250.
*/
function extractNumbers(str) {
    if (typeof (str) !== "string" || str.length == 0) {
        return NaN;
    }
    else {
        var nr = "";
        for (x = 0; x < str.length; x++) {
            if (!isNaN(str.substr(x, 1))) {
                nr += str.substr(x, 1);
            }
        }
        return new Number(nr);
    }
    return NaN;
}

/**
* Checks if a given year is a leap year.
* @return boolean True if the given year is a leap year, false otherwise.
* @param integer The year to perform a leap year check on.
*/
function isLeapYear(theYear) {
    var result = false;
    if (isNaN(theYear)) { return false; }
    if (theYear % 4 == 0) { result = true; }
    if (theYear % 100 == 0) {
        if (theYear % 400 == 0) { result = true; }
    }
    return result;
}

/**
* Returns the number of days in a given month.
* @return integer The number of days
* @param integer The month to return a number of days of.
* @param integer The year. This is used to check the number of days in a leap year for february.
* @remarks This function checks for leap years if a year value is supplied.
*/
function nrOfDaysInMonth(theMonth, theYear) {
    var nr30 = "4,6,9,11";
    if (theMonth != 2 && nr30.search(theMonth.toString()) > -1) {
        return 30;
    }
    else if (theMonth == 2) {
        if (typeof (theYear) == "number") {
            if (isLeapYear(theYear)) {
                return 29;
            }
            else { return 28; }
        }
        else { return 28; }
    }
    else { return 31; }
}

/**
* Returns the currently selected date
*/
function getCurrentDateSel(dateSelID) {
    var mainVal = $(dateSelID).value;
    var subVal = $(dateSelID + "_Month").value;
    return [mainVal, subVal];
}

/**
* Determines the previous date from the date selector control
* @param String DOM element ID of the date selector input value
* @param Integer The 'direction' to move the date to. 1 means Next; -1 means Previous.
*/
function moveDate(dateSelID, dir) {
    var conf = getCurrentDateSel(dateSelID);
    var dirFactor = dir === 1 ? 1 : -1;
    var yVal = new Number(conf[0]);
    var subVal = new Number(conf[1]);
    if (subVal == 0 || subVal == null) {
        // year mode
        yVal += dirFactor;
        if (yVal > 1753) {
            $(dateSelID).value = yVal;
            SubmitForm();
        }
    }

    if (subVal > 0 && subVal <= 12) {
        var monthVal = subVal + dirFactor;
        if (monthVal > 12) {
            $(dateSelID + "_Month").value = 1;
            $(dateSelID).value = yVal + 1;
        } else if (monthVal < 1) {
            $(dateSelID + "_Month").value = 12;
            $(dateSelID).value = yVal - 1;
            SubmitForm();
        } else {
            $(dateSelID + "_Month").value = monthVal;
        }
        SubmitForm();
    }

    if (subVal == 31 || subVal == 32) {
        // Half year
        if (subVal == 31) {
            if (dirFactor !== 1) {
                $(dateSelID).value = yVal - 1;
            }
            $(dateSelID + "_Month").value = 32;
        }
        else {
            if (dirFactor == 1) {
                $(dateSelID).value = yVal + 1;
            }
            $(dateSelID + "_Month").value = 31;
        }
        SubmitForm();
    }

    if (subVal >= 21 && subVal <= 24) {
        // Quarter
        var qVal = subVal + dirFactor;
        if (qVal < 21) {
            $(dateSelID + "_Month").value = 24;
            $(dateSelID).value = yVal - 1;
        } else if (qVal > 24) {
            $(dateSelID + "_Month").value = 21;
            $(dateSelID).value = yVal + 1;
        } else {
            $(dateSelID + "_Month").value = qVal;
        }
        SubmitForm();
    }
}

/**
* Validates if the key pressed yields a valid character for use in a date value.
*/
function ValidateDate(evt) {
    var e = evt || event;
    var keyCode = e.keyCode || e.which;
    var typedChar = String.fromCharCode(keyCode);
    var allowedChars = '-1234567890';
    return (keyCode <= 31) || (allowedChars.indexOf(typedChar) >= 0);
}

/**
* Validates if the key pressed yields a valid character for use in a time value.
*/
function ValidateTime(evt) {
    var e = evt || event;
    var keyCode = e.keyCode || e.which;
    var typedChar = String.fromCharCode(keyCode);
    var allowedChars = ':1234567890';
    return (keyCode <= 31) || (allowedChars.indexOf(typedChar) >= 0);
}

/**
* Validates if the key pressed yields a valid character for use in a number value.
*/
function ValidateNumber(scale, bNonNegative, evt, allowCalculation) {
    var e = evt || event;
    var keyCode = e.keyCode || e.which;
    var typedChar = String.fromCharCode(keyCode);
    var allowedChars = '.1234567890';
    if (allowCalculation && allowCalculation === true) {
        allowedChars += '+/*%^#()'; // add, division, multiplication, modulo, power, square root.
    }
    if (scale > 0) allowedChars += ',';
    if (!bNonNegative || (allowCalculation && allowCalculation === true)) allowedChars += '-';
    var bValid = (keyCode <= 31) || (allowedChars.indexOf(typedChar) >= 0);
    return bValid;
}

/**
* Rounds the decimal parameter using 'Bankers Rounding'.
* The rounding works in the normal way except when the decimal part is 
* exactly 0.5. Then it will round to the nearest even number.
* @param Decimal 'x': The decimal to round.
* @param Decimal 'iDec': The number decimals after the sign.
*/
function FWRound(x, iDec) {
    var sign = x == 0 ? 0 : (x < 0 ? -1 : 1);
    var delta = 0.000001;
    var decFactor = Math.pow(10, iDec);
    var absolute = Math.abs(x) * decFactor;
    var floored = Math.floor(absolute + delta);
    var rounded;
    if (Math.abs(absolute - floored - 0.5) < delta) {
        if (floored % 2 == 1) {
            rounded = Math.ceil(absolute) * sign;
        }
        else {
            rounded = floored * sign;
        }
    }
    else {
        rounded = Math.round(absolute) * sign;
    }
    return rounded / decFactor;
}

/**
* Attempts to round a number from a NumberField control.
* @param Event|null Key input event object.
* @param String     DOMElement ID of the NumberField control to attempt rounding for.
* @param Integer    Charcode for rounding. Use this only when no key input event is available.
*/
function roundNumberFieldVal(evt, id, keyVal, isCalcResult) {
    var el = $(id);
    var val = el.value;
    var e = evt || (typeof (event) != "undefined" ? event : null) || null;
    var keyCode;
    var fromCalc = isCalcResult === true ? true : false;
    if (typeof (e) != "undefined" && typeof (keyVal) == "undefined") {
        keyCode = e.keyCode || e.which;
    }
    else if (typeof (keyVal) !== "undefined") {
        keyCode = keyVal;
    }
    else return;

    var tooltip = "";
    val = new String(val);
    if (val.indexOf(",") > -1) {
        val = val.replace(/,/g, ".");
    }

    var tmpVal = new Number(val);
    if (isNaN(tmpVal)) return;
    if ((e && e.ctrlKey) || typeof (keyVal) !== "undefined") {
        var strVal = new String(val);

        switch (keyCode) {
            case 37:
                val = FWRound(val, 2);
                break;
            case 38:
                val = Math.ceil(val);
                break;
            case 39:
                val = Math.round(val);
                break;
            case 40:
                val = Math.floor(val);
                break;
        }

        val = new String(val);
        if (val.indexOf(".") > -1) {
            val = val.replace(/[.]/g, ",");
        }

        var splitVals = val.split(',');
        if (splitVals[1]) {
            if (splitVals[1].length == 1) {
                val += '0';
            }
        }
        else {
            val += ',00';
        }    
            
        el.value = val;
    }
}

/**
* Attempts to make calculations, if any, in a number field control.
* Requires FormValidation.js.
*/
function calculateField(e, id) {
    var fld = $(id);
    var val;
    if (fld) {
        var restoreComma = false;
        var roundResult = false;
        val = normalizeCalcVal(fld.value);

        if (formValidation.hasLower(val) || formValidation.hasUpper(val) || !formValidation.hasNumbers(val)) {
            return;
        }

        if (val.indexOf(",") > -1) {
            val = val.replace(/,/g, ".");
            restoreComma = true;
        }

        // Square root
        if (val.substr(0, 1) == "#" && val.length > 1) {
            val = "Math.sqrt(" + val.substring(1) + ")"
        }

        // Power
        if (val.indexOf("^") > -1) {
            val = val.replace("^", ",");
            val = "Math.pow(" + val + ")";
        }

        // Pct base amount (19-%119) 
        if (val.indexOf("-%") > -1) {
            val = val.replace("-%", "%");
            var tmpVals = val.split("%");
            val = "100*" + tmpVals[1] + "/(100+" + tmpVals[0] + ")";
            roundResult = true;
        }

        // VAT from inclusive amount (19+%119)   
        if (val.indexOf("+%") > -1) {
            val = val.replace("+%", "%");
            var tmpVals = val.split("%");
            val = tmpVals[1] + "-(100*" + tmpVals[1] + "/(100+" + tmpVals[0] + "))";
            roundResult = true;
        }

        // Pct
        if (val.indexOf("%") > -1 && val.indexOf("%%") == -1) {
            var tmpVals = val.split("%");
            val = "(" + tmpVals[0] + "*" + tmpVals[1] + ")/100";
        }

        // Modulo
        if (val.indexOf("%%") > -1) {
            val = val.replace("%%", "%");
        }

        try {
            // Other calculations
            var calc = val;
            var tmp = eval(val);
            var res = 0;
            res = tmp; // make sure its a number; however isNaN might fail
            if (res == undefined) res = "";
            if ((!val || val.length == 0) || (res !== Infinity && typeof (res) === "number")) {
                var tmp = new String(res);
                if (tmp.length > 1 && tmp.indexOf(".") == tmp.length - 2) {
                    tmp += "0";
                    res = tmp;
                }

                if (restoreComma) {
                    tmp = tmp.replace(/[.]/g, ",");
                    res = tmp;
                }

                fld.value = res;
                tooltip = res != calc ? calc + " = " + res : "";
                formValidation.applyStatus(fld, 0, tooltip, "calculate");
                //alert('rounding ' + res);
                roundNumberFieldVal(null, id, 37, true); // Round on 2 decimals						
            }
            else {
                formValidation.applyStatus(fld, 3, "Geen getal of fout in formule" + "\n(0)-" + e.message, "calculate");
            }
        }
        catch (e) { formValidation.applyStatus(fld, 3, "Geen getal of fout in formule" + "\n" + e.message, "calculate"); }
    }
    else {
        if (val.length > 0) {
            formValidation.applyStatus(fld, 3, "Geen getal of fout in formule", "calculate");
        }
    }
}

function normalizeCalcVal(value) {
    if (!value || typeof (value) != "string" || value.length == 0) {
        return value;
    }
    var tmpNr = "";
    var tmpResult = [];
    var currChar = null;
    var calcChars = /[\+\*\-\/\%\^\#]/;
    var nextCalcChar = null;
    var text = value.replace(/ /g, "");
    var len = text.length;
    for (z = 0; z < text.length; z++) {
        currChar = text.substr(z, 1);
        if (calcChars.test(currChar)) {
            if ((z + 1) < text.length) {
                nextCalcChar = text.substr(z + 1, 1);
            }
            if (!calcChars.test(nextCalcChar)) {
                // normalize number
                if (tmpNr.indexOf(",") > -1 && tmpNr.indexOf(".") > -1) {
                    tmpNr = tmpNr.replace(".", "");
                    tmpNr = tmpNr.replace(",", ".");
                } else if (tmpNr.search(",") > -1) {
                    tmpNr = tmpNr.replace(",", ".");
                }
                tmpNr = removeDoubleDot(tmpNr);
                tmpResult.push(tmpNr);
                tmpResult.push(currChar);
                tmpNr = "";
            }
            else {
                tmpNr = removeDoubleDot(tmpNr);
                tmpResult.push(tmpNr);
                tmpResult.push(currChar);
                tmpResult.push(nextCalcChar);
                z += 1;
                nextCalcChar = "";
                tmpNr = "";
                continue;
            }
        }
        else {
            tmpNr += currChar;
        }
    }
    if (tmpNr.length > 0) {
        // normalize number
        if (tmpNr.indexOf(",") > -1 && tmpNr.indexOf(".") > -1) {
            tmpNr = tmpNr.replace(".", "");
            tmpNr = tmpNr.replace(",", ".");
        } else if (tmpNr.search(",") > -1) {
            tmpNr = tmpNr.replace(",", ".");
        }
        tmpResult.push(removeDoubleDot(tmpNr));
    }
    return tmpResult.join("");
}

function removeDoubleDot(tmpNr) {
    if (!tmpNr || tmpNr.length == 0) { return tmpNr; }
    var dot = /[\.]/g;
    var dotTest;
    // Prevent double dot numbers
    dotTest = tmpNr.match(dot);
    if (dotTest && dotTest.length > 1) {
        dotTest = tmpNr.split(".");
        tmpNr = "";
        for (y = 0; y < dotTest.length; y++) {
            if (y == (dotTest.length - 1)) {
                tmpNr += ".";
            }
            tmpNr += dotTest[y];
        }
    }
    return tmpNr;
}

/**
* Shorthand for document.getElementById();
*/
function $(id) {
    return document.getElementById(id);
}
function FindElement(id) { return $(id) }

function GetElementValue(id) {
    var el = $(id);
    var value;
    if (el != null) value = el.value;
    return value;
}

function SetElementValue(id, value) {
    var el = $(id);
    if (el != null) el.value = value;
}

function GetObjectElementText(el) {
    if (el != null) {
        var displayValue = el.getAttribute("displayValue");
        if (displayValue) {
            return displayValue;
        }
        if (browserInfo.isIE()) {
            return el.innerText;
        }
        else {
            return el.textContent;
        }
    }
}

function GetElementText(id) {
    return GetObjectElementText($(id));
}

function SetObjectElementText(el, value) {
    if (el != null) {
        if (browserInfo.isIE()) {
            el.innerText = value;
        }
        else {
            if (el.tagName == 'INPUT') el.value = value;
            else el.textContent = value;
        }
    }
}

function SetElementText(id, value) {
    SetObjectElementText($(id), value);
}

/**
* Hides or unhides an HTML DOM element.
* @param string HTML DOM element ID.
* @param boolean True to show the element, false to hide the element. [optional]. Defaults to false. 
* @param string CSS display value to apply. [optional]. Defaults to 'block'.
* @return void
*/
function ShowElement(id, show, display) {
    var el = $(id);
    var disp = !display ? "block" : display;
    if (el != null) el.style.display = show === true ? disp : "none";
}

function ShowElement2(id, show) {
    var el = $(id);
    if (el != null) el.style.display = show ? '' : 'none';
}

function SubmitForm() {
    try {
        document.forms[0].submit();
    }
    catch (ex) {
        window.alert(ex.description);
    }
}

function ValidateForm() {
    SetElementValue('DCValidation', 1);
    SubmitForm();
}

function FireEvent(el, eventName) {
    // On IE
    if (el.fireEvent) {
        el.fireEvent("on" + eventName);
    }
    // On Gecko based browsers
    else if (document.createEvent) {
        var evt = document.createEvent("HTMLEvents");
        if (evt.initEvent) {
            evt.initEvent(eventName, true, true);
        }
        if (el.dispatchEvent) {
            el.dispatchEvent(evt);
        }
    }
}

var xhrGLA = null;
function glaXhrCheck(ctlID, docType) {
    var el = $(ctlID);
    var hdnEl = $(ctlID.replace("_RefValue", ""));
    if (el && hdnEl && xhrGLA == null) {
        xhrGLA = xhrRequestManager.add({
            url: "FormValidationAsync.aspx",
            action: "CheckGLAType",
            qs: "CtlID=" + ctlID + (isNaN(docType) ? "" : "&Type=" + docType) + "&ID=" + hdnEl.value + "&Desc=" + el.value,
            oncallback: glaXhrCheck_onCallback
        });
    }
}

function glaXhrCheck_onCallback(success, response) {
    xhrGLA = null;
    if (success && response) {
        if (response.valid == false && (response.msg && response.msg.length > 0)) {
            formValidation.applyStatus($(response.ctlID), 3, response.msg, "checkGLA_" + response.ctlID);
        }
        else if (!response.remarks || response.remarks.length === 0) {
            formValidation.applyStatus($(response.ctlID), 0, "", "checkGLA_" + response.ctlID);
        }
        else if (response.remarks) {
            formValidation.applyStatus($(response.ctlID), 0, response.remarks, "checkGLA_" + response.ctlID);
        }
    }
}

var msgConfirmDelete;
function SubmitForDelete() {
    if (msgConfirmDelete == null || msgConfirmDelete.length == 0)
        msgConfirmDelete = 'Weet u zeker dat u deze gegevens wilt verwijderen?';
    if (confirm(msgConfirmDelete)) {
        SetElementValue('DCAction', 2);
        SubmitForm();
    }
}

function BrowseData(id, returnFunction, returnFunctionParam, width, height) {
    return BrowseDataParam(id, null, null, returnFunction, returnFunctionParam, width, height);
}

function BrowseDataParam(id, clientParam, browseParam, returnFunction, returnFunctionParam, width, height) {
    var options;
    if (width == null) width = 700;
    options = 'dialogWidth:' + width.toString() + 'px';
    if (height == null) height = 400;
    options += ';dialogHeight:' + height.toString() + 'px';
    var url = 'DataBrowser.aspx?ID=' + escape(id)
    if (clientParam != null && clientParam.length > 0 && browseParam != null && browseParam.length > 0) {
        var paramNames = browseParam.split(',');
        var paramValues = clientParam.split(',');
        if (paramNames.length == paramValues.length) {
            for (var i = 0; i < paramNames.length; i++) {
                url += '&ParamName=' + paramNames[i] + '&ParamValue=' + escape(GetElementValue(paramValues[i]));
            }
        }
        else {
            url += '&ParamName=' + browseParam + '&ParamValue=' + escape(GetElementValue(clientParam));
        }
    }

    var value = showModalDialog(url, null, options);
    if (typeof (value) != 'undefined') {
        if (returnFunction != null) {
            if (returnFunctionParam != null) {
                returnFunction(returnFunctionParam, value);
            }
            else {
                returnFunction(value);
            }
        }
    }
    return value;
}

function doRowColor(className) {
    var cls = className.toLowerCase().trim();
    if (cls.length == 0 || cls == "even" || cls == "uneven" || cls.indexOf("unread") > 0 || cls.indexOf("read") > 0 || cls.indexOf("pastduedate") > 0 || cls.indexOf("negativebalance") > 0 || cls.indexOf("incorrectbalance") > 0) {
        return true;
    }
    return false;
}

function BrowseDataOnMouseOver(evt) {
    var e = typeof (event) !== "undefined" ? event.srcElement : evt.target;
    if (e != null && e.tagName == "TD") {
        var p = e.parentNode;
        if (p != null && p.tagName == "TR") {
            var className = p.className;
            if ((className.indexOf("Even") == 0 || className.indexOf("Uneven") == 0) && className.indexOf(" ") == -1) {
                e.parentNode.className = "Selected";
            }
        }
    }
}

function BrowseDataOnMouseOut(evt) {
    var e = typeof (event) !== "undefined" ? event.srcElement : evt.target;
    if (e != null && e.tagName == "TD") {
        var p = e.parentNode;
        if (p != null && p.tagName == "TR") {
            if (p.className == "Selected") {
                p.className = ((p.rowIndex % 2) != 0) ? "Uneven" : "Even";
            }
        }
    }
}

function BrowseDataOnClick(event) {
    var e = event.target || window.event.srcElement;
    if (e.tagName == "TD") BrowseDataSelect(e.parentNode);
}

function BrowseDataSelect(row) {
    if (row != null && row.tagName == "TR") {
        if (parent && parent.popupFrame && parent.popupFrame.isActive()) {
            parent.popupFrame.setResult([row.id, row.title]);
        } else {
            window.parent.returnValue = new Array(row.id, row.title);
            window.parent.close();
        }
    }
}

function BrowseDataOnKeyPress(event) {
}

function SetBrowseResult(id, value) {
    if (value !== null) {
        SetElementValue(id, value[0]);
        SetElementValue(id + '_RefValue', value[1]);
    }
}

function AddContactList(id, value) {
    if (!value || value.length < 2) { return; }
    var separator = id.substr(0, 1);
    id = id.substr(1, id.length - 1);
    var inputValue = GetElementValue(id);
    var bInputValue = inputValue != null && inputValue.length > 0;
    if (bInputValue) inputValue += '; ';
    inputValue += value[1];
    SetElementValue(id, inputValue);
    var idsName = id + '_ids';
    var ids = $(idsName);
    if (ids != null) {
        var idValue = GetElementValue(idsName);
        var bIdValue = idValue != null && idValue.length > 0;
        if (!bInputValue || bIdValue) {
            if (bIdValue) idValue += ',';
            idValue += value[0];
            SetElementValue(idsName, idValue);
        }
    }
}

function AddLabelField(id, value) {
    var inputValue = GetElementValue(id);
    var bInputValue = inputValue != null && inputValue.length > 0;
    if (bInputValue) inputValue += ' ';
    inputValue += value[1];
    SetElementValue(id, inputValue);
}

function WriteFlash(width, height, file, link) {
    if (browserInfo.isIE()) {
        document.write('<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="');
        document.write(width);
        document.write('" height="');
        document.write(height);
        document.writeln('" viewastext>');
        document.write('<param name="movie" value="');
        document.write(file);
        document.writeln('">');
        if (link != null && link.length > 0) {
            document.write('<param name="base" value="');
            document.write(link);
            document.writeln('">');
        }
        document.writeln('</object>');
    }
    else {
        document.write('<embed src="');
        document.write(file);
        document.write('" base="');
        document.write(link);
        document.write('" width="');
        document.write(width)
        document.write('" height="');
        document.write(height);
        document.writeln('"	type="application/x-shockwave-flash"></embed>');
    }
}

function WriteTiffViewer(width, height, url) {
    if (browserInfo.isIE()) {
        document.write('<object classid="CLSID:106E49CF-797A-11D2-81A2-00E02C015623"');
        document.write('codebase="alternatiffx-1_8_2.cab#version=1,8,2,1"');
        document.write(' width="');
        document.write(width);
        document.write('" height="');
        document.write(height);
        document.writeln('" viewastext>');
        document.write('<param name="src" value="');
        document.write(url);
        document.writeln('">');
        document.writeln('</object>');
    }
    else {
        document.write('<embed src="');
        document.write(url);
        document.write('" width="');
        document.write(width)
        document.write('" height="');
        document.write(height);
        document.writeln('" type="image/tiff"></embed>');
    }
}

function WritePDFViewer(width, height, url) {
    if (browserInfo.isIE()) {
        document.write('<object classid="CLSID:CA8A9780-280D-11CF-A24D-444553540000"');
        document.write(' type="application/pdf"');
        document.write(' width="');
        document.write(width);
        document.write('" height="');
        document.write(height);
        document.writeln('" viewastext>');
        document.write('<param name="src" value="');
        document.write(url);
        document.writeln('">');
        document.writeln('</object>');
    }
    else {
        document.write('<embed src="');
        document.write(url);
        document.write('" width="');
        document.write(width)
        document.write('" height="');
        document.write(height);
        document.writeln('" type="application/pdf"></embed>');
    }
}

function GetXmlHttpRequestObject() {
    var xmlhttp = null;
    if (browserInfo.isIE()) {
        try {
            xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
        }
        catch (err) {
            try {
                xmlhttp = new ActiveXObject("MSXML.XMLHTTP");
            }
            catch (err2) { }
        }
    }
    else {
        if (typeof (XMLHttpRequest) !== "undefined") {
            xmlhttp = new XMLHttpRequest();
        }
    }
    return xmlhttp;
}

function DoAsyncXmlRequest(xmlhttp, target, callbackFunction) {
    xmlhttp.open("GET", target);
    if (typeof (callbackFunction) == "function") {
        xmlhttp.onreadystatechange = callbackFunction;
    }
    xmlhttp.send(null);
}

function GetAbsoluteElementPosition(el) {
    for (var lx = 0, ly = 0; el != null; el = el.offsetParent) {
        lx += el.offsetLeft;
        ly += el.offsetTop;
        if (browserInfo.isIE()) {
            lx += el.clientLeft;
            ly += el.clientTop;
        }
        if (el.tagName.toLowerCase() == 'div') {
            if (el.scrollLeft > 0) lx -= el.scrollLeft;
            if (el.scrollTop > 0) ly -= el.scrollTop;
        }
    }
    return { x: lx, y: ly };
}

function getPageSize() {
    var xScroll, yScroll;
    if (window.innerHeight && window.scrollMaxY) {
        xScroll = document.body.scrollWidth;
        yScroll = window.innerHeight + window.scrollMaxY;
    } else if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
        xScroll = document.body.scrollWidth;
        yScroll = document.body.scrollHeight;
    } else if (document.documentElement && document.documentElement.scrollHeight > document.documentElement.offsetHeight) { // Explorer 6 strict mode
        xScroll = document.documentElement.scrollWidth;
        yScroll = document.documentElement.scrollHeight;
    } else { // Explorer Mac...would also work in Mozilla and Safari
        xScroll = document.body.offsetWidth;
        yScroll = document.body.offsetHeight;
    }
    var windowWidth, windowHeight;
    if (self.innerHeight) { // all except Explorer
        windowWidth = self.innerWidth;
        windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
        windowWidth = document.documentElement.clientWidth;
        windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
        windowWidth = document.body.clientWidth;
        windowHeight = document.body.clientHeight;
    }
    // for small pages with total height less then height of the viewport
    if (yScroll < windowHeight) {
        pageHeight = windowHeight;
    } else {
        pageHeight = yScroll;
    }
    // for small pages with total width less then width of the viewport
    if (xScroll < windowWidth) {
        pageWidth = windowWidth;
    } else {
        pageWidth = xScroll;
    }
    return [pageWidth, pageHeight, windowWidth, windowHeight];
}

function HandleNameSearchResult() {
    if (nameSearchTarget == null || xmlhttpNameSearch == null || xmlhttpNameSearch.readyState != 4) return;
    var response = xmlhttpNameSearch.responseText;
    if (response == null || response.length == 0) //DelayedHideNameSearch();

        var style;
    if (divNameSearch == null) {
        divNameSearch = document.createElement("div")
        divNameSearch.className = "NameSearch";
        divNameSearch.setAttribute('nsTarget', nameSearchTarget.id);
        document.body.appendChild(divNameSearch);
        style = divNameSearch.style;
        style.position = 'absolute';
        style.height = "125px";
        style.borderColor = '#808080';
        style.borderStyle = 'solid';
        style.backgroundColor = '#FDFDFD';
        style.borderWidth = '1px';
        style.overflow = 'auto';
    }
    else {
        style = divNameSearch.style;
        divNameSearch.scrollTop = 0;
    }
    divNameSearch.innerHTML = response;

    // Prevent namesearch layer to be hidden while scrolling
    addEvent(divNameSearch, "onscroll", function() { bDontHideNameSearch = true; });
    addEvent(divNameSearch, "onmouseout", function() { bDontHideNameSearch = false; });
    addEvent(document, "onclick", function() { HideNameSearch(); });

    // Make sure the anchors fire the onchange event for the text inputfield.
    var anchors = divNameSearch.getElementsByTagName("A");
    for (var x = 0; x < anchors.length; x++) {
        try {
            addEvent(anchors[x], "click", function() { FireEvent(nameSearchTarget, "change") });
        }
        catch (e) { alert(e.message); }
    }

    var pos = GetAbsoluteElementPosition(nameSearchTarget);
    var sizeOfDocument = getPageSize();
    style.left = pos.x - 3;

    if (parseInt(pos.y) + parseInt(style.height) > parseInt(sizeOfDocument[3])) {
        style.top = pos.y - 2 - parseInt(style.height);
    } else {
        style.top = pos.y + nameSearchTarget.offsetHeight - 2;
    }

    // Set minimum width
    style.width = nameSearchTarget.offsetWidth + 20;
    if (extractNumbers(style.width) < 300) {
        style.width = "300px";
    }

    style.visibility = 'visible';
    style.display = 'inline';
    style.zIndex = 1;


    if (frameNameSearch == null) {
        frameNameSearch = document.createElement("iframe")
        frameNameSearch.src = "blank.htm";
        frameNameSearch.border = 0;
        document.body.appendChild(frameNameSearch);
        nameSearchTarget.focus();
    }
    var fstyle = frameNameSearch.style;
    fstyle.visibility = 'visible';
    fstyle.position = 'absolute';
    fstyle.left = style.left;
    fstyle.top = style.top;
    fstyle.height = style.height;
    fstyle.width = style.width;
    fstyle.display = 'inline';
    fstyle.zindex = -1;
}

var bDontHideNameSearch = false;
function HideNameSearch() {
    if (bDontHideNameSearch) return;
    if (divNameSearch != null) {
        divNameSearch.style.visibility = 'hidden';
    }
    if (frameNameSearch != null) {
        frameNameSearch.style.visibility = 'hidden';
    }
}

function DelayedHideNameSearch() {
    setTimeout('HideNameSearch()', 200);
}

function SearchElementChanged() {
    if (nameSearchTarget == null) return;
    FireEvent(nameSearchTarget, "change");
}

var nameSearchTimeoutID;
function DoNameSearch(e, id, target) {
    var key = e.keyCode || e.which;
    if (key < 48 && key != 8) return;
    if (nameSearchTimeoutID != null) clearTimeout(nameSearchTimeoutID);
    nameSearchTimeoutID = setTimeout('DoDelayedNameSearch(\'' + id + '\',\'' + target + '\')', 350);
}

function DoDelayedNameSearch(id, target) {
    nameSearchTimeoutID = null;
    nameSearchTarget = $(id);

    var value;
    if (nameSearchTarget != null) { value = nameSearchTarget.value; }
    if (value == null || value.length == 0) {
        DelayedHideNameSearch();
        return;
    }

    if (xmlhttpNameSearch == null) xmlhttpNameSearch = GetXmlHttpRequestObject();
    else xmlhttpNameSearch.abort();

    target = target + ((target.indexOf('?') < 0) ? '?' : '&');
    target = target + 'NameSearch=' + encodeURIComponent(value);
    DoAsyncXmlRequest(xmlhttpNameSearch, target, HandleNameSearchResult)
}

function NameSearchDown(event) {
    if (divNameSearch != null && divNameSearch.style.visibility == 'visible') {
        var firstChild = divNameSearch.children[0];
        if (firstChild != null) {
            bDontHideNameSearch = true;
            firstChild.focus();
        }
        event.returnValue = false;
    }
}

function NameSearchKeyDown(e) {
    if (divNameSearch == null || divNameSearch.style.visibility != 'visible') return;
    var key = e.keyCode;
    if (key === 40 || key === 38) {
        e.returnValue = false;
        var current = document.activeElement;
        if (current != null) {
            var el;
            if (key == 40) el = current.nextSibling;
            else el = current.previousSibling;
            if (el != null && el.tagName == 'A') {
                el.focus();
            }
        }
    }
    else if (key === 27) {
        bDontHideNameSearch = false;
        HideNameSearch();
        nameSearchTarget.focus();
    }
}

function SelectNameSearchElement(el) {
    if (el == null || nameSearchTarget == null) return;
    SetObjectElementText(nameSearchTarget, GetObjectElementText(el));
    if (el.id && el.id.length > 0 && nameSearchTarget.id.indexOf("_RefValue") > -1) {
        var refEl = $(nameSearchTarget.id.replace("_RefValue", ""));
        if (refEl && el.id !== refEl.id) { SetObjectElementText(refEl, el.id); }
    }
    bDontHideNameSearch = false;
    HideNameSearch();
    nameSearchTarget.focus();
    if (browserInfo.isIE()) {
        var l = nameSearchTarget.value.length;
        if (l > 0) {
            var tr = nameSearchTarget.createTextRange();
            tr.moveStart('character', l);
            tr.select();
            tr.collapse(false);
        }
    }
}

function dataListRowOver(el, e) {
    if (el.className.length == 0 || el.className == 'Even' || el.className == 'Uneven') el.className += ' datalistRowHover';
}

function dataListRowOut(el, e) {
    el.className = el.className.replace(' datalistRowHover', '');
}

function ftbInsertImage(ftb, reserved) {
    var value = BrowseData('FTBInsertImage.aspx', null, null, 750, 400);
    if (typeof (value) == 'undefined') return;
    var tag = '<img alt="' + value[2] + '" src="';
    if (value[0] == 1) {
        tag += 'Picture.aspx?Type=2&ID=' + value[1];
        if (value[3] != null && value[3].length > 0) tag += '&MaxHeight=' + value[3];
        if (value[4] != null && value[4].length > 0) tag += '&MaxWidth=' + value[4];
        tag += '"';
    }
    else {
        tag += value[1] + '"';
        if (value[3] != null && value[3].length > 0) tag += ' height="' + value[3] + '"';
        if (value[4] != null && value[4].length > 0) tag += ' width="' + value[4] + '"';
    }
    tag += '>';
    ftb.InsertHtml(tag);
}

function ftbInsertLink(ftb, reserved) {
    var value = BrowseData('FTBInsertLink.aspx', null, null, 750, 400);
    if (typeof (value) == 'undefined') return;
    var tag = '<a href="';
    var url;
    if (value[0] == 1) {
        url = 'Document.aspx?ID=' + value[1];
        var accessID = value[3];
        if (accessID != null && accessID.length > 0) url += '&AccessID=' + value[3];
        tag += url + '"';
        tag += ' target="_blank"';
        tag += '>';
    }
    else {
        url = value[1];
        tag += url + '" target="_blank">';
    }
    var desc = value[2];
    if (desc == null || desc.length == 0) desc = url;
    tag += desc;
    tag += '</a>'
    ftb.InsertHtml(tag);
}

function ToggleDisplay(id) {
    var e = $(id);
    if (e != null) {
        if (e.style.display == 'none') {
            e.style.display = 'inline';
        }
        else {
            e.style.display = 'none';
        }
    }
}

function SetLabelListMode(mode) {
    SetElementValue('LabelListMode', mode);
    var lm;
    for (var i = 0; i <= 2; i++) {
        lm = $('LabelListMode_' + i);
        if (lm != null) lm.className = i == mode ? 'Selected' : '';
    }
    var row, parentid, img, show;
    var ll = $('LabelList');
    for (var i = 1; i < ll.rows.length; i++) {
        row = ll.rows[i];
        show = mode == row.mode;
        if (show) {
            parentid = row.getAttribute('parentid');
            if (parentid != null && parentid.length > 0) {
                img = $('img' + parentid);
                show = img.src.substr(img.src.lastIndexOf('/') + 1) == 'fw1050-10.gif';
            }
        }
        row.style.display = (show ? (browserInfo.isIE() ? 'block' : 'table-row') : 'none');
    }
}

var fnExpandLabelList = null;
function ShowLabelList(mode) {
    var pos = GetAbsoluteElementPosition($('LabelListTabs'));
    var ll = $('divLabelList');
    if (ll == null) {
        return;
    }
    if (ll.style.display == 'none') {
        ll.style.top = pos.y - 1;
        ll.style.width = 185;
        ll.style.left = pos.x - 185;
        ll.style.display = 'block';
        if (fnExpandLabelList != null) {
            fnExpandLabelList(true);
        }
        SetLabelListMode(mode);
        $('LabelListTab' + mode).className = 'LabelListTabActive';
    }
    else {
        var llm = $('LabelListMode');
        if (llm == null || mode == -1) {
            ll.style.display = 'none';
            if (fnExpandLabelList != null) fnExpandLabelList(false);
            for (i = 0; i <= 2; i++) {
                if ($('LabelListTab' + i) != null) {
                    $('LabelListTab' + i).className = 'LabelListTab';
                }
            }
        }
        else {
            var curMode = GetElementValue('LabelListMode');
            if (curMode == mode) {
                ll.style.display = 'none';
                if (fnExpandLabelList != null) fnExpandLabelList(false);
                $('LabelListTab' + mode).className = 'LabelListTab';
            }
            else {
                SetLabelListMode(mode);
                var i, tab;
                for (i = 0; i <= 3; i++) {
                    tab = $('LabelListTab' + i);
                    if (tab != null) {
                        if (i == mode) tab.className = 'LabelListTabActive';
                        else tab.className = 'LabelListTab';
                    }
                }
            }
        }
    }
}

function ToggleSection(imgname, secname) {
    var sec = $(secname);
    if (sec != null) {
        if (sec.style.display == 'none') {
            sec.style.display = 'inline';
            $(imgname).src = 'images/collapse-16.gif';
        }
        else {
            sec.style.display = 'none';
            $(imgname).src = 'images/expand-16.gif';
        }
    }
}

function FWInsertAtCaret(ctl, text) {
    if (ctl.createTextRange && ctl.caretPos) {
        var caretPos = ctl.caretPos;
        caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == '' ? text + ' ' : text;
    }
    else {
        ctl.focus();
        if (ctl.value.length > 0) { ctl.value = ctl.value + " " + text; } else { ctl.value = text; }
    }
}

function FWStoreCaret(ctl) {
    if (ctl.createTextRange) { ctl.caretPos = document.selection.createRange().duplicate(); }
}

function FWPad2(i) {
    var res = i.toString();
    if (i < 10) res = '0' + res;
    return res;
}

function GetFrameWindow(frame) {
    if (browserInfo.isIE()) {
        return document.frames[frame.name];
    }
    else {
        if (frame.contentWindow) {
            return frame.contentWindow;
        } else { return frame; }
    }
}

function FWGetFrameLocation(frame) {
    var loc = GetFrameWindow(frame).location.href;
    var iStart = loc.lastIndexOf('/');
    var iEnd = loc.indexOf('?');
    if (iEnd >= 0) {
        var params = loc.substring(iEnd + 1).split('&');
        loc = loc.substring(iStart + 1, iEnd);
    }
    else loc = loc.substring(iStart + 1);
    return { filename: loc, queryparams: params }
}

function FWMatchUrl(loc, filename, params) {
    var bMatch = loc.filename.toLowerCase() == filename.toLowerCase();
    if (bMatch && params != null) {
        var queryparams = loc.queryparams;
        if (queryparams != null) {
            params = params.split('&');
            var bParamMatch;
            for (var i = 0; i < params.length; i++) {
                bParamMatch = false;
                for (var j = 0; j < queryparams.length; j++) {
                    if (queryparams[j].toLowerCase() == params[i].toLowerCase()) {
                        bParamMatch = true;
                        break;
                    }
                }
                if (!bParamMatch) {
                    bMatch = false;
                    break;
                }
            }
        }
    }
    return bMatch;
}

function disableNode(parentName) {
    var elements = new Array('table', 'tr', 'td', 'select', 'input');
    var element, children, parent, i, j;
    parent = $(parentName);
    if (parent != null) {
        parent.disabled = true;
        for (i = 0; i < elements.length; i++) {
            element = elements[i];
            children = parent.getElementsByTagName(element);
            if (children != null) {
                for (j = 0; j < children.length; j++) {
                    children[j].disabled = true;
                }
            }
        }
    }
}

/**
* Determines when the focus needs to shift to another input field of the same type.
*/
function clieOpNextField(nextFieldID, text, maxLen, doSelect) {
    var _max = (typeof (maxLen) === "number" ? maxLen : 4);
    if (text && text.length === _max) {
        var field = $(nextFieldID);
        if (typeof (doSelect) === "undefined" || doSelect === true) {
            field.select();
        }
        field.focus();
    }
}

/**
* Clears all default text input captions to prevent them
* from being submitted as real values.
*/
function clearTICaptions() {
    // Clear text input captions
    var els = document.forms[0].getElementsByTagName("INPUT");
    for (x = 0; x < els.length; x++) {
        if (els[x].type == "text") {
            var txt = els[x].getAttribute("tiText");
            if (txt && !manageTICaption(els[x], 2)) {
                els[x].value = "";
            }
        }
    }
}

/**
* Manages the state of an inputbox which has text input caption enabled, like search boxes.
* @param DOMElement The INPUT element to apply the state change to
* @param Integer The state action to take.
*/
function manageTICaption(el, action) {
    var tiText = el.getAttribute("tiText");
    switch (action) {
        case 0: // clear
            if (el.value == tiText || el.value == "") {
                el.value = "";
                el.className = el.getAttribute("defaultCss");
            }
            break;
        case 1: // restore
            if (el.value.length === 0) {
                el.value = el.getAttribute("tiText");
                var css = el.getAttribute("defaultCss");
                el.className = (css.length > 0 ? css + " " + " tiCaption" : "tiCaption");
            }
            break;
        case 2: // determine prevention of posting of text input caption
            if (el.value == el.tiText && el.className !== el.getAttribute("defaultCss")) {
                return false;
            }
            else return true;
    }
}

function getCellText(cellID, e) {
    var _cellRow = null;
    var _el = $(cellID);
    var _nodeBuilder = [];
    var _cellText = "";
    var _cellIndex = 0;

    // Get its parent table element
    _cellRow = _el;
    while (_cellRow != null && _cellRow.tagName != "TR") {
        _cellRow = _cellRow.parentNode;
    }

    // Extracts all text from the cell. Do this
    // the DOM way to have it working in all
    // browsers (eg, don't use innerText or innerHTML)
    // and filter can work even if HTML markup is applied.				
    function extractText(node) {
        if (node && (node.nodeType === 1 || node.nodeType === 3)) {
            for (var child = node.firstChild; child !== null; child = child.nextSibling) {
                if (child.nodeType === 3) { _nodeBuilder.push(child.nodeValue); }
                if (child.childNodes.length > 0) { extractText(child); }
            }
        }
    }

    extractText(_el);
    _cellText = _nodeBuilder.join("");

    // Get column ordinal index:
    for (var start = _el; start != null; start = start.previousSibling) {
        _cellIndex += 1;
    }

    return {
        "text": _cellText,
        "cellID": cellID,
        "cellIndex": _cellIndex,
        "rowID": _cellRow ? _cellRow.id : ""
    };
}

var lastCellIndex = -1;
function filterDatalist(cellID, e) {
    var _list = null;
    var _el = $(cellID);
    var _nodeBuilder = [];
    var _cellText = "";
    var _cellIndex = 0;
    var _currIndex = -1;
    var _currText = "";

    // Get its parent table element
    _list = _el;
    while (_list != null && _list.tagName != "TABLE") {
        _list = _list.parentNode;
    }

    if (!_list) { return; }

    // Extracts all text from the cell. Do this
    // the DOM way to have it working in all
    // browsers (eg, don't use innerText or innerHTML)
    // and filter can work even if HTML markup is applied.				
    function extractText(node) {
        if (node && (node.nodeType === 1 || node.nodeType === 3)) {
            for (var child = node.firstChild; child !== null; child = child.nextSibling) {
                if (child.nodeType === 3) { _nodeBuilder.push(child.nodeValue); }
                if (child.childNodes.length > 0) { extractText(child); }
            }
        }
    }

    extractText(_el);
    _cellText = _nodeBuilder.join("");

    // Get column ordinal index:
    for (var start = _el; start != null; start = start.previousSibling) {
        _cellIndex += 1;
    }

    lastCellIndex = _cellIndex;
    // Run through all rows in the table, hide all which are not applicable
    var tbody = _list.getElementsByTagName("TBODY")[0];

    for (tr = tbody.firstChild; tr != null; tr = tr.nextSibling) {
        if (tr.tagName == "TR" && tr.style.display != "none") {
            var imgs = getElementsByAttribute("dfli", true, tr);
            for (x = 0; x < imgs.length; x++) {
                imgs[x].outerHTML = " ";
            }
        }
    }

    for (tr = tbody.firstChild; tr != null; tr = tr.nextSibling) {
        if (tr.tagName != "TR") { continue; }
        _currIndex = 0;
        for (td = tr.firstChild; td != null; td = td.nextSibling) {
            _currIndex += 1;
            if (td.tagName != "TD") {
                if (td.tagName == "TH" && _currIndex == _cellIndex) {
                    var cancelFilterImg = document.createElement("IMG");
                    cancelFilterImg.style.position = "absolute";
                    cancelFilterImg.src = "images/Cancel-Filter-cursor.png";
                    cancelFilterImg.style.left = (td.offsetLeft + td.offsetWidth) - 24;
                    cancelFilterImg.style.top = td.offsetTop + 2;
                    cancelFilterImg.alt = "Cancel filter";
                    cancelFilterImg.border = 1;
                    cancelFilterImg.setAttribute("onclick", "clearFilter('" + _list.id + "');event.cancelBubble=true;event.returnValue=false;");
                    td.appendChild(cancelFilterImg);
                }
                else if (td.tagName == "TH") {
                    td.style.backgroundImage = "";
                }
                continue;
            };
            _currText = "";
            _nodeBuilder = [];
            if (_currIndex == _cellIndex) {
                extractText(td);
                if (_nodeBuilder.length > 0) { _currText = _nodeBuilder.join(""); }
                if (_currText == _cellText) {
                    tr.style.display = browserInfo.isIE() ? "block" : "table-row";
                }
                else {
                    tr.style.display = "none";
                }
                break;
            }
        }
    }

    // Correct banding (alternate row coloring)
    var visibleTRCount = 0;
    for (tr = tbody.firstChild; tr != null; tr = tr.nextSibling) {
        if (tr.tagName == "TR" && (tr.className == "Even" || tr.className == "Uneven") && tr.style.display != "none") {
            visibleTRCount += 1;
            tr.className = visibleTRCount % 2 == 0 ? "Even" : "Uneven";
        }
    }

    preventBubbling(e);
    return false;
}

function getSelectedText() {
    var txt = "";

    // IE: Returns selected text anywhere.
    if (document.selection) {
        var range = document.selection.createRange();
        return range.text;
    }

    // Other: Returns selected text from the document, but not per se from input fields.
    if (window.getSelection) {
        txt = window.getSelection().toString();
    }
    else if (document.getSelection) {
        txt = document.getSelection();
    }

    // Check input and textarea fields (Firefox).
    if (txt === null || txt === "") {
        // Search through input and textarea fields
        var objList = document.getElementsByTagName("INPUT");
        for (var x = 0; x < objList.length; x++) {
            txt = getFFSelection(objList[x]);
            if (txt !== "") {
                break;
            }
        }

        objList = document.getElementsByTagName("TEXTAREA");
        for (var x = 0; x < objList.length; x++) {
            txt = getFFSelection(objList[x]);
            if (txt !== "") {
                break;
            }
        }
    }

    // Return empty string if nothing works.
    return txt;

    // Function to get the selected text from a input field in Firefox.
    function getFFSelection(el) {
        if (el.selectionStart !== undefined && el.selectionEnd !== undefined) {
            return el.value.substring(el.selectionStart, el.selectionEnd);
        }
        return ""; // Not supported       
    }
}

function clearFilter(id) {
    var _list = $(id);
    var _tbody = _list.getElementsByTagName("TBODY")[0];
    var visibleTRCount = 0;
    var colCount = 0;
    for (tr = _tbody.firstChild; tr != null; tr = tr.nextSibling) {
        visibleTRCount += 1;
        if (tr.tagName == "TR") {
            colCount = 0;
            for (td = tr.firstChild; td != null; td = td.nextSibling) {
                // Remove filter icon
                colCount += 1;
                if (colCount == lastCellIndex && td.tagName == "TH") {
                    td.style.backgroundImage = "";
                }
            }
            tr.style.display = browserInfo.isIE() ? "block" : "table-row";
        }
        if (tr.className == "Even" || tr.className == "Uneven") {
            tr.styleName = visibleTRCount % 2 == 0 ? "Even" : "Uneven";
        }
    }
    lastCellIndex = -1;
}

function showFilter(cellID) {
    var _el = $(cellID);
    if (_el) {
        _el.style.verticalAlign = "top";
        var img;
        img = getElementsByAttribute("dlfi", true, _el);
        if (img.length == 0) {
            var img = document.createElement("IMG");
            img.src = "images/Filter-cursor.png";

            img.onclick = function(event) {
                filterDatalist(cellID, event);
                return false;
            };

            var left = _el.offsetWidth;
            img.style.position = "absolute";
            img.align = "absmiddle"
            img.style.top = _el.offsetTop;
            img.style.left = (_el.offsetLeft + _el.offsetWidth) - 20;
            img.setAttribute("dlfi", "1");

            if (_el.tagName == "TD") {
                _el.appendChild(img);
            }
        }
        else {
            img[0].style.display = "inline";
        }
    }
}

function hideFilter(cellID) {
    var _el = $(cellID);
    if (_el) {
        var img = getElementsByAttribute("dlfi", true, _el);
        if (img && img.length > 0) { img[0].style.display = "none"; }
    }
}
// ---------------------------------------
// Flash Player Version Detection - Rev 1.6
// Detect Client Browser type
// Copyright(c) 2005-2006 Adobe Macromedia Software, LLC. All rights reserved.
function ControlVersion() {
    var version, axo, e;
    // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry
    try {
        // version will be set for 7.X or greater players
        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
        version = axo.GetVariable("$version");
    } catch (e) { }

    if (!version) {
        try {
            // version will be set for 6.X players only
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");

            // installed player is some revision of 6.0
            // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29,
            // so we have to be careful. 

            // default to the first public version
            version = "WIN 6,0,21,0";

            // throws if AllowScripAccess does not exist (introduced in 6.0r47)		
            axo.AllowScriptAccess = "always";

            // safe to call for 6.0r47 or greater
            version = axo.GetVariable("$version");

        } catch (e) { }
    }

    if (!version) {
        try {
            // version will be set for 4.X or 5.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
            version = axo.GetVariable("$version");
        } catch (e) { }
    }

    if (!version) {
        try {
            // version will be set for 3.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
            version = "WIN 3,0,18,0";
        } catch (e) { }
    }

    if (!version) {
        try {
            // version will be set for 2.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
            version = "WIN 2,0,0,11";
        } catch (e) { version = -1; }
    }
    return version;
}

// JavaScript helper required to detect Flash Player PlugIn version information
function GetSwfVer() {
    // NS/Opera version >= 3 check for Flash plugin in plugin array
    var flashVer = null;
    if (navigator.plugins != null && navigator.plugins.length > 0) {
        if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
            var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
            var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
            var descArray = flashDescription.split(" ");
            var tempArrayMajor = descArray[2].split(".");
            var versionMajor = tempArrayMajor[0];
            var versionMinor = tempArrayMajor[1];
            var versionRevision = descArray[3];
            if (versionRevision == "") {
                versionRevision = descArray[4];
            }
            if (versionRevision[0] == "d") {
                versionRevision = versionRevision.substring(1);
            } else if (versionRevision[0] == "r") {
                versionRevision = versionRevision.substring(1);
                if (versionRevision.indexOf("d") > 0) {
                    versionRevision = versionRevision.substring(0, versionRevision.indexOf("d"));
                }
            }
            flashVer = "WIN " + versionMajor + "," + versionMinor + "," + versionRevision;
        }
    }
    else if (browserInfo.isIE() && !browserInfo.isOpera()) {
        flashVer = ControlVersion();
    }
    return flashVer;
}
// --- End of Adobe Flash Player detection ---