﻿// JScript File

/**
* ODACommonLibrary file version
* @returns the version of the current file
* @type string
*/
function ODACommonLibrary()
{
    return "1.0";
}

if(typeof SelectVersion == 'undefined' || SelectVersion() != "1.0"){
    alert("CommonLibrary.js requires Selection.js which could not be located. on page " + location.href);
}












/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////       ODATech Namespace       /////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var ODATech = {};

/**
* initilize the hidden filter select
* this creates a hidden select and loads it with all the options
* that exist in the select object and sets up requried events.
* @param {string} select: Select Element id (optional: element object)
* @param {string} txt: Text Input Element id (optional: element object)
* @param {function} onChangeName: Optional function to run after filter
* is run
*/
ODATech.initSelectFilter = function(select, txt, onChangeName) {
    var visible = $(select);
    var txt = $(txt);
    var hdn = $('hdn_' + visible.id)
    if (hdn == null) {
        //First Run
        hdn = document.createElement('select');
        hdn.id = 'hdn_' + visible.id;
        hdn.style.display = 'none';

        visible.up().appendChild(hdn);
        if (txt != null) {
            //addEventHandler(txt, 'onkeyup', 'function() { ODATech.filterSelect("' + visible.id + '","' + txt.id + '","' + onChangeName + '"); }')
            var visID, txtID;
            visID = visible.id;
            txtID = txt.id;
            Event.observe(txt, 'keyup', function() {
                ODATech.filterSelect(visID, txtID, onChangeName);
            });
        }
    }

    ODATech.clearSelect(hdn);

    for (var index = 0; index < visible.options.length; index++) {
        var optn = document.createElement("OPTION");
        optn.text = visible.options[index].text;
        optn.value = visible.options[index].value;
        if (optn.text.length > 0)
            hdn.options.add(optn);
    }
}

ODATech.filterTimer = null;
ODATech.timerRunning = false;

/**
* Runs at keyup of txt to filter a select list
* @param {string} selectID: Select Element id
* @param {string} txtID: Text Input Element id
* @param {function} onChangeName: Optional function to run after filter
* is run
* @private
*/
ODATech.filterSelect = function(selectID,txtID,onChangeName)
{
    if(ODATech.timerRunning)
    {
        clearTimeout(ODATech.filterTimer)
        ODATech.timerRunning = false;
    }
    
    ODATech.filterTimer = setTimeout('var before = $F("' + selectID + '"); ODATech.applyFilter("' + selectID + '","' + txtID + '"); if(before != $F("' + selectID + '") && ' + onChangeName + ' != null) { ' + onChangeName + '();}',500);
    ODATech.timerRunning = true;
}

/**
* clears all options from select element
* @param {string} sel: Element id (optional: element object)
* of select to load
*/
ODATech.clearSelect = function(sel)
{
	if(typeof(sel) == 'string')
	{
		sel = $(sel);
	}
	
	for (var index=sel.options.length-1; index>=0; index--)
	{
		sel.options[index] = null;
	}
	sel.selectedIndex = -1;
}

ODATech.loadSelectJSON = function(sel, JSON) {
    if (typeof (JSON) != 'object') {
        JSON = JSON.evalJSON();
    }
    sel = $(sel);

    ODATech.clearSelect(sel);

    var keys = Object.keys(JSON);
    var values = Object.values(JSON);

    for (var j = 0; j < keys.length; j++) {
        sel.options[sel.options.length] = new Option(keys[j], values[j]);
    }

}

/**
* run the filter on select element from text in text element
* @param {string} selectID: Select Element id (optional: element object)
* @param {string} txtID: Text Input Element id (optional: element object)
* @private
*/
ODATech.applyFilter = function(selectID,txtID)
{
    var visible = $(selectID);
    var before = $F(visible);
    var hdn = $('hdn_' + selectID);
    var txt = $(txtID);
    clearSelect(visible);
    
    for(var index = 0; index < hdn.options.length; index++)
    {
        var optn = document.createElement("OPTION");
        optn.text = hdn.options[index].text;
        optn.value = hdn.options[index].value;
        if(optn.text.toUpperCase().indexOf(txt.value.toUpperCase()) > -1)
            visible.options.add(optn);
    }
    
    for(var index = 0; index < visible.options.length; index++)
    {
        var optn = visible.options[index];
        if(before == optn.value)
        {
            optn.selected = true;
            break;
        }
    }
}

ODATech.initializeLookup = function(el, tableName, afterUpdateCallback, initialFilters, url, extraParams, returnMultiple, columnName, _autoRun, _admin) {
    el = $(el);
    if (el == null || typeof el != "object") {
        return;
    }
    if (url == null || url.length == 0) {
        if (_admin) {
            url = "Formbuilder/AutocompleterResultsAdmin.aspx";
        } else {
            url = "Formbuilder/AutocompleterResults.aspx";
        }
    }
    if ($(el.id + "_Options")) {
        $(el.id + "_Options").remove();
    }
    if ($(el.id + "_Loading")) {
        $(el.id + "_Loading").remove();
    }
    if ($(el.id + "_link")) {
        $(el.id + "_link").remove();
    }
    if ($(el.id + "_magnifier")) {
        $(el.id + "_magnifier").remove();
    }
    // _LookupBtn comes from SavedForm and needs to removed if this function is being called
    // for that same input.  otherwise, there could be two lookup buttons
    if (protoda.$SID(el.id + "_LookupBtn")) {
        protoda.$SID(el.id + "_LookupBtn").remove();
    }

    if (typeof (_admin) != "boolean") { _admin = false; }

    // elements added in reverse order
    el.up(0).setStyle({ "whiteSpace": "nowrap" });
    var div = new Element("DIV", { id: el.id + "_Options", 'class': 'autocomplete' });
    div.setStyle({ display: 'none', width: 'auto' });
    el.insert({ after: div });

    var span = new Element("SPAN", { id: el.id + "_Loading" });
    span.setStyle({ display: 'none' });
    span.update("<img src='/images/smallloading.gif' alt='Loading...' />");
    el.insert({ after: span });

    if (extraParams != null && extraParams.length > 0 && !extraParams.startsWith('&')) {
        extraParams = '&' + extraParams;
    }
    if (extraParams == null || typeof extraParams == "undefined") {
        extraParams = "";
    }

    if (initialFilters == null || initialFilters.length == 0) {
        initialFilters = "IsDeleted=false";
    }

    var params = {};
    if (initialFilters.isJSON()) {
        params = initialFilters.evalJSON();
    }
    else {
        var filterPairs = initialFilters.split('&');

        for (var l = 0; l < filterPairs.length; l++) {
            var keyValue = filterPairs[l].split('=');
            if (keyValue[0].indexOf('.') > -1) {
                keyValue[0] = globalReplace(keyValue[0], '\\.', '_DOT_');
            }
            if (isNaN(parseFloat(keyValue[1]))) {
                eval('params.' + keyValue[0] + ' = "' + keyValue[1] + '";');
            } else {
                eval('params.' + keyValue[0] + ' = ' + keyValue[1] + ';');
            }
        }

    }

    if (columnName == null || columnName == "NULL") { columnName = ""; }

    var lookupLink = new Element("IMG", { 'src': '/SavedFiles/magnifier.png', 'id': el.id + '_magnifier' });
    Event.observe(lookupLink, "click", function() {
        ODATech.Lookup(el.id, '', columnName, Object.toJSON(params), true, null, afterUpdateCallback, tableName, returnMultiple, null, _autoRun, _admin);
    });

    el.insert({ after: lookupLink });
    initialFilters = Object.toJSON(params);

    var autoPrompts = 'TypeTableName=' + tableName + "&ReturnColumn=" + columnName;
    autoPrompts += "&JSONFilters=" + initialFilters + extraParams;

    if (afterUpdateCallback != null &&
        typeof (afterUpdateCallback) == "string" && afterUpdateCallback.length > 0) {
        //afterUpdateCallback = afterUpdateCallback.getName();
        eval('afterUpdateCallback = ' + afterUpdateCallback + ';');
    }

    if (afterUpdateCallback != null && typeof (afterUpdateCallback) == "function") {
        return new Ajax.Autocompleter(el.id, el.id + '_Options'
        , url,
        { paramName: 'CurrentValue',
            indicator: el.id + '_Loading',
            parameters: autoPrompts,
            afterUpdateElement: function(element, selectedElement) { afterUpdateCallback(element, selectedElement); },
            onFailure: function(transport) {
                $(element).update(transport.responseText);
                if (typeof setStatusImage == "function") {
                    setStatusImage(2);
                }
            }
        });
    }
    else {
        return new Ajax.Autocompleter(el.id, el.id + '_Options'
        , url,
        { paramName: 'CurrentValue',
            indicator: el.id + '_Loading',
            parameters: autoPrompts,
            onFailure: function(transport) {
                $(element).update(transport.responseText);
                if (typeof setStatusImage == "function") {
                    setStatusImage(2);
                }
            }
        });
    }
}

/**
* applies oddRow/evenRow and headerRow colors to table rows
* @param {string} tableID: Table Element id 
* @param {boolean} hasHeaderRow: True if table should have a header row (optional: default true)
* @public
*/
ODATech.applyAlternatingRowColors = function(tableID, hasHeaderRow) {
    var table = $(tableID);

    if (table.tagName.toUpperCase() != "TABLE") {
        alert("applyAlternatingRowColors can only be called on a table");
        return;
    }
    table.hide();

    var curRow = null;

    for (var j = 0; j < table.rows.length; j++) {
        curRow = $(table.rows[j]);

        // remove all previous row colorings
        if (curRow.hasClassName("oddRow"))
            curRow.removeClassName("oddRow");

        if (curRow.hasClassName("evenRow"))
            curRow.removeClassName("evenRow");

        if (curRow.hasClassName("headerRow"))
            curRow.removeClassName("headerRow");

        // apply headerRow class
        if (j == 0 && hasHeaderRow) {
            curRow.addClassName("headerRow");
            continue;
        }

        var curRowNum = j;
        if (hasHeaderRow)
        { curRowNum--; }

        if ((curRowNum % 2) == 0)
            curRow.addClassName("evenRow");
        else
            curRow.addClassName("oddRow");
    }
    table.show();

}

ODATech.initializeAutoPopulation = function(autoPopulationPath,destinationProperty){
    var rootProperty = autoPopulationPath.split('.')[0];
    
    // find the html object that represents the rootProperty
    var objArr = $$('[id*="' + rootProperty + '"]');
    if(objArr != null)
    {
        if(objArr.tagName.toLowerCase() == "select"){
            Event.observe(objArry, 'change', function(e){alert(destinationProperty);});
        }
        else if(objArr.tagName.toLowerCase() == "input"){
            if(objArr.type.toLowerCase() == "text"){
                Event.observe(objArr, "blur", function(e){alert(destinationProperty);});
            }
            else if(objArr.type.toLowerCase() == "checkbox"){
                Event.observe(objArr, "checked", function(e){alert(destinationProperty);});
            }
        }
    }
}

ODATech.hideControl = function (ctlID){
    var curCtrl = $(ctlID);
    while(curCtrl.tagName.toLowerCase() != "tr"){
        curCtrl = curCtrl.up(0);
    }
    
    if(curCtrl != null && curCtrl.tagName.toLowerCase() == "tr"){
        curCtrl.hide();
    }
}

ODATech.initFormControls = function(){
    $$('[valuestring]').each(function(el){
        $S(el, el.readAttribute("valuestring"));
    });
}

ODATech.visible = function(element) {
    var curElement = element;
    var visible = true;
    while (curElement != null && curElement != document && curElement != window && curElement.style) {
        if (curElement.style.display == 'none') {
            visible = false;
            break;
        }
        curElement = curElement.up();
    }
    return visible;
}

ODATech.addRoundedBorder = function(element) {
    element = $(element);
    element.addClassName('boxcontent');
    var mainDiv = new Element("DIV", { "class": "main" });
    element.insert({ before: mainDiv });
    mainDiv.appendChild(element);

    element.insert({ before: '<b class="edge"><b class="b0"></b><b class="b1"></b><b class="b2"></b><b class="b3"></b><b class="b4"></b></b>' });
    element.insert({ after: '<b class="edge"><b class="b4 btm"></b><b class="b3 btm"></b><b class="b2 btm"></b><b class="b1 btm"></b><b class="b0"></b></b>' });
};

ODATech.RenderReport = function(/*string*/_element, /*int*/_reportID, /*string*/_reportName, /*array*/_params, /*string*/_queryID, /*function*/_callbackFunc, /*string*/_customEventName) {
    var options = {};

    options.autoPrompts = false;
    options.gridOnly = true;

    if (_reportID) {
        options.reportID = _reportID;
    }
    if (_reportName) {
        options.reportID = _reportName;
    }

    options.OnSuccess = _callbackFunc;

    _queryID = _queryID.toString();
    if (_queryID && _queryID.length > 0) {
        _queryID = _queryID.replace("&amp;", "&");

        options.additionalParams = "QueryID=" + _queryID;
    }
    else {
        options.additionalParams = "QueryID=0";
    }

    var prompts = "";
    if (_params) {
        for (var j = 0; j < _params.length; j++) {
            prompts += 'txtPrompt' + j.toString() + '^' + _params[j] + '~';
        }
    }
    options.promptValues = prompts;
    if (options.additionalParams != null) {
        options.additionalParams += "&Seed" + new Date().getTime();
    }
    else {
        options.additionalParams = "&Seed" + new Date().getTime();
    }
    if (_customEventName != null && _customEventName.length > 0) {
        options.customEventName = _customEventName;
        options.useDefaultEventNames = false;
    }

    ODATech.RenderSearch(_element, options);
};



//ODATech.RenderReport = function(/*string*/_element, /*int*/_reportID, /*string*/_reportName, /*array*/_params, /*string*/_queryID, /*function*/_callbackFunc) {
//    var reportParams = new Hash();
//    reportParams.set('Seed', new Date().getTime());
//    if (_reportID || _reportName) {
//        reportParams.set('ElementName', _element);
//        if (_reportID) {
//            reportParams.set('ReportID', _reportID);
//        }
//        if (_reportName) {
//            reportParams.set('ReportName', _reportName);
//        }
//        if (_queryID && _queryID.length > 0) {
//            _queryID = _queryID.replace("&amp;", "&");

//            if (_queryID.indexOf('&') == -1) {
//                reportParams.set("QueryID", _queryID);
//            } else {
//                var pairs = _queryID.split('&');
//                for (var x = 0; x < pairs.length; x++) {
//                    if (pairs[x].indexOf('=') == -1) {
//                        reportParams.set("QueryID", pairs[x]);
//                    } else {
//                        var pair = pairs[x].split('=');
//                        reportParams.set(pair[0], pair[1]);
//                    }
//                }
//            }
//        }

//        if (_params) {
//            for (var x = 0; x < _params.length; x++) {
//                reportParams.set('Parameter' + x, _params[x]);
//            }
//        }

//        $(_element).stopObserving("RenderReport:Refresh");


//        $(_element).observe("RenderReport:Refresh", function(event) {
//            if (typeof setStatusImage == "function") { setStatusImage(1); }
//            $(_element).update("<img src='./images/loading.gif' alt='Loading...' />");
//            new Ajax.Request('/FormBuilder/RenderReport.aspx', {
//                parameters: reportParams,
//                method: 'POST',
//                onSuccess: function(transport) {
//                    $(_element).update(transport.responseText);
//                    if (typeof setStatusImage == "function") {
//                        setStatusImage(0);
//                    }
//                    if (typeof _callbackFunc == "function") {
//                        _callbackFunc();
//                    }
//                },
//                onFailure: function(transport) {
//                    $(_element).update(transport.responseText);
//                    if (typeof setStatusImage == "function") {
//                        setStatusImage(2);
//                    }
//                }
//            });
//        });

//        $(_element).fire("RenderReport:Refresh");


//    } else {
//        alert("ODATech.RenderReport must have a valid Report ID or Name");
//    }
//};

ODATech.Lookup = function(
/*string*/_returnElement
    , /*string*/_objectName
    , /*string*/_columnToReturn
    , /*string*/_initialFilters
    , /*boolean*/_autoPrompts
    , /*string*/_promptColumns
    , /*string*/_callbackFunction
    , /*string (optional)*/_tableName
    , /*boolean*/_returnMultiple
    , /*long*/_reportID
    , /*bool*/_autoRun
    , /*bool*/_admin) {

    if (_objectName == null) { _objectName = ""; }
    if (_columnToReturn == null) { _columnToReturn = ""; }
    if (_tableName == null) { _tableName = ""; }
    if (_reportID == null) { _reportID = ""; }
    if (typeof (_autoRun) != 'boolean') { _autoRun = true; }
    if (typeof (_admin) != 'boolean') { _admin = false; }

    var divWindowID = "lookup_" + _objectName + "_" + _columnToReturn + "_" + _tableName + "_" + _reportID;
    new divWindow(divWindowID, "Lookup", null, null, null, true);
    //$(divWindowID).clonePosition($(_returnElement), { setHeight: false, setWidth: false });


    if (_callbackFunction != null && typeof (_callbackFunction) == "function") {
        _callbackFunction = _callbackFunction.odaGetName();
    }
    if (_callbackFunction == null || _callbackFunction.length == 0) {
        _callbackFunction = "ODATech.LookupComplete";
    }

    var params = "";
    params += "PropertyName=" + _columnToReturn;
    if (params.indexOf("ObjectName") == -1) {
        params += "&ObjectName=" + _objectName;
    }
    if (params.indexOf("InitialFilters") == -1) {
        params += "&InitialFilters=" + _initialFilters;
    }
    if (params.indexOf("PromptColumns") == -1) {
        params += "&PromptColumns=" + _promptColumns;
    }
    if (params.indexOf("AutoPrompts") == -1) {
        params += "&AutoPrompts=" + _autoPrompts;
    }
    if (params.indexOf("ElementID") == -1) {
        params += "&ElementID=" + _returnElement;
    }
    if (params.indexOf("callbackFunction") == -1) {
        params += "&callbackFunction=" + _callbackFunction;
    }
    if (params.indexOf("divWindowID") == -1) {
        params += "&divWindowID=" + divWindowID;
    }
    if (params.indexOf("TableName") == -1) {
        params += "&TableName=" + _tableName;
    }
    if (params.indexOf("ReturnMultiple") == -1) {
        params += "&ReturnMultiple=" + _returnMultiple;
    }
    if (params.indexOf("ReportID") == -1) {
        params += "&ReportID=" + _reportID;
    }

    if (params.indexOf("GridOnly") == -1) {
        params += '&GridOnly=False';
    }
    if (params.indexOf("Prefix") == -1) {
        params += "&Prefix=" + divWindowID;
    }
    if (params.indexOf("AutoRun") == -1) {
        params += "&AutoRun=" + _autoRun;
    }


    if (_admin) {
        ajaxUpdate(divWindowID + "_content", '/FormBuilder/AJAXLookupAdmin.aspx', params, null, null);
    } else {
        ajaxUpdate(divWindowID + "_content", '/FormBuilder/AJAXLookup.aspx', params, null, null);
    }
}

ODATech.LookupComplete = function(value, divWindowID) {
    hideDivWindow(divWindowID);

    if (typeof (lookupCompleteCallback) == 'function') {
        lookupCompleteCallback(value, divWindowID);
    }
}

ODATech.lookupComplete = function(value, divWindowID) {
    ODATech.LookupComplete(value, divWindowID);
}

ODATech.RenderSearch = function(/*string*/_elementID, /*obj*/_options) {
    var options = {};
    options.objectName = _options.objectName || "";
    options.initialFilters = _options.initialFilters || "";
    options.promptColumns = _options.promptColumns || "";
    options.autoPrompts = _options.autoPrompts;
    if (options.autoPrompts == null) { options.autoPrompts = true; }
    options.tableName = _options.tableName || "";
    options.GridOnly = _options.gridOnly || false;
    options.reportID = _options.reportID || 0;
    options.additionalParams = _options.additionalParams;
    options.divWindowID = _options.divID || _elementID;
    if (options.additionalParams && options.additionalParams.length > 0 && !options.additionalParams.startsWith('&')) {
        options.additionalParams = '&' + options.additionalParams;
    }
    options.OnSuccess = _options.OnSuccess || null;
    options.promptValues = _options.promptValues;
    options.autoRun = true;

    if (typeof (_options.autoRun) == 'boolean') {
        options.autoRun = _options.autoRun;
    }

    options.useDefaultEventNames = true;
    if (typeof (_options.useDefaultEventNames) == 'boolean') {
        options.useDefaultEventNames = _options.useDefaultEventNames;
    }

    var params = "";
    params += "ObjectName=" + options.objectName;
    params += "&InitialFilters=" + options.initialFilters;
    params += "&PromptColumns=" + options.promptColumns;
    params += "&AutoPrompts=" + options.autoPrompts;
    params += "&TableName=" + options.tableName;
    params += "&ReportID=" + options.reportID;
    params += '&GridOnly=' + options.GridOnly;
    params += "&divWindowID=" + options.divWindowID;
    params += "&Prefix=" + _elementID;
    params += "&PromptValues=" + options.promptValues;
    params += "&AutoRun=" + options.autoRun;
    if (typeof options.additionalParams != "undefined") {
        params += options.additionalParams;
    }


    var eventNames = new Array();
    if (options.useDefaultEventNames) {
        eventNames[eventNames.length] = "RenderSearch:Refresh";
        eventNames[eventNames.length] = "RenderReport:Refresh";
    }

    if (_options.customEventName != null && _options.customEventName.length > 0) {
        eventNames[eventNames.length] = _options.customEventName;
    }

    for (var p = 0; p < eventNames.length; p++) {
        $(_elementID).stopObserving(eventNames[p]);


        $(_elementID).observe(eventNames[p], function(event) {
            var subPrompts;
            eval('if(typeof ' + options.divWindowID + 'submitPrompts == "function"){subPrompts = ' + options.divWindowID + 'submitPrompts;}');

            if (typeof (subPrompts) == 'function') {
                subPrompts(event);
            }
            else {
                $(_elementID).update('<img src="./images/Loading.gif" alt="Loading..." />');
                ajaxUpdate(_elementID, '/FormBuilder/AJAXLookup.aspx', params, options.OnSuccess, _elementID, ODATech.RenderSearchFailed);
            }
        });
    }

    $(_elementID).fire(eventNames[0]);
}

ODATech.RenderSearchFailed = function(trans, context) {
    if ($(context)) {
        $(context).update("Failed to load search screen");
        if (odaconsole) {
            odaconsole.debug(trans);
        }
    }
}

var RenderSearchExpandList = new Array();

ODATech.RenderSearch_Expand = function(expanderElement, expanderRow, expanderCell, expanderArgs) {
    // switch the src of the expanderElement
    // toggle visibility on expanderRow
    // fire refresh event on expanderCell
    $(expanderRow).toggle();
    if ($(expanderRow).visible()) {
        $(expanderElement).src = '/images/minus.gif';
    }
    else {
        $(expanderElement).src = '/images/plus.gif';
    }

    if (RenderSearchExpandList.indexOf(expanderCell) == -1) {
        // tie event
        var reportName = expanderArgs.split('_')[1];
        var queryID = expanderArgs.split('_')[2];

        ODATech.RenderReport(expanderCell
        , null
        , reportName
        , null
        , queryID
        , null
        , 'RenderExpander:Refresh');

        RenderSearchExpandList.push(expanderCell);
    }
}

ODATech.checkForSubmit = function(_event, _containerID) {
    var odaKey = new ODAKeyCode(_event);
    if (odaKey.keyCode == odaKey.ENTER) {
        var submitBtns = $(_containerID).up(1).select('input[type="submit"]')
        if (submitBtns && submitBtns.length == 1) {
            submitBtns[0].click();
            Event.stop(_event);
        }
    }
}

ODATech.showNotes = function(_sourceEl, _noteID, _noteIdentifier, noteText, _saveFunction) {

    //var div = divWindow('EditNote' + _noteID, 'Edit Note', null, null, null, true);
    //var contentDiv = $('EditNote' + _noteID + '_content');
    $("GlobalRadEditoryContainer").show();
    noteText = globalReplace(unescape(noteText), '%22', '"');
    noteText = globalReplace(unescape(noteText), '%23', '#');
    gRadEditor.fire("ToggleScreenMode");
    gRadEditor.setFocus();
    gRadEditor.set_html(noteText);
    
    //move the cursor to the end
    var doc = gRadEditor.get_document();
    doc.execCommand("SelectAll", null, false);
    gRadEditor.getSelection().collapse();

    Telerik.Web.UI.Editor.CommandList["Save"] = function(commandName, editor, args) {
        ODATech.saveNote(gRadEditor.get_id(), _noteID, _noteIdentifier, _saveFunction);
    };
}

ODATech.saveNote = function(_tinyEditor, _noteID, _noteIdentifier, _saveCompleteFunction) {
    var context = {};
    context.saveFunction = _saveCompleteFunction;
    context.divID = "EditNote" + _noteID;
    //context.tinyEditorID = _tinyEditor;

    showLoading("Saving Note...");
    $("GlobalRadEditoryContainer").hide();

    var noteContent = gRadEditor.get_html(true).escapeHTML();
    ServerFunction("Odatech.Business.NoteFactory.SaveNote|" + noteContent + "|" + _noteIdentifier + "|" + _noteID + "|Default"
        , Object.toJSON(context));

    //ServerFunction('Save|' + getQueryStringValue('NoteIdentifier') + '|' + tinyMCE.activeEditor.getContent().escapeHTML() + '');
}

ODATech.SaveNote = function(args, context) {
    hideLoading();
    if (args == "success" && context != null && context.saveFunction != null && context.saveFunction.length > 0
        && context.saveFunction != 'null') {

        ODATech.closeNote();
        eval(context.saveFunction + "('" + context.divID + "');");
    }
    else {
        $("GlobalRadEditoryContainer").show();
    
        alert(args);
    }
}

ODATech.closeNote = function(txtAreaID) {
    var odaEditor = null;
    var divID = "";

    $("GlobalRadEditoryContainer").hide();
    gRadEditor.set_html("");
    gRadEditor.fire("ToggleScreenMode");
    /*
    for (var ed in tinyMCE.editors) {
    var editor = tinyMCE.get(ed);

        if (editor != null && editor.odaOptions != null) {
    odaEditor = editor;
    break;
    }
    }

    if (odaEditor != null) {
    divID = odaEditor.odaOptions.divID;
    tinyMCE.get(odaEditor.odaOptions.txtAreaID).remove();
    }*/
    /*
    fullScreenContainer = $(tinyMCE.activeEditor.id + "_container")
    tinyMCE.activeEditor.remove();
    fullScreenContainer.remove();
    */

    /*(if ($(divID)) {
        hideDivWindow(divID);
        $(divID + "_content").update("");
    }*/
}

ODATech.bindEvent = function(/*string*/_containerID, /*string*/_domSelectQuery, /*string*/_eventName, /*function*/_listener) {
    var bindEls = $(_containerID).select(_domSelectQuery);
    if (bindEls == null) { return; }

    for (var j = 0; j < bindEls.length; j++) {
        $(bindEls[j]).observe(_eventName, function(event) { _listener(event); });
    }
    //elements.each(function(el) {
    //    $(el).observe(_eventName, function(event) { _listener(event); });
    //});
}

ODATech.exit = function(defaultScreen) {
    var retURL = getQueryStringValue('ReturnURL');

    if (retURL != null && retURL.length > 0 && retURL != "null") {
        window.location.href = 'default.aspx?' + decodeURIComponent(retURL);
    }
    else {
        window.location.href = 'default.aspx?screen=' + defaultScreen;
    }
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////       ODATech Namespace       /////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////       ODATech.DispatchAction Namespace       //////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ODATech.DispatchAction = {};

ODATech.DispatchAction.dispatchClick = function(selectedValue, objectTableName, json) {
    // make the AJAX call
    hash = new Hash();
    hash.set("Command", "Dispatch");
    hash.set("ID", selectedValue);
    hash.set("TableName", objectTableName);
    hash.set("JSONParam", json);

    showLoading("Performing Action...");

    ajaxRequest("/DispatchActionService.aspx", hash
        , ODATech.DispatchAction.dispatchResponseHandler
        , escape(Object.toQueryString(hash.toJSON())));
}

ODATech.DispatchAction.dispatchResponseHandler = function(trans, context) {
    // trans is either the response, or prompts so we need to figure out which one
    var response = unescape(trans).replace("&amp;", "&");
    hideLoading();


    // show the prompts in a shadowbox
    var cpWindow = divWindow('DispatchPromptsWindow', 'Dispatch', null, null, null, false, true)
    var content = $('DispatchPromptsWindow_content');
    var closeButton = $('DispatchPromptsWindow_close');
    if (closeButton) {
        Event.observe(closeButton, "click", function() { showLoading("Refreshing..."); window.location.reload(); });
    }

    content.update(response);
    center('DispatchPromptsWindow_body');

    // The renderDocument when successful returns a javascript block that opens a window to the GetDocument page
    // it will also include a DIV with ID renderDocumentSuccess so that we know to hide the shadow box
    // this isn't necessary with inspections because it will either return prompts, or the results.  the user
    // will then manually hide the shadowbox
    if ($('renderDocumentSuccess') != null && typeof ($('renderDocumentSuccess')) == 'object') {
        hideDivWindow('DispatchPromptsWindow');
    }
}

ODATech.DispatchAction.saveInspectionPrompts = function(selectedAction, objectTableName) {
    if (validateGroup('DAServiceInspectionPrompt')) {
        var UserInputs = $('DispatchPromptsWindow').select('.inspectionPromptField');
        function myObj() { };
        UserInputs.each(function(s) { if ($(s) && $(s).id.length > 0) { eval('myObj.prototype.' + getTrimmedID($(s).id, "") + ' = "' + getEscapeFormInput(s) + '";'); } });

        var UserInputs = $('DispatchPromptsWindow').select('input[type="radio"]');
        UserInputs.each(function(s) { eval('myObj.prototype.' + getTrimmedID($(s).name, "") + ' = "' + protoda.$RF(s.name) + '";'); });

        var json = new myObj();

        hideDivWindow('DispatchPromptsWindow');
        showLoading("Please Wait...");

        var bodyJSON = null;
        if (typeof (BuildCustomDispatchActionJSON) == 'function') {
            bodyJSON = BuildCustomDispatchActionJSON();
        }
        else {
            var bodyJSON = new Hash(buildJSON('body', 'UserInputControl').evalJSON());
        }

        bodyJSON = bodyJSON.merge($H(json));

        hash = new Hash();
        hash.set("Command", "Dispatch");
        hash.set("ID", selectedAction);
        hash.set("TableName", objectTableName);
        hash.set("JSONParam", bodyJSON.toJSON());


        ajaxRequest("/DispatchActionService.aspx", hash
        , ODATech.DispatchAction.dispatchResponseHandler
        , null);
    }
}

ODATech.DispatchAction.saveDocumentPrompts = function(selectedAction, objectTableName) {
    var json = buildJSON($('DispatchPromptsWindow'), null, null, 'input');

    var bodyJSON = null;
    if (typeof (BuildCustomDispatchActionJSON) == 'function') {
        bodyJSON = BuildCustomDispatchActionJSON();
    }
    else {
        var bodyJSON = new Hash(buildJSON('body', 'UserInputControl').evalJSON());
    }
    
    bodyJSON = bodyJSON.merge($H(json.evalJSON()));

    hash = new Hash();
    hash.set("Command", "Dispatch");
    hash.set("ID", selectedAction);
    hash.set("TableName", objectTableName);
    hash.set("JSONParam", bodyJSON.toJSON());


    ajaxRequest("/DispatchActionService.aspx", hash
        , ODATech.DispatchAction.dispatchResponseHandler
        , null);
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////       ODATech.DispatchAction Namespace       //////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////














//////////////////////////////////////////////////////////////////////////////////////////
////////    Textbox Helper Methods
//////////////////////////////////////////////////////////////////////////////////////////
/**
* Sets focus to the element and put the cursor at the end of the current Text
* @param{input} sender: the instance of the input field on which to set focus
*/
function setFocus(sender) {
    sender = $(sender);
    if (sender.visible()) {
        sender.focus();
        sender.select();
        moveCursorToEnd(sender);
    }
}

/**
* Sets color to black and removes the mask if the sender value
* matches the mask value.
* @param{input} sender: the instance of the input field on which to clear the mask.
* @param{string} mask: value to check for.
*/
function clearMask(sender,mask) {
    sender = $(sender);
    sender.style.color = 'Black';
    if(sender.value == mask)
    {
        sender.value = '';
    }
}

/**
* If the value of sender is empty string ('') then it sets the value to the mask
* sent in and sets the color to gray.
* @param{input} sender: the instance of the input field on which to set the mask.
* @param{string} mask: value to set.
*/
function setMask(sender,mask)
{
    if(sender.value == '' || sender.value == mask)
    {
        sender.value = mask;
        sender.style.color = 'gray';
    }
}

/**
* Finds many times _char exists in _string.
* @param {string} _string: String that may contain '_char'.
* @param {char} _char: char to count instances in '_string'.
* @returns count of how many times char is found in string
* @type int
*/
function getCharCount(_string,_char)
{
    var count = 0;
    var lastIndex = -1;
    for(var j=0; j<_string.length; j++)
    {
        if(lastIndex == -1)
        {
            lastIndex = _string.indexOf(_char);
            if(lastIndex > -1){count++;}
        }
        else
        {
            var temp = _string.indexOf(_char,lastIndex+1);
            if(temp > -1)
            {
                lastIndex = temp;
                count++;
            }
        }
    }
    return count;
}

/**
* Gets previous character.
* @param {input} myField: field to get character before cursor
* @returns Character before cursor or '' if cursor is at begining.
* @type char
*/
function getPreviousChar(myField)
{
    var sel = new Selection(myField);
    var orgRng = sel.create();
    
    if(orgRng.start == 0)
        return "";
    
    sel.setRange(orgRng.start-1,orgRng.end);
    var nextChar = sel.create().text;
    
    sel.setRange(orgRng.start,orgRng.end);
    return nextChar;
}

/**
* Gets next character.
* @param {input} myField: field to get character after cursor.
* @returns Character after cursor or '' if cursor is at end.
* @type char
*/
function getNextChar(myField)
{
    var sel = new Selection(myField);
    var orgRng = sel.create();
    
    if(orgRng.end == $F(myField).length)
        return "";
    
    sel.setRange(orgRng.start,orgRng.end+1);
    var nextChar = sel.create().text;
    
    sel.setRange(orgRng.start,orgRng.end);
    return nextChar;
}

/**
* Moves cursor specified number of characters (negative to move backwards).
* @param {input} myField: field in which to move cursor.
* @param {int} count: number of charachters to move cursor.
*/
function MoveCursor(myField,count)
{
    var sel = new Selection(myField);
    var rng = sel.create();
    
    
    rng.start += count;
    if(rng.start < 0)
    {
        rng.start = 0;
    }
        
    if(rng.start > $F(myField).length)
    {
        rng.start = $F(myField).length;
    }
    
    sel.setRange(rng.start,rng.start);
}

/**
* Gets the curent position of the currsor.
* @param {input} myField: field in which to find cursor position.
* @returns where if the field the cursor is at
* @type int
*/
function getCursorPosition(myField)
{
    var rng = new Selection(myField).create();
    return rng.start;
}

/**
* Sets the curent position of the currsor.
* @param {input} control: field in which to set cursor position.
* @param {int} caret_position: position to set the cursor.
*/
function setCursorPosition(control, caret_position){
    new Selection(control).setRange(caret_position, caret_position);        
}

/**
* Same as getCursorPosition.
* @param {input} myField: field in which to find cursor position.
* @returns where if the field the cursor is at.
* @type int
* @see #getCursorPosition
*/
function getCaretPosition(myField)
{
    return getCursorPosition(myField);
}

/**
* Same as setCursorPosition
* @param {input} control: field in which to set cursor position.
* @param {int} caret_position: position to set the cursor.
* @see #setCursorPosition
*/
function setCaretPosition(control, caret_position){
    setCursorPosition(control, caret_position);      
}

/**
* Move cursor to end of field
* @param {input} myField: the cursor will be a the end of this field.
*/
function moveCursorToEnd(myField)
{
   var selection = new Selection(myField);
   selection.setRange(myField.value.length, myField.value.length);
}

/**
* Same as moveCursorToEnd
* @param {input} myField: the cursor will be a the end of this field.
* @see #moveCursorToEnd
*/
function moveCaretToEnd(myField)
{
   moveCursorToEnd(myField);
}

/**
* Move cursor to beginning of field
* @param {input} control: the cursor will be a the beginning of this field.
*/
function moveCursorToStart(control){
    setCursorPosition(control, 0);
}

/**
* Same as moveCursorToStart
* @param {input} control: the cursor will be a the beginning of this field.
* @see #moveCursorToStart
*/
function moveCaretToStart(control){
    moveCursorToStart(control);
}

/**
* Delete highlighted text/ Backspace
* @param {input} myField: delete the text from this field.
*/
function deleteAtCursor(myField)
{
    var selection = new Selection(myField);
    
    // get the range
    var rng = selection.create();
    
    // if the range start is more than 0 then move the start back one to increase the selection area
    if(rng.start > 0){
        rng.start -=1;
    }
    
    // set the selection
    selection.setRange(rng.start,rng.end);
    
    
    rng.setText('');
}

/**
* Insert value where the cursor is.
* @param {input} myField: Insert the text into this field.
* @param {string} myValue: Value to insert.
*/
function insertAtCursor(myField, myValue) 
{  
    var rng = new Selection(myField).create();
    rng.setText(myValue);
    if (!Prototype.Browser.IE) {
        new Selection(myField).setRange(rng.start + 1, rng.start + 1);
    }
}

/**
* finds the position of the object passed in, and then returns 
* a two element array where 0=offsetLeft and 1=offsetTop
* recursive up two generations.
* @param {element} obj: element (or elements id) of which to find top left corner.
* @returns Array holding [left,top] of the element passed in.
* @type int[2]
*/
function findPos(obj) 
{
    if(typeof(obj) == 'string')
    { obj = $(obj); }
    
    var curleft = curtop = 0;
    if (obj.offsetParent) 
    {
        curleft = obj.offsetLeft
        curtop = obj.offsetTop
        for(var p = 0; p < 2; p++)
        {
            obj = obj.offsetParent;
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        }
    }
    return [curleft,curtop];
}

/**
* finds the position of the object passed in, and then returns 
* a two element array where 0=offsetLeft and 1=offsetTop
* recursive up generations till no object parent is found.
* @param {element} obj: element (or elements id) of which to find top left corner.
* @returns Array holding [left,top] of the element passed in.
* @type int[2]
*/
function findPosFull(obj) 
{
    if(typeof(obj) == 'string')
    { obj = $(obj); }
    
    var curleft = curtop = 0;
    if (obj.offsetParent) 
    {
        curleft = obj.offsetLeft
        curtop = obj.offsetTop
        while(obj.offsetParent)
        {
            obj = obj.offsetParent;
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        }
    }
    return [curleft,curtop];
}

/**
* fire event for a specific element
* @param {object} element: the element, or element id to fire the event for
* @param {string} event: the name of the event to fire.
*/
function fireEvent(element, event) {
    element = $(element);
    if (document.createEventObject) {
        // dispatch for IE
        var evt = document.createEventObject();
        return element.fireEvent('on' + event, evt)
    }
    else {
        // dispatch for firefox + others
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent(event, true, true); // event type,bubbling,cancelable
        return !element.dispatchEvent(evt);
    }
}

/**
* Case insensitive search and replace
* @param {string} str: original string to search in.
* @param {string} oldVal: value to replace.
* @param {string} newVal: value to replace with.
* @returns string with newVal having replaced every instance of oldVal
* @type string
*/
function globalReplace(str,oldVal,newVal)
{
    if(!str || str == "null" || str == "undefined"){return "";}

    return str.replace(new RegExp(oldVal, "gi"), newVal);
}

/**
* Case insensitive search and replace
* @param {object} container: Name or instance of DOM element containing form elements to clear
* @param {string} className: Name of CSS class of form elements that are to be cleared
*/
function clearForm(container, className)
{
    if(typeof container == 'string')
    {
        container = $(container);
    }
    
    var UserInputs = container.select('.' + className);   
    
    UserInputs.each(function(el)
    {
        switch(el.tagName)
        {
            case "CHECKBOX":
                el.checked = false;
                return;
            case "SELECT":
                el.selectedIndex = -1;
                return;
            case "INPUT":
                if(el.type.toUpperCase() == "CHECKBOX")
                {
                    el.checked = false;
                }
                else
                {
                    el.value = "";
                }
                return;
            default:
                el.value = "";
                return;
        }
    });
}

/**
* Case insensitive search and replace
* @param {object} container: Name or instance of DOM element containing form elements to clear
* @param {string} className: Name of CSS class of form elements that are to be cleared
*/
function clearFormInputs(container) {
    if (typeof container == 'string') {
        container = $(container);
    }

    var UserInputs = container.select('input');

    UserInputs.each(function(el) {
        switch (el.tagName) {
            case "CHECKBOX":
                el.checked = false;
                return;
            case "SELECT":
                el.selectedIndex = -1;
                return;
            case "INPUT":
                if (el.type.toUpperCase() == "CHECKBOX") {
                    el.checked = false;
                }
                else {
                    el.value = "";
                }
                return;
            default:
                el.value = "";
                return;
        }
    });
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  Event Manipulation
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Add a function to be called on the window.onload event
* @param {function} func: function reference (or anonymous)
*/
function addLoadEvent(func) 
{
    var oldonload = window.onload;
    if (typeof window.onload != 'function') 
    {
        window.onload = func;
    } 
    else 
    {
        window.onload = function() 
        {
            if (oldonload) 
            {
                oldonload();
            }
            if(typeof func == 'function')
            { func(); }
            else
            { func; }
        }
    }
}


/**
* use this event to programatically subscribe to any event of any object
* simply pass in the objectName, the eventName you wish to subscribe to
* and the handler function
* @param {string} objectName: id of the control
* @param {string} eventName: name of the event (eg. 'onKeyPress', 'onLoad', etc)
* @param {function} handler: function reference (or anonymous)
*/
function addEventHandler(objectName,eventName,handler)
{
    var obj = $(objectName);
    var oldOnLoad = null;
    var oldFunc;
    
    eval('oldFunc = obj.' + eventName + ';');
    
    if (typeof oldFunc != 'function') 
    {eval('obj.' + eventName + ' = ' + handler);} 
    else 
    {eval('obj.' + eventName + ' = function() {if (oldFunc) {oldFunc();}handler();}');}
}

/**
* Cross browser suppport for events
* @param {event} e: event
* @returns curent event
* @type event
*/
function ensureEvent(e)
{
    if(!e){e = window.event;}
    
    return e;
}

/**
* Cross browser suppport for firing events
* @param {object} _obj: object
* @param {string} _eventName: name of the event (eg. 'load', 'click', etc)
* @param {string} _eventType: name of the event type (eg. 'MouseEvents', 'HTMLEvents', etc)  see:http://developer.mozilla.org/En/DOM:document.createEvent
*/
function fireEvent(_obj, _eventName, _eventType)
{
    if (_obj.dispatchEvent) 
    {
        var EventType = _eventType == null ? "HTMLEvents" : _eventType;
	    //fire event Firefox
        var e = document.createEvent(EventType); 
        e.initEvent(_eventName, true, true);

        _obj.dispatchEvent(e); 
    }
    else
    {
        //fire event IE
        var eventFunction = null;
        eval("eventFunction = _obj." + _eventName);
        if(eventFunction != null){
            eval("_obj." + _eventName + "();");
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  Dom Parsing Helpers
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Get all elements of a form
* the first form of the document is used if no form is passed in
* @param {form} form: (optional)form to get elements from
* @returns array of elements
* @type element[]
*/
function getAllFormElements(form)
{
    if(form == null)
    {
        return document.forms[0].elements;
    }
    return form.elements
}

/**
* Get all elements that match *_id or = id and puts them in an array
* @param {string} id: Server id to look for on the client
* @returns array of elements
* @type element[]
*/
function getElementsByServerId(id) {
    return $$('[id*="' + id + '"]');
}

function getInputElementByServerId(id) {
    return $$('INPUT[id*="' + id + '"]');
}

/**
* Calls $F (get value) using the first result returned by getElementsByServerId
* requires prototype.js.
* @param {string} fieldID: Server id to look for on the client
* @returns value of element specified by ServerID
* @type string
*/
function getFieldValue(fieldID)
{
    var tmp = getElementsByServerId(fieldID);
	if(tmp.length > 0)
	{
	    return $F(tmp[0]);
	}
}

/**
* Cross Browser support for getting the DomDocument
* @class Cross Browser support for DomDocument
* @constructor
* @returns string representation of the DomDocument
* @type DomDocument
* @throws Error if unable to find DOMDocument
* @throws Error if unable to parse document
*/
function getDomDocument()
{
	var adapter = '';
	if ('undefined' != typeof ActiveXObject) {
		adapter = 'MS';
	} else if ('undefined' != typeof document
		&& document.implementation
		&& document.implementation.createDocument
		&& 'undefined' != typeof DOMParser)
	{
		adapter = 'default';
	}
	switch (adapter) {
		case 'MS':
			return new (function () {
			    /**
                * creates an instance of the DomDocument
                * @returns ActiveX DOMDocument
                * @type ActiveXObject
                */
				this.createDocument = function () {
					var names = ["Msxml2.DOMDocument.6.0",
						"Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument",
						"MSXML.DOMDocument", "Microsoft.XMLDOM"];
					for (var key in names) {
						try {
							return new ActiveXObject(names[key]);
						} catch (e) {}
					}
					throw new Error('Unable to create DOMDocument');
				};
				/**
                * XML string representation of the document
                * @param {DomDocument} doc: document to serialize
                * @returns xml representation of the DomDocument
                * @type string
                */
				this.serialize = function (doc) {
					return doc.xml;
				};
				/**
                * loads a DomDocument from XML string representation
                * @param {string} xml: xml representation to deserialize
                * @returns navigable DomDocument from xml
                * @type DomDocument
                */
				this.parseXml = function (xml) {
					var doc = this.createDocument();
					if (!doc.loadXML(xml)) {
						throw new Error('Parse error');
					}
					return doc;
				};
			})();
		case 'default':
			return new (function () {
				/**
                * creates an instance of the DomDocument
                * @returns default DOMDocument
                * @type DomDocument
                */
				this.createDocument = function () {
					return document.implementation.createDocument("", "", null);
				};
				/**
                * XML string representation of the document
                * @param {DomDocument} doc: document to serialize
                * @returns xml representation of the DomDocument
                * @type string
                */
				this.serialize = function (doc) {
					return new XMLSerializer().serializeToString(doc);
				};
				/**
                * loads a DomDocument from XML string representation
                * @param {string} xml: xml representation to deserialize
                * @returns navigable DomDocument from xml
                * @type DomDocument
                */
				this.parseXml = function (xml) {
					var doc = new DOMParser().parseFromString(xml, "text/xml");
					if ("parsererror" == doc.documentElement.nodeName) {
						throw new Error('Parse error ' + xml);
					}
					return doc;
				};
			})();
		default:
			throw new Error('Unable to select the DOM adapter');
	}
};

/**
* loads a DomDocument from XML string representation
* @param {string} xml: xml representation to deserialize
* @returns navigable DomDocument from a xml string
* @type DomDocument
*/
function parseXMLFromString(sXml)
{
	var doc = getDomDocument().parseXml(sXml);
	return doc;
}

/**
* parses Xml to get the value from a node.
* @param {DomDocument} Tags: xml DomDocument to get node from
* @param {int} index: index of Tags to search children for TagName
* @param {string} TagName: name of the node to get value from
* @returns value found within given node
* '' if node not found.
* @type string
*/
function GetNodeValue(Tags, index, TagName)
{
	if(Tags[index] && Tags[index].getElementsByTagName(TagName)[0] && Tags[index].getElementsByTagName(TagName)[0].firstChild)
	{
		return Tags[index].getElementsByTagName(TagName)[0].firstChild.nodeValue;
	}
	return '';
}

/**
* Loads a table element and populates rows and columns
* from the xml data<br>
* example XML format:<br>
* {<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;TableID&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ColumnName&gt;Row 1 Column 1 Data&lt;/ColumnName&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ColumnName&gt;Row 1 Column 2 Data&lt;/ColumnName&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ColumnName&gt;Row 2 Column 1 Data&lt;/ColumnName&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ColumnName&gt;Row 2 Column 2 Data&lt;/ColumnName&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;/TableID&gt;<br>
* }
* @param {string} xml: xml to build table from 
* Optional pass in the xml DomObject directly
* @returns Table element
* @type element
*/
function buildHTMLTable(xml)
{
	if(typeof(xml) == 'string')
	{
		xml = parseXMLFromString(xml);
	}
	
	var docRoot = xml.firstChild;//xml.getDocumentElement();
	var tbl = document.createElement("table");
	tbl.id = docRoot.nodeName;
	tbl.style.backgroundColor = 'White';
	$(tbl).addClassName('tableGrid');
    var tblBody = document.createElement("tbody");
    tbl.appendChild(tblBody);
        
    for(rowIndex = 0; rowIndex < docRoot.childNodes.length; rowIndex++)
    {
        var rowNode = docRoot.childNodes[rowIndex];
        //Create Header
        if(rowIndex == 0)
        {
            var trHeader = document.createElement("tr");
            trHeader.className = "headerRow";
            tblBody.appendChild(trHeader);
            
            for(colIndex = 0; colIndex < rowNode.childNodes.length; colIndex++)
            {
                var colNode = rowNode.childNodes[colIndex];
                var td = document.createElement("td");
                trHeader.appendChild(td);
                $(td).update(colNode.nodeName);
            }
        }
        
        var tr = document.createElement("tr");
        if (rowIndex % 2 == 0) {
            tr.className = "oddRow";
        }
        else {
            tr.className = "evenRow";
        }
        tblBody.appendChild(tr);
        
        for(colIndex = 0; colIndex < rowNode.childNodes.length; colIndex++)
        {
            var colNode = rowNode.childNodes[colIndex];
            var td = document.createElement("td");
            tr.appendChild(td);
            if (colNode.childNodes.length > 0) {
                $(td).update(colNode.childNodes[0].nodeValue);
            }
            else {
                $(td).update('&nbsp;');
            }
  
        }
    }
	
	if(docRoot.childNodes.length == 0)
	{
	    var trEmpty = document.createElement("tr");
        tblBody.appendChild(trEmpty);
        
        var td = document.createElement("td");
        trEmpty.appendChild(td);
        $(td).update("No rows returned!");
    }
	
	return tbl;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  select objects
/////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Loads a select element text and (optional) values
* from the xml data<br>
* example XML format:<br>
* {<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;root&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Text&gt;Text1&lt;/Text&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Value&gt;Value1&lt;/Value&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Text&gt;Text2&lt;/Text&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Value&gt;Value2&lt;/Value&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;/root&gt;<br>
* }
* @param {string} select: Element id (optional: element object)
* of select to load
* @param {string} xml: Xml string (optional: xml Dom)
* of data to load into select
*/
function loadSelect(select, xml) {
    if (typeof (select) == 'string') {
        select = $(select);
    }
    if (xml == null || xml.length == 0) {
        clearSelect(select);
        return;
    }
    if (typeof (xml) == 'string') {
        xml = parseXMLFromString(xml);
    }
    clearSelect(select);

    if (xml != null) {
        var xmlOption = xml.getElementsByTagName('Option');
        if (xmlOption != null && xmlOption.length > 0) {
            for (var index = 0; index < xmlOption.length; index++) {
                /*
                var optn = document.createElement("OPTION");
                optn.text = GetNodeValue(xmlOption, index, 'Text');
                optn.value = GetNodeValue(xmlOption, index, 'Value');
                if(optn.text.length > 0)
                select.options.add(optn);*/
                var value = GetNodeValue(xmlOption, index, 'Value');
                var text = GetNodeValue(xmlOption, index, 'Text');
                if (text.length > 0 && value.length > 0) {
                    select.options[select.options.length] = new Option(text, value);
                }
            }
        }
    }
}



/**
* clears all options from select element
* @param {string} sel: Element id (optional: element object)
* of select to load
*/
function clearSelect(sel)
{
//	if(typeof(sel) == 'string')
//	{
//		sel = $(sel);
//	}
//	
//	for (var index=sel.options.length-1; index>=0; index--)
//	{
//		sel.options[index] = null;
//	}
//	sel.selectedIndex = -1;
    ODATech.clearSelect(sel);
}

/**
* run the filter on select element from text in text element
* @param {string} selectID: Select Element id (optional: element object)
* @param {string} txtID: Text Input Element id (optional: element object)
* @private
*/
function applyFilter(selectID,txtID)
{
//    var visible = $(selectID);
//    var before = $F(visible);
//    var hdn = $('hdn_' + selectID);
//    var txt = $(txtID);
//    clearSelect(visible);
//    
//    for(var index = 0; index < hdn.options.length; index++)
//    {
//        var optn = document.createElement("OPTION");
//        optn.text = hdn.options[index].text;
//        optn.value = hdn.options[index].value;
//        if(optn.text.toUpperCase().indexOf(txt.value.toUpperCase()) > -1)
//            visible.options.add(optn);
//    }
//    
//    for(var index = 0; index < visible.options.length; index++)
//    {
//        var optn = visible.options[index];
//        if(before == optn.value)
//        {
//            optn.selected = true;
//            break;
//        }
//    }
    ODATech.applyFilter(selectID, txtID);
}


/**
* initilize the hidden filter select
* this creates a hidden select and loads it with all the options
* that exist in the select object and sets up requried events.
* (Obsolete) Use ODATech.initSelectFilter instead
* @param {string} select: Select Element id (optional: element object)
* @param {string} txt: Text Input Element id (optional: element object)
* @param {function} onChangeName: Optional function to run after filter
* is run
*/
function initSelectFilter(select,txt,onChangeName)
{
//    var visible = $(select);
//    var txt = $(txt);
//    var hdn = $('hdn_' + visible.id)
//    if(hdn == null)
//    {
//        //First Run
//        hdn = document.createElement('select');
//        hdn.id = 'hdn_' + visible.id;
//        hdn.style.display = 'none';
//    
//        visible.up().appendChild(hdn);
//        if(txt != null) { addEventHandler(txt,'onkeyup','function() { filterSelect("' + visible.id + '","' + txt.id + '","' + onChangeName + '"); }') }
//    }
//    
//    clearSelect(hdn);
//    
//    for(var index = 0; index < visible.options.length; index++)
//    {
//        var optn = document.createElement("OPTION");
//        optn.text = visible.options[index].text;
//        optn.value = visible.options[index].value;
//        if(optn.text.length > 0)
//            hdn.options.add(optn);
//    }
    ODATech.initSelectFilter(select, txt, onChangeName);
}

var filterTimer;
var timerRunning = false;

/**
* Runs at keyup of txt to filter a select list
* (Obsolete) use ODATech.filterSelect instead
* @param {string} selectID: Select Element id
* @param {string} txtID: Text Input Element id
* @param {function} onChangeName: Optional function to run after filter
* is run
* @private
*/
function filterSelect(selectID,txtID,onChangeName)
{
//    if(timerRunning)
//    {
//        clearTimeout(filterTimer)
//        timerRunning = false;
//    }
//    
//    filterTimer = setTimeout('var before = $F("' + selectID + '"); applyFilter("' + selectID + '","' + txtID + '"); if(before != $F("' + selectID + '") && ' + onChangeName + ' != null) { ' + onChangeName + '();}',500);
//    timerRunning = true;
    ODATech.filterSelect(selectID, txtID, onChangeName);
}

/**
* Trades places fo the two Items in a select list
* @param {string} item1: Option Element id (optional: element object)
* @param {string} item2: Option Element id (optional: element object)
*/
function swapNodes(item1,item2) 
{
    item1 = $(item1);
    item2 = $(item2);
    
    if(item1 == item2)
    { return; }
    // We need a clone of the node we want to swap
    var itemtmp = item1.cloneNode(1);

    // We also need the parentNode of the items we are going to swap.
    var parent = item1.parentNode;

    // First replace the second node with the copy of the first node
    // which returns a the new node
    item2 = parent.replaceChild(itemtmp,item2);

    //Then we need to replace the first node with the new second node
    parent.replaceChild(item2,item1);

    // And finally replace the first item with it's copy so that we
    // still use the old nodes but in the new order. This is the reason
    // we don't need to update our Behaviours since we still have 
    // the same nodes.
    parent.replaceChild(item1,itemtmp);

    // Free up some memory, we don't want unused nodes in our document.
    itemtmp = null;
}

/**
* Set the Select element selected option by Value
* @param {string} select: Select Element id (optional: element object)
* @param {string} value: value of the option to mark as selected.
*/
function setSelectedValue(select, value)
{
    select = $(select);
    
    for(var j=0;j<select.options.length;j++)
    {
        if(select.options[j].value == value)
        {
            select.selectedIndex = j;
            return;
        }
    }
}

/**
* Set the Select element selected option by text
* @param {string} select: Select Element id (optional: element object)
* @param {string} text: text of the option to mark as selected.
*/
function setSelectedText(select,text)
{
    for(var j=0;j<select.options.length;j++)
    {
        if(select.options[j].text == text)
        {
            select.selectedIndex = j;
            return;
        }
    }
}


// returns an array of the <select> elements selected options values
function getSelectedValues(selectID){
    var select = $(selectID);
    var selVals = new Array();
    
    for(var j=0; j < select.length; j++)
    {
        if(select.options[j].selected)
        {
            selVals.push(select.options[j].value);
        }
    }
    
    return selVals;
}

// returns an array of the <select> elements selected options text
function getSelectedText(selectID){
    var select = $(selectID);
    var selText = new Array();
    
    for(var j=0; j < select.length; j++)
    {
        if(select.options[j].selected)
        {
            selText.push(select.options[j].text);
        }
    }
    
    return selText;
}

// returns an array of the <select> elements selected options items as { text: String, value: String }
function getSelectedItems(selectID){
    var select = $(selectID);
    var selText = new Array();
    
    for(var j=0; j < select.length; j++)
    {
        if(select.options[j].selected)
        {
            selText.push({value: select.options[j].value, text: select.options[j].text});
        }
    }
    
    return selText;
}

function moveSelectedOptions(fromSelectID, toSelectID)
{
    var fromSelect = $(fromSelectID);
    var toSelect = $(toSelectID);
    var valuesMoved = new Array();
    
    for(var j = fromSelect.length - 1; j >= 0; j--)
    {
        if(fromSelect.options[j].selected)
        {
            var option = fromSelect.options[j];
            valuesMoved.push(option.value);
            fromSelect.remove(j);
            toSelect.options.add(option);
        }
    }
    return valuesMoved;
}


function removeSelectedOptions(fromSelectID) {
    var fromSelect = $(fromSelectID);
    var valuesMoved = new Array();

    for (var j = fromSelect.length - 1; j >= 0; j--) {
        if (fromSelect.options[j].selected) {
            var option = fromSelect.options[j];
            valuesMoved.push(option.value);
            fromSelect.remove(j);
        }
    }
    return valuesMoved;
}

function sortSelectList(selectID, sortFirstItem)
{
    var select = $(selectID);
    if(sortFirstItem == null) { sortFirstItem = true; }
    var startIndex = sortFirstItem == true ? 0 : 1;
    var optionsMoved = true;
    while(optionsMoved)
    {
        optionsMoved = false;
        for(var j=startIndex; j < select.length - 1; j++)
        {
            if(select.options[j].text.toLowerCase() > select.options[j + 1].text.toLowerCase())
            {
                swapNodes(select.options[j],select.options[j + 1])
                optionsMoved = true;
            }
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  Hide and Show Draggables
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* hides the draggable object
* @param {string} obj: draggable id (optional: draggable object)
*/
function hideDraggable(obj)
{
    //obj Object or ID of Draggable Object to Hide
    if(typeof(obj) == 'string')
	{
		obj = $(obj);
	}
	
    var index = 0;
    for(index = 0; index < obj.childNodes.length; index++)
    {
        obj.childNodes[index].style.display = 'none';
    }
    
    obj.height = 0;
}

/**
* show the draggable object
* @param {string} obj: draggable id (optional: draggable object)
* @param {string} idsNotToShow: (Optional) '^' delimited list of ID's not to show
* @param {string} height: (Optional) height for draggable object if left blank default height used
*/
function showDraggable(obj,idsNotToShow, height)
{
    if(typeof(obj) == 'string')
	{
		obj = $(obj);
	}
	if(idsNotToShow == null)
	{
	    idsNotToShow = '_fIeLdS_sHoUlD_nOt_Be_NaMeD_tHiS';
	}
	
    var index = 0;
    var hdnarr = idsNotToShow.split('^');
    for(index = 0; index < obj.childNodes.length; index++)
    {
        var Show = true;
        for(var i2 = 0; i2 < hdnarr.length; i2++)
        {
            if(hdnarr[i2] == obj.childNodes[index].id)
            {
                Show = false;
            }
        }
        
        if(Show)
        {
            if(obj.childNodes[index] != null)
            {$(obj.childNodes[index]).show();}
        }
    }
    
    if(height != null)
    {
        alert(height);
        obj.style.height = height;
    }
    else
    {
        obj.style.height = '';
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  AjaxExpandingRecursiveTree
/////////////////////////////////////////////////////////////////////////////////////////////////////

/** 
* Default location for TreeBranch Page
* @final
* @type string
*/
var treeBranchURL = 'TreeBranch.aspx';

/**
* get the root nodes and set up events functions for tree object
* @param {string} elementToPopulate: id of the element to place the tree
* @param {string} className: Qualified class name of objects to load into the tree
* @param {string} textPropertyName: Property on the class from which to take the text for the tree
* @param {string} lnkOnClickFunction: (Optional) function to call when Item is clicked
* @param {string} lnkOnContextClickFunction: (Optional) function to call when Item is right clicked
* @param {string} treeBranchURLOverride: (Optional) override the default treeBranch url
*/
function initializeTree(elementToPopulate, className, textPropertyName, lnkOnClickFunction
    , contextAttributeValue, treeBranchURLOverride, lnkOnHoverFunction
    , textDescriptionName) {

    // override the treeBranchURL (why is this property global?)
    if (treeBranchURLOverride) {
        treeBranchURL = treeBranchURLOverride;
    }
    
    // call the getBranch Method
    getBranch(elementToPopulate, 'NULL', className, textPropertyName, lnkOnClickFunction, contextAttributeValue
        , lnkOnHoverFunction, textDescriptionName);
}

/**
* toggle the tree branch (visible: hidden)
* @param {string} sendingImg: image object that was clicked
* @param {string} elementToPopulate: id of the element to place the tree branch
* @param {string} className: Qualified class name of objects to load into the tree branch
* @param {string} textPropertyName: Property on the class from which to take the text for the tree
* @param {string} parentID: id of the tree branch from which to find children
* @param {string} lnkOnClickFunction: (Optional) function to call when Item is clicked
* @param {string} lnkOnContextClickFunction: (Optional) function to call when Item is right clicked
* @private
*/
function toggleTree(sendingImg, elementToPopulate, className, textPropertyName, parentID, lnkOnClickFunction, contextAttributeValue, lnkOnHoverFunction, textDescriptionName)
{
    if(IsValidPattern(sendingImg.src,'^.*plus.gif$'))
    {
        sendingImg.src = "images/minus.gif";
        sendingImg.alt = "Collapse";
        $(elementToPopulate).style.display = 'inline';

        getBranch(elementToPopulate, parentID, className, textPropertyName, lnkOnClickFunction, contextAttributeValue, lnkOnHoverFunction, textDescriptionName)
    }
    else
    {
        sendingImg.src = "images/plus.gif";
        sendingImg.alt = "Expand";
        $(elementToPopulate).style.display = 'none';
    }
}

/**
* load the tree branch from the server based on Parent ID
* @param {string} elementToPopulate: id of the element to place the tree branch
* @param {string} className: Qualified class name of objects to load into the tree branch
* @param {string} parentID: id of the tree branch from which to find children
* @param {string} textPropertyName: Property on the class from which to take the text for the tree
* @param {string} lnkOnClickFunction: (Optional) function to call when Item is clicked
* @param {string} lnkOnContextClickFunction: (Optional) function to call when Item is right clicked
* @private
*/
function getBranch(elementToPopulate, parentID, className, textPropertyName, lnkOnClickFunction, contextAttributeValue, lnkOnHoverFunction, textDescriptionName)
{
    var params = "";
    params += 'ParentID=' + parentID;
    params += '&ClassName=' + className;
    params += '&TextPropertyName=' + textPropertyName;
    params += '&LnkOnClickFunction=' + lnkOnClickFunction;
    params += '&ContextAttributeValue=' + contextAttributeValue;
    params += "&Prefix=" + elementToPopulate;
    params += "&LnkOnHoverFunction=" + lnkOnHoverFunction;
    params += "&textDescriptionName=" + textDescriptionName;
            
    ajaxUpdate(elementToPopulate,treeBranchURL,params,_getBranchSuccess);
}

function _getBranchSuccess()
{
    if(typeof(getBranchSuccess) == 'function'){ getBranchSuccess(); }
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  JSON
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* get a Json Object from elements of a given css classname within a given container
* @param {string} container: id of the element (optional: draggable object) to build the Json object from
* @param {string} className: css classname on inputs to gather values from
* @param {string} prefix: buildJSON removes everything up-to-and-including prefix from field name (optional: used in conjunction with Embedded Form server control)
*/
function buildJSON(container, className, prefix, domSelectQuery)
{
    //build a JSON object from all child inputs with the given className
    
    
    container = $(container);


    var UserInputs = null;
    if (className != null && className.length > 0 && className != "NULL") {
        UserInputs = container.select('.' + className);
    }
    else if (domSelectQuery != null && domSelectQuery.length > 0 && domSelectQuery != "NULL") {
        UserInputs = container.select(domSelectQuery);
    }
    else {
        return "";
    }
    
	function myObj(){};
	UserInputs.each(function(s){ if($(s) && $(s).id.length > 0) { eval('myObj.prototype.' + getTrimmedID($(s).id, prefix) + ' = "' + getEscapeFormInput(s) + '";');} });
	//alert(Object.toJSON(new myObj()));
	return Object.toJSON(new myObj());
}

function getTrimmedID(id, prefix){
    if(prefix == null || prefix.length == 0)
        return id;
            
    return globalReplace(id, ".*" + prefix, "");
}

/**
* update a Form Input fields value to be escaped of line feeds, carriage returns, etc
* @param {object} formInputElement: id or instance of form input element to update
*/
function getEscapeFormInput(formInputElement)
{
    var el = $(formInputElement);

    var value = $F(el);
    if (el != null && el.odaTextBox != null) {
        value = el.odaTextBox.GetValue();
    }
    if (value != null) {
        value = value.stripScripts().stripTags();
        //$S(el, value);
    }
    value = globalReplace(value, "\\r", "");
    value = globalReplace(value, "\\n", "\\\\n");
    //value = globalReplace(value, "\\b", "\\\\b");
    value = globalReplace(value, "\\f", "\\\\f");
    value = globalReplace(value, "\\t", "\\\\t");
    //value = globalReplace(value, "\\\\", "\\\\\\\\");
    value = escape(value);
    return value;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  XML
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* load inputs from xml string<br>
* example XML format:<br>
* {<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;root&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Name&gt;ElementID1&lt;/Name&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Value&gt;Value1&lt;/Value&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Name&gt;ElementID2&lt;/Name&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Value&gt;Value2&lt;/Value&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Option&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;/root&gt;<br>
* }
* @param {string} xml: xml string with id's and values
*/
function loadFormFromXML(xml) {

    var xmlDoc = null;

    Try.these(
    function() { xmlDoc = parseXMLFromString(xml); },
    function() { xml = xml.unescapeHTML(); xmlDoc = parseXMLFromString(xml); }
    );

    if (xmlDoc == null) { return false; }
    else { xml = xmlDoc; }

    var xmlOption = xml.getElementsByTagName('Option');
    for(var index = 0; index < xmlOption.length; index++)
    {
        var ElemName = GetNodeValue(xmlOption, index, 'Name');
        var Value = GetNodeValue(xmlOption, index, 'Value');
        //alert('ID: ' + ElemName + '\r\nValue: ' + Value);

        var element = $(ElemName);
        //try formbuilder extensions
        if (element == null) {
            var arr = getInputElementByServerId(ElemName + '_txt');
            if (arr.length > 0) { element = arr[0]; }
        }
        if (element == null) {
            var arr = getInputElementByServerId(ElemName + '_chk')
            if (arr.length > 0) { element = arr[0]; }
        }
        if (element == null) {
            var arr = getElementsByServerId(ElemName + '_ddl')
            if (arr.length > 0) { element = arr[0]; }
        }
        if (element == null) {
            //alert('Property ' + ElemName + ' was not set'); 
            continue;
        }
        
        /*
        if(element.visible() && !element.isDisabled)
        { 
            try{
                element.focus(); 
            }
            catch (ex){
                // don't do anything here
            }
        }
        */
        
        $S(element, Value);
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  Ect
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Trims whitespace from beginning and ending of a string
* @param {string} str: string to trim
* @return string with no leading or trailing whitespaces
* @type string
*/
function trim(str) {
	var	str = str.replace(/^\s\s*/, ''),
		ws = /\s/,
		i = str.length;
	while (ws.test(str.charAt(--i)));
	return str.slice(0, i + 1);
}

String.prototype.trim = function(){
    return trim(this);
}


/**
* Check to see if string starts with a string2Match
* @param {string} string2Test: string to check beginning
* @param {string} string2Match: string that beginning must match
* @return true if matches, false if doesn't
* @type bool
*/
function startsWith(string2Test,string2Match)
{
    var regExPattern = "^" + string2Match + ".*";
    var regEx = new RegExp(regExPattern);
    
    if(string2Test.match(regEx))
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
* Check to see if string ends with a string2Match
* @param {string} string2Test: string to check end
* @param {string} string2Match: string that end must match
* @return true if matches, false if doesn't
* @type bool
*/
function endsWith(string2Test,string2Match)
{
    var regExPattern = ".*" + string2Match + "$";
    var regEx = new RegExp(regExPattern);
    
    if(string2Test.match(regEx))
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
* Check to see if string contains with a string2Match
* @param {string} string2Test: string to check contains
* @param {string} string2Match: string that string2Test must contain
* @return true if matches, false if doesn't
* @type bool
*/
function contains(string2Test,string2Match)
{
    var regExPattern = ".*" + string2Match + ".*";
    var regEx = new RegExp(regExPattern);
    
    if(string2Test.match(regEx))
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
* Check to see if string starts with a regExPattern
* @param {string} string2Test: string to check match
* @param {string} regExPattern: string pattern that string2Test must match
* @return true if matches, false if doesn't
* @type bool
*/
function matches(string2Test,regExPattern)
{
    var regEx = new RegExp(regExPattern);
    
    if(string2Test.match(regEx))
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
* Creates a DivWindow with all properties on the object passed in
* @param {object} object: object to see properties of
*/
function $O(object)
{
    var div =divWindow('object_inspector','Object Details');
    var innerDiv = $('object_inspector_content');
    innerDiv.innerHTML = '';
    for(property in object)
    {
        if(property == "innerHTML")
        {
            innerDiv.innerHTML += 'escaped ' + property + ':: ' + object.innerHTML.escapeHTML() + '<br />';
        }
        
        innerDiv.innerHTML += property + ':: ' + eval('object.' + property) + '<br />';
    }
}

/**
* Creates a floating draggable div with close button
* 
*  ID's you can call
*  ID               The ID you passed in will be the Containing Div's id
*  ID_content       The ID of the div that will contain the content
*  ID_handle        The ID of the table row used to move the draggable
*  ID_closeImage    The ID of the image used to close the divWindow
*  ID_loadingImage  The ID of the image used to wait for the loading of the content
*  ID_iframe        (Optional) The ID of the Iframe if src parameter was used
* @param {string} id: id of the Div to make a div window out of.
* div will be created if doesn't already exist.
* @param {string} title: text that will show in the title bar
* @param {string} src: (Optional) if included it will polulate the ID_contentdiv with an 
* @param {string} method: (Optional) send POST to send src parameters as POST variables instead
*  iframe pointed to the given src.
*  This is for new divs only. not re-displaying existing divs 
*  (iframe only created when this parameter is populated.)
* @return div that is the div window
* @type element
*/
function divWindow(id, title, src, method, JSONPostPararms, fullScreen, shadowBox)
{
    
    //src is optional if included it will polulate the ID_contentdiv with an iframe pointed to the given src
    //  This is for new divs only. not re-displaying existing divs
    //  
    var paramStrings;
    var usingPOST = false;
    if(method != null && method == "POST" && src != null && src.length > 0){
        paramStrings = src.split('?');
        usingPOST = true;
        src = "./Content.aspx";
    }
    
    var div = $(id);
    if(div == null)
    {
        var htmlString = '';
        if (shadowBox) {
            htmlString += '<div id="' + id + '" style="width:100%;height:100%;background-color: Transparent; background-image: url(\'/images/shadow.png\'); background-repeat:repeat;z-index:10000;top:0;left:0;right:0;bottom:0;position:fixed;">';
            htmlString += '<div id="' + id + '_body" class="divWindow" style="z-index:100010;position:absolute;">';
        } else {
            htmlString += '<div id="' + id + '" class="divWindow" style="position:absolute; z-index:100010;">';
        }
        htmlString += '    <table cellspacing="0px" border="0px" style="width:100%;min-width:200px;">';
        htmlString += '        <tbody>';
        htmlString += '              <tr id="' + id + '_handle" class="divWindowHeader">';
        htmlString += '                  <td>' + title + '</td>';
        htmlString += '                  <td align="right" style="padding-top: 0px; vertical-align: top; text-align: right;">';
        htmlString += '                      <img src="/images/close.png" id="' + id + '_close" style="cursor:hand;" onclick="hideDivWindow(\'' + id + '\');" />';
        htmlString += '                  </td>';
        htmlString += '              </tr>';
        htmlString += '              <tr>';
        htmlString += '                  <td colspan="2" style="border: solid 5px white;">';
        htmlString += '                      <div id="' + id + '_content" style="overflow: auto;background-color:white; padding:5px;">';
        
        if(src != null && src.length > 0) {
            if (usingPOST) {
                htmlString += '              <iframe id="' + id + '_iframe" name="' + id + '_iframe" style="height: 100px; width: 100%;" frameborder="0px" marginwidth="0px" src="./emptyPage.htm"></iframe>';
            }
            else {
                htmlString += '              <iframe id="' + id + '_iframe" name="' + id + '_iframe" style="height: 100px; width: 100%;" frameborder="0px" marginwidth="0px" src="'+ src +'"></iframe>';
            }
        }
        else{
            htmlString += '              <img id="' + id + '_loadingImage" src="/images/loading.gif" />';
        }
        
        htmlString += '                      </div>';
        htmlString += '                  </td>';
        htmlString += '              </tr>';
        htmlString += '        </tbody>';
        htmlString += '    </table>';
        htmlString += '</div>';

        if (shadowBox) {
            htmlString += '</div>';
        }


        $(document.body).insert(htmlString);
        div = $(id); 
        
        if(usingPOST && JSONPostPararms){
            // convert the paramString to hidden input fields and add them to a new form
            // that has a target of the new iframe and action of src   
            var newForm = $(id + "_form");
            if(newForm == null){
                newForm = new Element("FORM", {"id": id + "_form", "action": paramStrings[0], "target": id + "_iframe"});
            }
            
            newForm.action = paramStrings[0];
            
            newForm.innerHTML = "";
            
            $(document.body).insert(newForm);
            
            var paramPairs = paramStrings[1].split('&');
            for(var x=0; x<paramPairs.length; x++){
                var paramPair = paramPairs[x].split('=');
                var hdnInput = new Element("INPUT", {
                    "name": paramPair[0]
                    , "id": paramPair[0]
                    , "value": paramPair[1]
                    , "type": "hidden"});
                newForm.insert({bottom: hdnInput});
            }     
            
            if(JSONPostPararms.length > 0){
                hdnInput = new Element("INPUT", {
                    "name": "JSON_Values"
                    , "ID": "JSON_Values"
                    , "value": JSONPostPararms
                    , "type": "hidden"});
                newForm.insert({bottom: hdnInput});
            }
            
            newForm.submit();
        }
    }
    else
    {
        div.style.display = 'block';
    }

    if (fullScreen) {
        var height, width, dims;
        dims = document.viewport.getDimensions();
        w = dims.width;
        h = dims.height;

        if (Prototype.Browser.IE) {
            h -= 20;
            w -= 15;
        }
        else if (Prototype.Browser.Gecko) {
            h -= 20;
        }

        div.setStyle({ position: 'fixed', top: '0px', left: '10px', bottom: '0px', right: '10px' });

        $(div.id + "_content").setStyle({ position: 'fixed', top: '20px', left: '10px', bottom: '0px', right: '10px' });

        div.down().setStyle({ width: '100%' });

        if ($('masterHeader')) { $('masterHeader').hide(); }
        if ($(document.body).select(".outerMain")[0]) { $(document.body).select(".outerMain")[0].hide(); }
        if ($('masterFooter')) { $('masterFooter').hide(); }
        hideLoading();

    }
    else if (shadowBox) {
        if ((typeof Draggable) == 'function') {
            new Draggable(div.id + "_body", { handle: div.id + "_handle", snap: [5, 5] });
        }
        setTimeout('divWindowWithinViewport("' + div.id + '_body");', 1);
    }
    else {
        if ((typeof Draggable) == 'function') {
            new Draggable(div.id, { handle: div.id + "_handle", snap: [5, 5] });
        }
        setTimeout('divWindowWithinViewport("' + div.id + '");', 1);
    }

    return div;
}

function divWindowWithinViewport(windowID) {
    var cumLeft, offsetWidth, viewPortWidth;
    cumLeft = $(windowID).cumulativeOffset().left;
    offsetWidth = $(windowID).offsetWidth;
    viewPortWidth = document.viewport.getDimensions().width;
    
    if (cumLeft + offsetWidth > viewPortWidth) {
        var newLeft = (cumLeft - ((offsetWidth + cumLeft) - viewPortWidth)) + document.viewport.getScrollOffsets().left;
        $(windowID).setStyle({ left: (newLeft) + 'px' });
    }
}

function hideDivWindow(id) {
    $(id).hide();

    if ($('masterHeader')) { $('masterHeader').show(); }
    if ($(document.body).select(".outerMain")[0]) { $(document.body).select(".outerMain")[0].show(); }
    if ($('masterFooter')) { $('masterFooter').show(); }
    if (typeof hideLoading == 'function') { hideLoading(); }
}

/**
* Pads a string with a character untill it is the requested length
* usage paddedString(4,'String','0',true);
* equivilent to paddedString(4,'String');
* @param {int} finishLength: final length to pad to
* @param {string} str: string that needs padding
* @param {char} character: (Optional) Character to pad with (default 0)
* @param {bool} padLeft: (Optional) pad left side of original string (default true)
* @return string padded with char
* @type string
*/
function paddedString(finishLength,str,character,padLeft)
{
	if(padLeft == null)
	{
		padLeft = true;
	}
	if(character == null || character.length < 1)
	{
		character = '0';
	}
	if(character.length > 1)
	{
		character = character.substring(0,1);
	}
	if(str == null)
	{
		str = '';
	}
	str += '';
	if(finishLength == null)
	{
		finishLength = 0;
	}
	
	while(str.length < finishLength)
	{
		if(padLeft)
		{
			str = character + str;
		}
		else
		{
			str = str + character;
		}
	}
	return str;
}

/**
* gets a string representation of current date (Browser)
* @return string representation of current date
* @type string
*/
function nowToString()
{
	var date = new Date();
	return paddedString(2,date.getMonth()) + '/' + paddedString(2,date.getDate()) + '/' + date.getFullYear() + ' ' + paddedString(2,date.getHours()) + ':' + paddedString(2,date.getMinutes()) + ':' + paddedString(2,date.getSeconds());
}

/**
* takes a foat value and displays it in Common US Dollar notation
* @param {float} value: value to display as Currency
* @param {string} symbol: Currency Symbol to use default ('$')
* @param {float} accuracy: accuracy to use in displaying currency default (2) max(10)
* @return string representation of US Dollars
* @type string
*/
function formatAsMoney(value, symbol, accuracy)
{
    if (symbol == null)
    { symbol = '$'; }
    if (accuracy == null)
    { accuracy = 2; }

    var money = parseFloat(value);
    money = Math.round(money * Math.pow(10, accuracy)) / Math.pow(10, accuracy);

    var sMoney = money.toString();
    var decIndex = sMoney.indexOf('.', 0);
    var len = sMoney.length;
    if (decIndex < 0) {
        sMoney += '.';
        for (var j = 0; j < accuracy; j++) {
            sMoney += "0";
        }
    }
    else {
        var monPart = sMoney.split('.')[0];
        var decPart = sMoney.split('.')[1];
        while (decPart.length < accuracy) {
            decPart += "0";
        }
        sMoney = monPart + '.' + decPart;
    }
    return symbol + ' ' + sMoney;
}

var checkingForDeletedFalseEvalScript = '';
var humanReadableIDValue = ''
var checkingForDeleted = false;
/**
* Checks with server to see if object with Human Readable Identifier
* exists deleted in the database
* for use with formbuilder pages
* @param {string} prop: Human Readable Identifier property of class
* @param {string} falseEvalScript: (Optional) script to eval if item not reactivated
*/
function existsDeleted(prop,falseEvalScript)
{
    if(!checkingForDeleted)
    {
        //prevent multiple clicks
        checkingForDeleted = true;
        setTimeout('checkingForDeleted = false;',5000);

        checkingForDeletedFalseEvalScript = falseEvalScript;

        var className = 'UserInputControl';

        var UserInputs = $('body').select('.' + className);
        UserInputs.each(function(s){ if($(s).id.indexOf(prop + '_') == 0) { humanReadableIDValue = $F(s); } });

        ServerFunction('NewExistsDeletedNotActive|' + humanReadableIDValue, null);
    }
}

/**
* Server callback from call to see if item exists on DB
* for use with formbuilder pages
* @param {string} args: 'True' or 'False' ('True' means it can be reactivated)
* @param {string} context: (Optional) context passed to server
* @private
*/
function NewExistsDeletedNotActive(args, context)
{
    if(args == 'True')
    {
        if(confirm(humanReadableIDValue + ' exists marked as deleted.\r\n Would you like to reactivate it rather than create a new one?'))
        {
            window.location.href = 'default.aspx?screen=Reactivate&TypeTableName=InventoryItem&CurrentValue='+ humanReadableIDValue + '&Redirect=default.aspx?screen=' + getQueryStringValue('screen');
        }
        else
        {
            setTimeout('eval(\'' + checkingForDeletedFalseEvalScript + '\');',10);
        }
    }
    else
    {
        setTimeout('eval(\'' + checkingForDeletedFalseEvalScript + '\');',10);
    }
    checkingForDeletedFalseEvalScript = '';
    humanReadableIDValue = '';
}

/**
* Set any element input or select control
* for select lists tries value first then text
* @param {string} element: ID or obj to populate value
* @param {string} value: value to set on element
* @throw nothing
*/
function $S(element, value)
{
    if(typeof element == 'string')
    {
        element = $(element);
    }
    
    if (element == null)
    { return; }
    
    switch(element.tagName)
    {
        case "CHECKBOX":
            if(getBool(value))
            { element.checked = true; }
            else
            { element.checked = false; }
            return;
        case "SELECT":
            element.selectedIndex = -1;
            for (var index=element.options.length-1; index>=0; index--)
	        {
		        if(element.options[index].value == value && !element.options[index].selected)
		        {
		            element.options[index].selected = true;
		            if(typeof element.onchange == 'function'){element.onchange();}
                    return;
                }
	        }
	        for (var index=element.options.length-1; index>=0; index--)
	        {
		        if(element.options[index].text == value && !element.options[index].selected)
		        {
		            element.options[index].selected = true;
		            if(typeof element.onchange == 'function'){element.onchange();}
                    return;
                }
	        }
	        if(element.options[0])
	        {
	            element.options[0].selected = true;
	        }
            return;
        case "INPUT":
            if(element.type.toUpperCase() == "CHECKBOX")
            {
                if(getBool(value))
                { element.checked = true; }
                else
                { element.checked = false; }
            }
            else if(element.type.toUpperCase() == "TEXT" && element.odaTextBox != null && typeof element.odaTextBox == 'object'){
                element.odaTextBox.SetValue(value);
            }
            else
            {
                element.value = value;
            }
            return;
        default:
            element.value = value;
            return;
    }
}

function $SF(element,value)
{
    $S(element, value);
    var bgImage = element.getStyle("backgroundImage");
    var bWidth = element.getStyle("borderWidth");
    var bStyle = element.getStyle("borderStyle");
    var bColor = element.getStyle("borderColor");
    var c = element.getStyle("color");
    new Effect.Highlight(element, { startcolor: '#ffff99', endcolor: '#ffffff' });
    
    element.setStyle({backgroundImage: bgImage, borderWidth: bWidth, borderStyle: bStyle, borderColor: bColor, color: c});
}

/**
* Get value from any element input or select control
* calls prototypes $F() but catches errors
* @param {string} element: ID or obj to populate value
* @return the value of the object
* @type object
* @throw nothing
*/
function $G(element)
{
    try
    {
        return $F(element);
    }
    catch(ex)
    {
        return '';
    }
}

/**
* Selects multiple options in a multi-select listbox
* @param {string} _element: ID or obj to populate value
* @param {string} _values: Comma seperated list of values
* @return void
* @type object
* @throw nothing
*/
function $SS(_element,_values){
    var values = _values.split(',');
    var element = $(_element);
    if(element != null && element.tagName.toUpperCase() == 'SELECT'){
      for(var x=0; x < element.options.length; x++){
          for(var i=0; i < values.length; i++){
              if(element.options[x].value == values[i]){
                  element.options[x].selected = true;
              }
          }
      }
    }
}


/*
* Get value from a RadioGroup by name
* @param {element} el: The parent form for the Radio Group
* @param {string} radioGroup: The name of the Radio Group
* @return the value of the Radio Group
* @type string
*/
function $RF(el, radioGroup) 
{
	if($(el).type && $(el).type.toLowerCase() == 'radio') 
	{
		var radioGroup = $(el).name;
		var el = $(el).form;
	} 
	else if ($(el).tagName.toLowerCase() != 'form') 
	{
		return false;
	}
 
	var checked = $(el).getInputs('radio', radioGroup).find(
		function(re) 
		{
			try
			{
				if(re.checked)
					return re.value;
			//return re.checked;
			}
			catch(e)
			{
				debug(e.message);
			}
		}
	);
	return (checked) ? $F(checked) : null;
}

/*
* Finds the Radio Group of the radio button passed as el.  Then sets the Radio button
* in the Radio Group that matches the value.
* @param {element} el: One of the Radio Buttons in the Radio Group that needs to be set
* @param {string} value: The value in the Radio Group that should be selected
* @return indication of successful selection
* @type bool
*/
function selectRadioButtonValue(el, value) {
    try
    {
        if($(el).type && $(el).type.toLowerCase() == 'radio') 
        {
            var radioGroup = $(el).name;
            var el = $(el).form;
        } 
        else if ($(el).tagName.toLowerCase() != 'form') 
        {
            return false;
        }
 	    var checked = false;
        checked = $(el).getInputs('radio', radioGroup).find(
            function(re) 
            {
        	    try
        	    {
	        	    if(re.value == value)
	        	    {
	        		    re.checked = true;
	        		    return true;
	        	    }
        	    }
		   	    catch(e)
		   	    {
		   		    debug(e.message);
		   	    }
            }
        );
    }
    catch(e)
    {
	    debug(e.message);
    }
    return checked;
}

/**
* hide lookup button for read only fields
* for use with form builder pages (or similar form)
* @param {string} element: ID or obj to populate value
* @throw nothing
*/
function hideLookupButton(element)
{
    if(typeof element == 'string')
    {
        element = $(element);
    }
    
    if (element == null)
    { return; }
    
    var btn = element.next();
    if(typeof btn != 'undefined' && btn.tagName == 'BUTTON')
    { btn.hide(); }
}

/**
* Check to See if String represents a boolean Value
* @param {string} str: string to convert to bool
* @return true if string can be matched as such false otherwise
* @type bool
*/
function getBool(str)
{
    str = String(str).toUpperCase();
    if(str == 'Y' || str == 'YES' || str == 'ON' || str == 'CHECKED' || str == 'T' || str == 'TRUE' || str == '1')
    {
        return true;
    }
    return false;
}
                
/**
* Loops through all child elements and removes them
* @param {string} element: ID or obj from which to remove children
*/
function clearChildren(element)
{
    if(typeof element == 'string')
    {
        element = $(element);
    }
    
    var elems = element.childElements()
    for(var index = 0; index < elems.length; index++)
    {
        elems[index].remove();
    }
}

var curStatus = 0;
var m_divStatus_img = null;
var statusImages = new Array();
statusImages[0] = new Image(100,100);
statusImages[0].src = './images/loader/loader-idle.gif';

statusImages[1] = new Image(100,100);
statusImages[1].src = './images/loader/loader.gif';

statusImages[2] = new Image(100,100);
statusImages[2].src = './images/loader/loader-stopped.gif';

/**
* Sets the status graphic.  Once in error status, use resetStatus to return to idle status.
* @param {int} _newStatus: New Desired status 0: idle, 1: processing, 2: error
*/
function setStatusImage(_newStatus)
{
    try{
        if(m_divStatus_img == null){m_divStatus_img = $('divStatus_img');}
        if(m_divStatus_img == null){return;}
        
        if(curStatus < 2)
        { setTimeout("m_divStatus_img.src = statusImages[" + _newStatus + "].src", 300); }
    }catch(ex){
    }
}

/**
* Sets the status graphic back to idle from error.
*/
function resetStatusImage()
{
    curStatus = 1;
    setStatusImage(0);
}

/**
* Builds a context menu that will eval the securitycontext attribute of any anchor
*/
function BuildSecurityContextMenus()
{
	var menuItems = [{
			name: 'Security', className: 'protoMenuItem', callback: function(e){ eval(Event.element(e).readAttribute('securitycontext')); }
		}];
			
	new Proto.Menu({selector: 'a[securitycontext]',
					className: 'protoMenu desktop',
					menuItems: menuItems});
}

/**
* Check to see if string is a real number
* @param {string} string2Test: string to check
* @return true if matches, false if doesn't
* @type bool
*/
function isNumeric(string2Test)
{
    var regExPattern = "(^(([0-9]*\\.[0-9]+)|([0-9]*)|(\\.[0-9]+)|(-[0-9]*\\.[0-9]+)|(-[0-9]*)|(-\\.[0-9]+))$)";
    return matches(string2Test,regExPattern);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  SQL Helper function
/////////////////////////////////////////////////////////////////////////////////////////////////////


/**
* Check for invalid words while building formulas
* @param {string} str: string to parse for invalid words.
* @return true if there are no injection words found
* @type bool
* @throws alert
*/
function checkForInjection(str)
{
    if(IsValidPattern(str.toLowerCase(),'^.* update .*|.* delete .*|.* drop .*|.* create .*|.* alter .*|.* truncate .*$'))
    {
        alert(" Statements that contain 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER' or 'TRUNCATE' are not excepted");
        return false;
    }
    return true;
}

/**
* Rounds a float to a specific precision
* @param {float} num: number to be rounded
* @param {int} prec: precision
* @return rounded float
* @type float
*/
function RoundFloat(num, prec) {
	var mul = Math.pow(10, prec);
	
	return (num * mul).toPrecision(10) / mul;
}

function getIFrameOffsets(srcEl) {
    if (srcEl && srcEl.ownerDocument) {
        if (srcEl.ownerDocument.location.href != window.top.location.href) {
            for (var x = 0; x < window.parent.frames.length; x++) {
                if (window.parent.frames[x].location.href = srcEl.ownerDocument.location.href) {
                    var windowOffsets = $(window.parent.frames[x].frameElement).cumulativeOffset();
                    var scrollOffsets = window.top.document.viewport.getScrollOffsets();
                    windowOffsets.top = windowOffsets.top - scrollOffsets.top;
                    windowOffsets.left = windowOffsets.left - scrollOffsets.left;
                    return windowOffsets;
                }
            }
        }
    }
    return null;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////  ODATooltip
/////////////////////////////////////////////////////////////////////////////////////////////////////

var odaToolTipInstance = null;

var ODATooltip = Class.create();
var ODATooltip_Show = null;

ODATooltip.prototype = {
    /**
    * Shows a tooltip
    * @param {object} _event: event object from the href
    * @param {string} _hoverDivID: id of div to use for tooltip (gets created dynamically if necessary)
    * @param {string} _innerHTML: optional HTML content of tooltip window
    * @param {string} _hoverPluginClass: optional Fully Qualified IUpdaterPlugin class name
    * @param {string} _objectID: ID parameter used during IUpdaterPlugin callback
    * @param {string} _tooltipClass: CSS Class name to use for the tooltip
    */
    initialize: function(_event, _hoverDivID, _innerHTML, _hoverPluginClass, _objectID, _tooltipClass) {
        var element = Event.element(_event);
        var tooltip = gToolTipManager.getToolTipByElement(element);

        //Create a tooltip if no tooltip exists for such element 
        if (!tooltip) {
            tooltip = gToolTipManager.createToolTip(element);

            //Use the fact that the image was named after a country
            //Extract the country name from the image, and set it as the value to be supplied to the web-service

            if (_hoverPluginClass != null) {
                tooltip.set_content("Loading...");
                var url = 'UpdaterPluginHost.aspx?PluginClass=' + _hoverPluginClass + '&' + 'ObjectID=' + _objectID;
                new Ajax.Request(url, {
                    method: 'get',
                    onSuccess: function(transport) {
                        tooltip.set_content(transport.responseText);
                        tooltip.show();
                    }
                });
            } else {
                tooltip.set_content(_innerHTML);
                tooltip.show();
            }
        }

        //Let the tooltip's own show mechanism take over from here - execute the onmouseover just once
        element.onmouseover = null;

    }
    /* if (odaToolTipInstance != null) {
    try {
    odaToolTipInstance.hide();
    clearTimeout(odaToolTipInstance.showTimer);
    clearTimeout(odaToolTipInstance.hideTimer);
    odaToolTipInstance = null;
    } catch (ex) { }
    }
    var divExists = ($(_hoverDivID) != null);

        this.div = new divWindow(_hoverDivID, "ToolTip");
    this.showTimer = null;
    this.hideTimer = null;

        if (_event == null) { _event = window.event; }

        if (_event != null) {
    var srcEl = Event.element(_event);
    $(_hoverDivID).clonePosition(srcEl, { setHeight: false, setWidth: false });
    var iframeOffsets = getIFrameOffsets(srcEl);
    if (iframeOffsets) {
    var hoverDivOffsets = $(_hoverDivID).cumulativeOffset();
    $(_hoverDivID).setStyle({ top: (iframeOffsets.top + hoverDivOffsets.top) + 'px'
    , left: (iframeOffsets.left + hoverDivOffsets.left) + 'px'
    });
    }
    }
    $(_hoverDivID).setStyle({ border: 'none' });
    $(_hoverDivID + "_handle").hide();
    if (_tooltipClass != null && _tooltipClass.toString().length > 0) {
    $(_hoverDivID + "_content").addClassName(_tooltipClass);
    }
    else {
    $(_hoverDivID + "_content").addClassName("ODAToolTip");
    }

        Event.observe(_hoverDivID, "mouseout", this.hide.bindAsEventListener(this));
    Event.observe(_hoverDivID, "mouseover", this.show.bindAsEventListener(this));

        // if the div is being created on this run
    if (!divExists) {
    // check to see if the HTML is simply provided to us and if so insert it into the div
    if (_innerHTML != null && _innerHTML.toString().length > 0) {
    $(_hoverDivID + "_content").update(_innerHTML);
    }
    // then check to see if we are to be invoking the IUpdaterPlugin interface class
    else if (_hoverPluginClass != null && _hoverPluginClass.toString().length > 0) {
    getPluginForm(_hoverDivID + "_content", _hoverPluginClass, 'ObjectID=' + _objectID, function() {
    var h = $(_hoverDivID + "_content").down().getHeight();
    h += 20;
    $(_hoverDivID).setStyle({ height: h + 'px' });
    $(_hoverDivID + "_content").setStyle({ height: h + 'px' });
    }, null);
    }
    // otherwise there will simply be a blank tooltip
    }
    odaToolTipInstance = this;
    },
    show: function() {
    clearTimeout(this.hideTimer);
    if (this.showTimer == null) {
    ODATooltip_Show = this._show.bind(this);
    this.showTimer = setTimeout("ODATooltip_Show();", 1000);
    }
    },
    _show: function() {
    this.div.show();
    clearTimeout(this.showTimer);
    this.showTimer = null;
    },
    hide: function() {
    clearTimeout(this.showTimer);
    this.showTimer = null;
    clearTimeout(this.hideTimer);
    if (this.div != null && typeof (this.div) == "object") {
    this.hideTimer = setTimeout("$('" + this.div.id + "').remove();", 200);
    }
    }*/
};




ODATech.clearAccessKeys = function() {
    var keys = customHotKeys.keys();
    for (var j = 0; j < keys.length; j++) {
        customHotKeys.unset(keys[j]);
    }
}

ODATech.setAccessKey = function(element, key) {
    customHotKeys.set(key, element);
}

/**
* Shows the FileUpload dialog
* @param {string} _dialogTitle: Title of the FileUpload dialog window
* @param {string} _fileKey: The Session variable name that will contain the uploaded file
* @param {string} _callbackFunctionName: optional name of a function to call on upload completed
* @param {string} _srcElement: optional name, or instance, of DOM element that initiated the File Upload dialog.  This element is used for positioning
*/
ODATech.showFileUpload = function(_dialogTitle, _fileKey, _callbackFunctionName, _srcElement) {
    var div = divWindow('divFileUpload', _dialogTitle);
    div.absolutize();
    if ($(_srcElement) == null) {
        div.setStyle({ top: '100px', left: '100px' });
    }
    else {
        div.clonePosition(_srcElement, { setHeight: false, setWidth: false, topOffset: _srcElement.offsetHeight });
    }
    var content = $('divFileUpload_content');
    if (_callbackFunctionName == null) { _callbackFunctionName = ""; }
    content.innerHTML = '<iframe id=\'frmFileUpload\' src=\'FileUpload.aspx?SessionVariableName=' + _fileKey + '&amp;IDToHide=divFileUpload&amp;callbackFunction=' + _callbackFunctionName + '\'/>';
    content.style.height = '';
}


function setZIndex(sourceEl, destEl) {
    // loop over the sourceEl and all parents to find the largest zIndex
    // then apply largest zIndex+1 to destEl

    var curEl = $(sourceEl);
    var largestZ = 0;
    while (curEl != null) {
        if (curEl.getStyle && parseInt(curEl.getStyle("zIndex")) > parseInt(largestZ)) {
            largestZ = parseInt(curEl.getStyle("zIndex"));
        }
        if (curEl.up) {
            curEl = $(curEl.up());
        } else {
            curEl = null;
        }
    }
    var curZ = parseInt($(destEl).getStyle("zIndex"));
    if (curZ != null && parseInt(curZ) < parseInt(largestZ)) {
        $(destEl).setStyle({ zIndex: largestZ + 1 });
    }
}




//sets the top of the element based on scroll distance
function setScrollOffset(_element) {
    var top = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    $(_element).style.top = top + 'px';
}

odaGetName = function(target) {
    var funcString = target.toString();

    var regEx = new RegExp(/function (.*)\s*\(|(.*)\s*=\s*function|(.*)\s*:\s* /);
    var matches = regEx.exec(funcString);

    var funcName = "";
    for (var i = 1; i < matches.length; i++) {
        if (matches[i] != null && matches[i] != 'undefined') {
            funcName = matches[i];
            return funcName;
        }
    }
}

Function.prototype.odaGetName = odaGetName.methodize();

function center(elt) {
    elt = $(elt);
    var eltDims = elt.getDimensions();
    var browserDims = document.body.getDimensions();

    // calculate the center of the page using the browser and element dimensions

    var y = 200;
    var x = (browserDims.width - eltDims.width) / 2;

    // set the style of the element so it is centered

    var styles = { position: 'absolute',
        top: y + 'px',
        left: x + 'px'
    };

    elt.setStyle(styles);
}




function ShowContact(/*long*/_ContactIdentifier, /*long*/_ContactID, /*long*/ _ContactInfoIdentifier) {
    if (_ContactID == null) {
        _ContactID = 0;
    }

    // remove all event listeners for Existing Contact Info Grid element
    /*if ($('Contact_' + _ContactID + '_ExistingContactInfoGrid')) {
        Event.stopObserving($('Contact_' + _ContactID + '_ExistingContactInfoGrid'));
    }*/
    var tempDivID = 'Contact' + _ContactID + '_ContactWindow';
    
    var alreadyExisted = false;
    if ($(tempDivID)) {
        alreadyExisted = true;
    }

    var window = divWindow(tempDivID, 'Contact');
    window.setStyle({ zIndex: '9999', top: '50px', left: '100px' });
    var temphtml = '<div style="float:left">';
    temphtml += '<input name="Contact_' + _ContactID + '_ContactIdentifier_txt" type="hidden" id="Contact_' + _ContactID + '_ContactIdentifier_txt" class="UserInputControl" value="' + _ContactIdentifier + '" />';
    temphtml += '<table>';
    temphtml += '<tr>';
    temphtml += '<td valign="top" colspan="2">';
    temphtml += '<table>';
    temphtml += '<tr>';
    temphtml += '<td valign="top">';
    temphtml += '<span id="Name_lbl">Name</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_Name_txt" type="text" id="Contact_' + _ContactID + '_Name_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="Description_lbl">Description</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_Description_txt" type="text" id="Contact_' + _ContactID + '_Description_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="Address1_lbl">Address</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_Address1_txt" type="text" id="Contact_' + _ContactID + '_Address1_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="Address2_lbl"></span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_Address2_txt" type="text" id="Contact_' + _ContactID + '_Address2_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="City_lbl">City</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_City_txt" type="text" id="Contact_' + _ContactID + '_City_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="StateProvince_lbl">State</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_StateProvince_txt" type="text" id="Contact_' + _ContactID + '_StateProvince_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="Country_lbl">Country</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_Country_txt" type="text" id="Contact_' + _ContactID + '_Country_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr class="">';
    temphtml += '<td valign="top">';
    temphtml += '<span id="PostalCode_lbl">Postal Code</span>';
    temphtml += '</td>';
    temphtml += '<td valign="top">';
    temphtml += '<input name="Contact_' + _ContactID + '_PostalCode_txt" type="text" id="Contact_' + _ContactID + '_PostalCode_txt" class="UserInputControl" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '</table>';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '<tr>';
    temphtml += '<td valign="top" colspan="2">';
    temphtml += '<input type="button" value="Save" onclick="SaveContact(' + _ContactIdentifier + ',' + _ContactID + ');" />';
    temphtml += '<input type="button" value="Cancel" onclick="$(\''+tempDivID+'\').hide();" />';
    temphtml += '</td>';
    temphtml += '</tr>';
    temphtml += '</table>';
    temphtml += '</div>';


    if (_ContactID != 0 && _ContactInfoIdentifier != null) {
        temphtml += '<div style="float:left">';

        temphtml += '<div id="Contact_' + _ContactID + '_NewContactInfo" style="display:none;" class="accentDiv">';
        temphtml += '<table>';
        temphtml += '<tr>';
        temphtml += '<td>Type</td>';
        temphtml += '<td>';
        temphtml += '<input id="ContactInfo_'+_ContactID+'_ContactInfoType_txt" class="UserInputControl" type="text" />';
        temphtml += '</td>';
        temphtml += '</tr>';
        temphtml += '<tr>';
        temphtml += '<td>Contact Information</td>';
        temphtml += '<td><input id="ContactInfo_' + _ContactID + '_Info_txt" class="UserInputControl" onkeypress="var odaKey = new ODAKeyCode(ensureEvent(event)); if(odaKey.keyCodeValue == odaKey.ENTER){saveContactInfo();}"/></td>';
        temphtml += '</tr>';
        temphtml += '<tr>';
        temphtml += '<td>Description</td>';
        temphtml += '<td><input id="ContactInfo_' + _ContactID + '_Description_txt" class="UserInputControl" onkeypress="var odaKey = new ODAKeyCode(ensureEvent(event)); if(odaKey.keyCodeValue == odaKey.ENTER){saveContactInfo();}"/></td>';
        temphtml += '</tr>';
        temphtml += '<tr>';
        temphtml += '<td colspan="2">';
        temphtml += '<input type="button" value="Save" onclick="SaveContactInfo(' + _ContactInfoIdentifier + ',' + _ContactID + ');" />';
        temphtml += '<input type="button" value="Cancel" onclick="$(\'Contact_' + _ContactID + '_NewContactInfo\').hide(); $(\'Contact_' + _ContactID + '_ExistingContactInfo\').show();" />';
        temphtml += '</td>';
        temphtml += '</tr>';
        temphtml += '</table>';
        temphtml += '</div>';



        temphtml += '<div id="Contact_'+_ContactID+'_ExistingContactInfo">';
        temphtml += '<table>';
        temphtml += '<tr>';
        temphtml += '<td><a href="#" onclick="$(\'Contact_' + _ContactID + '_ExistingContactInfo\').hide(); $(\'Contact_' + _ContactID + '_NewContactInfo\').show(); return false;">New Contact Information</a></td>';
        temphtml += '</tr>';
        temphtml += '<tr>';
        temphtml += '<td valign="top">';
        temphtml += '</td>';
        temphtml += '</tr>';
        temphtml += '<tr>';
        temphtml += '<td valign="top">';
        temphtml += '<div id="Contact_'+_ContactID+'_ExistingContactInfoGrid"></div>';
        temphtml += '</td>';
        temphtml += '</tr>';
        temphtml += '</table>';
        temphtml += '</div>';

        temphtml += '</div>';
    }

    if (!alreadyExisted) {
        $(tempDivID + '_content').update(temphtml);
    }

    if (_ContactID != 0) {
        showLoading();
        ODATech.initializeLookup('ContactInfo_' + _ContactID + '_ContactInfoType_txt', 'ContactInfoType');
        var context = {};
        context.ContactIdentifier = _ContactIdentifier;
        context.ContactID = _ContactID;
        context.ContactInfoIdentifier = _ContactInfoIdentifier;
        ServerFunction("Odatech.Business.ContactHelper.GetContact|" + _ContactID, Object.toJSON(context));
    }
}


function GetContactReturn(args, context) {
    if (parseInt(context.ContactID, 10) == 0) {
        hideLoading();
        return;
    }

    var temp = unescape(args).evalJSON();
    $S('Contact_' + context.ContactID + '_Name_txt', temp.Name);
    $S('Contact_' + context.ContactID + '_Description_txt', temp.Description);
    $S('Contact_' + context.ContactID + '_Address1_txt', temp.Address1);
    $S('Contact_' + context.ContactID + '_Address2_txt', temp.Address2);
    $S('Contact_' + context.ContactID + '_City_txt', temp.City);
    $S('Contact_' + context.ContactID + '_StateProvince_txt', temp.State);
    $S('Contact_' + context.ContactID + '_Country_txt', temp.Country);
    $S('Contact_' + context.ContactID + '_PostalCode_txt', temp.PostalCode);

    //TODO Change the reportID

   
    ODATech.RenderReport('Contact_' + context.ContactID + '_ExistingContactInfoGrid', null, 'Contact Info List', '', temp.ContactInfoIdentifier);
    //ODATech.RenderSearch('Contact_' + context.ContactID + '_ExistingContactInfoGrid', { GridOnly:true, autoPrompts: true, reportID: -124, additionalParams: 'QueryID=' + temp.ContactInfoIdentifier });

    hideLoading();
}


function SaveContactInfo(_ContactInfoIdentifier, _ContactID) {
    var details = buildJSON('Contact_' + _ContactID + '_NewContactInfo', 'UserInputControl', 'ContactInfo_' + _ContactID + '_');
    showLoading("Saving...");
    var context = {};
    context.ContactInfoIdentifier = _ContactInfoIdentifier;
    context.ContactID = _ContactID;
    ServerFunction("Odatech.Business.ContactHelper.SaveContactInfo|" + _ContactInfoIdentifier + "|" + _ContactID + "|" + details, Object.toJSON(context));
}
function SaveContactInfoReturn(args, context) {
    alert(args);
    $S('ContactInfo_' + context.ContactID + '_ContactInfoType_txt', '');
    $S('ContactInfo_' + context.ContactID + '_Info_txt', '');
    $S('ContactInfo_' + context.ContactID + '_Description_txt', '');
    
    $('Contact_' + context.ContactID + '_NewContactInfo').hide();
    $('Contact_' + context.ContactID + '_ExistingContactInfo').show();

    if ($('Contact_' + context.ContactID + '_ExistingContactInfoGrid')) {
        $('Contact_' + context.ContactID + '_ExistingContactInfoGrid').fire("RenderSearch:Refresh");
    }
    hideLoading();
}


function SaveContact(_contactIdentifier, _ContactID) {
    var details = buildJSON('Contact' + _ContactID + '_ContactWindow', 'UserInputControl', 'Contact_' + _ContactID + '_');
    var context = {};
    context.ContactIdentifier = _contactIdentifier;
    context.ContactID = _ContactID;
    showLoading("Saving...");
    ServerFunction("Odatech.Business.ContactHelper.SaveContact|" + _contactIdentifier + "|" + _ContactID + "|" + details, Object.toJSON(context));
}
function SaveContactReturn(args, context) {
    $('Contact' + context.ContactID + '_ContactWindow').hide();

    if (parseInt(context.ContactID, 10) == 0) {
        var temp = args.split("~^~");
        ShowContact(context.ContactIdentifier, parseInt(temp[0], 10), parseInt(temp[1], 10));
    } else {
        alert(args);
        hideLoading();
    }

    if (typeof (SaveContactCallback) == "function") {
        SaveContactCallback();
    }
}


function DeleteContactInfo(_ContactInfoID) {
    if (confirm('Are you sure you want to Delete this contact info?')) {
        showLoading("Deleting...");
        ServerFunction("Odatech.Business.ContactHelper.DeleteContactInfo|" + _ContactInfoID, _ContactInfoID);
    }
}
function DeleteContactInfoReturn(args, context) {
    var contactID = parseInt(args, 10);
    if (contactID != 0 && $('Contact_' + contactID + '_ExistingContactInfoGrid')) {
        $('Contact_' + contactID + '_ExistingContactInfoGrid').fire("RenderSearch:Refresh");
    }
    hideLoading();
}


function odaDecode(str) {
    var ta = document.createElement("textarea");
    ta.innerHTML = str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
    var val = ta.value;
    delete ta;
    return val;
}
