var MULTIPLE_VALUES_SEPARATOR = searchCharacters[1];
var IMAGE_BUTTON_ENABLE = true;
var IMAGE_BUTTON_DISABLE = false;
var IMAGE_BUTTON_ENABLE_STRING = "IMAGE_BUTTON_ENABLE";
var IMAGE_BUTTON_DISABLE_STRING = "IMAGE_BUTTON_DISABLE";
var DefaultDecimalSeparator = ".";
var MonetaryDecimalSeparator = ".";
var messageID = null;
var messageDelayTime = 1;
var IN_PROGRESS = "window.document.body.style.cursor = 'progress';showStatusMessage();";

isNav = (navigator.appName.indexOf("Netscape") != -1) ? true : false;
isIE = (navigator.appName.indexOf("Microsoft") != -1) ? true : false;
isIE6 = (navigator.appVersion.indexOf("MSIE 6") != -1) ? true : false;

function checkCookieEnabled()
{
    document.cookie = "testcookie";
    var cookieEnabled = (document.cookie.indexOf("testcookie") != -1) ? true : false;
    return cookieEnabled;
}

function deleteTestCookie()
{
    var d = new Date();
    document.cookie = "testcookie;expires=" + d.toGMTString() + ";" + ";";
}

function showCalendar(datePickerComponent, fieldName, onChangeCallback)
{
    var obj = eval('document.' + fieldName);
    if(obj != null)
    {
        var url = datePickerComponent + '?fieldName=' + fieldName 
                    + '&refdate=' + convertToDatePickerParam((obj.value != null && obj.value != "") ? obj.value : dateToString(new Date()));
        if(onChangeCallback != null)
            url = url + '&onChangeCallback=' + onChangeCallback;
        vWinCal = window.open(url, 'DatePicker', 'height='+CalendarPageHeight+', width='+CalendarPageWidth+', top=50, left=50, screenX=0, screenY=0, resizable=no, menubar=no, toolbar=no, titlebar=no, statusbar=no, status=no, scrollbars=no');
    }
}

/**************************************************************************************************
    FUNCTION NAME: showStatusMessage
    FUNCTION DESC: Displays a Status message on the current page
***************************************************************************************************/
function showStatusMessage()
{
    messageID = setTimeout("showPopupMessageWindow()", messageDelayTime);
}

function showPopupMessageWindow() {
    var obj = document.getElementById("statusMessage");
    if(obj != null) {
        obj.style.visibility = "visible";
        obj.style.backgroundColor = "#fff6a6";
        obj.style.borderStyle = "solid";
        obj.style.borderWidth = 3;
        obj.style.borderColor = "#c6c2c6";
        obj.style.position = "absolute";
        obj.style.width = '4cm';
        obj.style.wordWrap = 'break-word';
        obj.style.padding = 10;        
        obj.style.left=(document.body.clientWidth/2) - (obj.offsetWidth/2);
        obj.style.top=(document.body.clientHeight/2) - (obj.offsetHeight/2);
    }
}

function hidePopupMessageWindow() {
    var obj = document.getElementById("statusMessage");
    if(obj != null)
        obj.style.visibility = "hidden";
}

function changeBorder(id, style, width)
{
    if(document.getElementById)
    {
        var obj = document.getElementById(id);
        if(obj != null)
        {
            obj.style.borderStyle = style;
            obj.style.borderWidth = width;
        }
    }
}

function checkOnSubmit(form)
{
    if (typeof(this['submitPageForm']) != 'undefined')
        submitPageForm(form);
    return;
}

function keyPressed(e, form, gatewayPath)
{
    if (e.keyCode == 13)
    {
        var inputsFound = 0;
        for (var i = 0, feLen = form.elements.length; i < feLen; i++)
            if (((form.elements[i].type.indexOf('text') > -1) && (form.elements[i].name != 'JumpTo')) ||
                    (form.elements[i].type.indexOf('password') > -1))
                inputsFound++;

        var elemStr = "";
        source = null;
        if (isIE)
        {
            source = '' + e.srcElement;
            elemStr = 'javascript:';
        }
        else if (isNav)
        {
            source = '' + e.target;
            elemStr = 'HTMLAnchorElement';
        }
        if (inputsFound != 1)
        {
            if (source.indexOf(elemStr) >= 0)
            {
                e.cancelBubble = true;
                return true;
            }
            else if (source.indexOf(gatewayPath) >= 0)
            {
                var tmp = source.substr(source.indexOf(gatewayPath) + gatewayPath.length);
                if (tmp == undefined || tmp.length == 0)
                {
                    e.cancelBubble = true;
                    return;
                }
            }
            if (typeof(this['submitPageForm']) != 'undefined')
                submitPageForm(form);
            e.cancelBubble = true;
            return false;
        }
        else
        {
            if (source.indexOf(elemStr) >= 0)
            {
                e.cancelBubble = true;
                return true;
            }
        }
    }
}

function catchKeyPressed()
{
    var forms = document.forms;
    if ((window.event.keyCode == 13) && (forms != null) && (forms.length > 0))
    {
        var srctype = window.event.srcElement.type;
        var inputsFound = 0;
        if (forms.length == 1)
        {
            for (var i = 0, feLen = forms[0].elements.length; ((inputsFound <= 1) && (i < feLen)); i++)
            {
                formelem = forms[0].elements[i];
                if ((((formelem.type.indexOf('text') != -1) && (formelem.name != 'JumpTo')) || 
                        (formelem.type.indexOf('password') != -1)) && !formelem.disabled)
                    inputsFound++;
            }
        }
        var emphButton = document.getElementById("buttonEmphasized");
        if(emphButton)
        {
            var buttonNodes = emphButton.childNodes;
            if (buttonNodes)
                for (var i = 0, bnLen = buttonNodes.length; i < bnLen; i++)
                    if (buttonNodes(i).href && ((inputsFound != 1) || 
                            (srctype == 'select-one') || (srctype == 'select-multiple') ||
                            (srctype == 'checkbox') || (srctype == 'radio')))
                    {
                        location.href = buttonNodes(i).href;
                        window.event.cancelBubble = true;
                    }
        }
    }
}

function afterPageLoaded()
{
    if(document.onLoadFunctions != null)
        for (var i = 0, olLen = document.onLoadFunctions.length; i < olLen; i++)
        {
            document.onLoadFunctions[i]();
            var fcnString = document.onLoadFunctions[i].toString();
            if ((fcnString.indexOf("i2uiCollapseContainerIgnoreIndicator") != -1) ||
                    (fcnString.indexOf("i2uiExpandContainerIgnoreIndicator") != -1))
                continue;
            if ((fcnString.indexOf("i2uiCollapseContainer") != -1) ||
                    (fcnString.indexOf("i2uiExpandContainer") != -1))
            {
                var idx0 = fcnString.indexOf("'");
                var idx1 = fcnString.lastIndexOf("'");
                setConstraintIndicator(trimBeginEnd(fcnString.substring(idx0 + 1, idx1)));
            }
        }

    resizeTables();
}

function resize()
{
    resizeTables();

    /*
     * For future Tab scrolling.
    tabTag = document.getElementById("tabSelected");
    if (tabTag != undefined)
        tmuiResetTabs(getTag(tabTag, "TABLE").id, document.body.clientWidth - 45);
    */
}

function doResetShellActionsAndUsername(doc, shellActions, userInfo, doFocus)
{
    shellActionsObj = doc.getElementById('shellActions');
    if (shellActionsObj != null)
        shellActionsObj.innerHTML='<BR>'+shellActions;
    shellUsername = doc.getElementById('shellUsername');
    if (shellUsername != null)
        shellUsername.innerHTML='<BR>'+encodeJSValue(userInfo);
    var shellContent = top.i2ui_shell_content;
    if (shellContent.nav != null && shellContent.nav.userRole != userInfo)
    	shellContent.nav.location.reload();
    else
        shellContent.nav.navLoaded = true;

    navLoaded(shellContent);

    var doc1;
    if (shellContent.results != null)
        doc1 = shellContent.results.document;
    else
        doc1 = shellContent.document;
    if (doc1 != null)
    {
        var forms = doc1.forms;

        if (doFocus && (forms != null) && (forms.length > 0))
            putInFocus(forms[0]);
    }
}

function navLoaded(_target)
{
    var frameStatus = _target.nav.navLoaded;
    if (!frameStatus)
    {
        cmd = function(){navLoaded(_target);}
        setTimeout("cmd()", 10);
    }
    else
        window.document.body.style.cursor = 'auto';
}

function showStatus()
{
    window.document.body.style.cursor = 'progress';
    showStatusMessage();
}

function validateSaveSearch(form, dir)
{
    if(form.saveSearchAs.value.length == 0) {
        messageAlert("SPECIFY_NAME_WHEN_SAVING_SEARCH");
        form.saveSearchAs.focus();
        return false;
    }
    if(!isAlphanumeric(form.saveSearchAs.value)) {
        messageAlert("ALPHANUMERIC", "SAVE_SEARCH_AS");
        form.saveSearchAs.focus();
        return false;
    }

    for(var j = 0, k = form.savedSearch.options.length; j < k; j++)
        if(j != form.savedSearch.selectedIndex && form.savedSearch.options[j].value == form.saveSearchAs.value)
            return ('yes' == i2uiShowMessageBox(dir + 'ModalDialog.jsp?interaction=YESNO&icontype=WARN&key=SEARCH_NAME_ALREADY_EXISTS_REPLACE', 90, 250));

    return true;
}

function resetForm(form) {
    for(var i = 0, j = form.elements.length; i < j; i++) {
        var formObj = eval('form.elements[' + i + ']');
        var formObjType = eval('form.elements[' + i + '].type');
        if(formObjType == 'text' || formObjType == 'textarea')
            formObj.value = '';
        else if(formObjType == 'checkbox')
            formObj.checked = false;
        else if(formObjType == 'select-one')
            formObj.selectedIndex = 0;
        else if(formObjType == 'select-multiple') {
            var options = formObj.options;
            for (var k = 0, m = options.length; k < m; k++) {
                options[k].selected = false;
            }
            formObj.options.selectedIndex = 0;
            showComboboxSelection(formObj);
        }
    }
}

function savedSearchChanged(form) {
    var savedSearchIndex = form.savedSearch.selectedIndex;
    if(savedSearchIndex != 0) {
        resetForm(form);
        form.saveSearchAs.value = form.savedSearch[savedSearchIndex].value;
        savedSearchIndex--;
        var savedNameArray = eval('savedNameArray' + savedSearchIndex);
        var savedValueArray = eval('savedValueArray' + savedSearchIndex);
        for(var i = 0, snLen = savedNameArray.length; i < snLen; i++) {
            var formObj = form[savedNameArray[i]];
            if(formObj == undefined) {
                messageAlert("INVALID_CONSTRAINT");
                return;
            }
            var formObjType = formObj.type;
            if(formObjType == 'text' || formObjType == 'textarea')
                formObj.value = savedValueArray[i];
            else if(formObjType == 'select-one') {
                for(var j = 0, j2 = formObj.options.length; j < j2; j++) {
                    if(formObj.options[j].value == savedValueArray[i]) {
                        formObj.selectedIndex = j;
                        break;
                    }
                }
                refreshCountriesStates(formObj);
            }
            else if(formObjType == 'checkbox') {
                if(toUpperCase(savedValueArray[i]) == 'CHECKED')
                    formObj.checked = true;
            }
            else if(formObjType == 'hidden') {
                var formObj_ = form[savedNameArray[i]+"_"];
                if (formObj_ != undefined) {
                    formObjType = formObj_.type;
                    if(formObjType == 'select-multiple') {
                        var values = savedValueArray[i].split(MULTIPLE_VALUES_SEPARATOR);
                        var options = formObj_.options;
                        for (var k = 0, k2 = values.length; k < k2; k++) {
                            var value = values[k];
                            for (var j = 0, j2 = options.length; j < j2; j++) {
                                if(options[j].value == value) {
                                    options[j].selected = true;
                                    break;
                                }
                            }
                        }
                        refreshCountriesStates(formObj_);
                    }
                    showComboboxSelection(formObj_);
                } else if(formObj.value != savedValueArray[i]) {
                    messageAlert("CONSTRAINT_REPLACED");
                }
            }
        }
        form.savedSearch.selectedIndex = savedSearchIndex + 1;
    }
}

//========================================================================
//  Function Name: validRowsSelected
//  Description  : Determines validity of selected row(s)
//========================================================================

function validRowsSelected(form, selectionMode, tableType, tableObj)
{
    if(tableType == '4')// Gantt Chart
    {
        if(selectionMode != 'NOTRQD' && form.RowKey.value != undefined && form.RowKey.value.length < 1)
        {
            messageAlert("SELECT_GANTT_ENTITY");
            return false;
        }
    }
    
    else if(selectionMode == 'ONEPLUS' || selectionMode == 'ONE' || selectionMode == 'ZEROONETWO')
    {
        var count = rowsSelectedCount(form);
        if(count < 1 && selectionMode != 'ZEROONETWO')
        {
            if(tableObj == null || !tableObj.checkHasSelectedRow())
            {
                if(tableObj == null)
                    messageAlert((tableType == '1') ? "SELECT_RADIO_BUTTON" : "SELECT_CHECKBOX");
                return false;
            }
        }
        else if(selectionMode == 'ONE' || selectionMode == 'ZEROONETWO')
        {
            var maxNum = (selectionMode == 'ONE') ? "1" : "2";
            if(count > maxNum)
            {
                messageAlert((selectionMode == 'ONE') ? "MULTI_SELECT_NOT_ALLOW_FOR_ACTION" : "NO_MORE_THAN_TWO_ENTRIES_CAN_BE_SELECTED");
                return false;
            }
        }
    }
    return true;
}
//========================================================================
//  Function Name: rowsSelectedCount
//  Description  : Determines the number of rows selected 
//========================================================================
function rowsSelectedCount(form)
{
    if(form != undefined && form.RowKey != undefined)
    {
        var len = form.RowKey.length;

        if(len == undefined && form.RowKey.checked)// nodeList not available - 1 row selected
            return 1;  

        if (len != undefined && len > 1)
        {
            var count = 0;
            var rk = form.RowKey;
            for (var i = 0; i < len && count < 4; i++)
                if(rk[i].checked)
                    count++;
            return count;
        }
    }
    return 0;
}

//========================================================================
//  Function Name: getTimeInterval
//  Description  : Determines the time difference between two date strings 
//========================================================================

function getTimeInterval(fromDate, fromTime, toDate, toTime)
{
    var fromHours = !isTime(fromTime) ? 0 : (fromTime.substring(0, 2));
    var fromMinutes = !isTime(fromTime) ? 0 : (fromTime.substring(3, 5));
    var toHours = !isTime(toTime) ? 0 : (toTime.substring(0, 2));
    var toMinutes = !isTime(toTime) ? 0 : (toTime.substring(3, 5));
    var tempDate = new Date();

    var fromD = (fromDate == '' || !isDate(fromDate)) ? tempDate : convertToDateObj(fromDate)
        fromD.setHours(fromHours, fromMinutes);
    if(fromD != tempDate)
        fromD.setMonth(fromD.getMonth()-1);

    var toD = (toDate == '' || !isDate(toDate)) ? tempDate : convertToDateObj(toDate)
        toD.setHours(toHours, toMinutes);
    if(toD != tempDate)
        toD.setMonth(toD.getMonth()-1);

    var timeInterval = toD.getTime()-fromD.getTime();
    timeInterval = (timeInterval < 0) ? 0 : timeInterval;
    return timeInterval;
}

//===================================================================
//  Function Name: addTime
//  Description  : Adds a Time interval to a date object 
//  Returns      : Date as a string, time as a string 
//===================================================================
function addTime(dateStr, timeStr, timeInterval)
{
    var sourceDate = convertToYMD(dateStr);
    var sDay = sourceDate.charAt(8) == "0" ? sourceDate.substring(9) : sourceDate.substring(8, 10);
    var iDay = parseIntNumeric(sDay);

    var sMonth = sourceDate.charAt(5) == "0" ? sourceDate.substring(6) : sourceDate.substring(5, 7);
    var iMonth = parseIntNumeric(sMonth) - 1;

    var sYear = sourceDate.substring(0, 4);
    var iYear = parseIntNumeric(sYear);

    var dateObj = new Date(iYear, iMonth, iDay);
    var hours = !isTime(timeStr) ? 0 : (timeStr.substring(0, 2));
    var minutes = !isTime(timeStr) ? 0 : (timeStr.substring(3, 5));

    dateObj.setHours(hours, minutes);
    // add the time interval
    dateObj.setTime(dateObj.getTime()+timeInterval);
    retValue = new Array();
    retValue[0] = dateToString(dateObj); // Date
    retValue[1] = timeToString(dateObj); // Time   

    return retValue;
}

//===================================================================
//  Function Name: timeToString
//  Description  : Converts the time associated with a date object 
//                 to a string, using Locale. 
//  Returns      : Time as a string 
//===================================================================
function timeToString(date)
{
    var format = toUpperCase(TimeFormat);

    if(format == null || format == "")
        format = "HH:MM";

    var timeSep = format.charAt(2);   
    var hour = date.getHours();
    hour = (hour.toString().length < 2) ? "0" + hour : hour;
    var min = date.getMinutes();
    min = (min.toString().length < 2) ? "0" + min : min;

    return (hour + timeSep + min);
}

/**************************************************************************************************
    FUNCTION NAME: dateToString
    FUNCTION DESC: Converts a Date object to String. The date format is being derived
    from the variable DateFormat as embedded in the LocaleSpecific include file
***************************************************************************************************/
function dateToString(date)
{
    var format = toUpperCase(DateFormat);
    if (format == null || format == "")
        format = "MM/DD/YYYY";

    var vMonth = date.getMonth() + 1;
    var vDD = date.getDate();
    var vY4 = date.getFullYear();
    vMonth = (vMonth.toString().length < 2) ? "0" + vMonth : vMonth;
    var vDD = (vDD.toString().length < 2) ? "0" + vDD : vDD;
    var vData;

    switch (format) {

        /*    USA Format MM/dd/yyyy */
        case "MM\/DD\/YYYY" :
            vData = vMonth + "\/" + vDD + "\/" + vY4;
            break;

        case "MM-DD-YYYY" :
            vData = vMonth + "-" + vDD + "-" + vY4;
            break;

        case "MM.DD.YYYY" :
            vData = vMonth + "." + vDD + "." + vY4;
            break;

        case "DD\/MM\/YYYY" :
            vData = vDD + "\/" + vMonth + "\/" + vY4;
            break;

        case "DD-MM-YYYY" :
            vData = vDD + "-" + vMonth + "-" + vY4;
            break;

            /*    EUR Format dd.MM.yyyy */
        case "DD.MM.YYYY" :
            vData = vDD + "." + vMonth + "." + vY4;
            break;

        case "YYYY\/MM\/DD" :
            vData = vY4 + "\/" + vMonth + "\/" + vDD;
            break;

            /*   ISO Format yyyy-MM-dd */
            /*   JIS Format yyyy-MM-dd */
        case "YYYY-MM-DD" :
            vData = vY4 + "-" + vMonth + "-" + vDD;
            break;

        case "YYYY.MM.DD" :
            vData = vY4 + "." + vMonth + "." + vDD;
            break;

        case "YYYY\/DD\/MM" :
            vData = vY4 + "\/" + vDD + "\/" + vMonth;
            break;

        case "YYYY-DD-MM" :
            vData = vY4 + "-" + vDD + "-" + vMonth;
            break;

        case "YYYY.DD.MM" :
            vData = vY4 + "." + vDD + "." + vMonth;
            break;

        default :
            vData = vMonth + "\/" + vDD + "\/" + vY4;
    }

    return vData;
}

//===================================================================
//          Cookie
//===================================================================

function setCookie(name, value, expire)
{
    document.cookie = name + "=" + escape(value)
                        + ((expire == null) ? "" : ("; expires=" + expire.toGMTString()));
}

function getCookie(Name)
{
    var search = Name + "="
    if (document.cookie.length > 0)
    { // if there are any cookies
        offset = document.cookie.indexOf(search);
        if (offset != -1)
        { // if cookie exists
            offset += search.length;
            // set index of beginning of value
            end = document.cookie.indexOf(";", offset);
            // set index of end of cookie value
            if (end == -1)
                end = document.cookie.length;
            return unescape(document.cookie.substring(offset, end));
        }
    }
}

function register(name, value, milisecs)
{
    var today = new Date();
    var expires = new Date();
    expires.setTime(today.getTime() + milisecs);
    setCookie(name, value, expires);
}

var states;
var isNavPadOpen;

//===================================================================
//          DateUtils
//===================================================================

function compareDates(date1, date2)
{
    var compDate1 = comparableDate(date1);
    var compDate2 = comparableDate(date2);

    return compareString(compDate1, compDate2);
}

function compareDateTime(date1, time1, date2, time2)
{
    var timeSep = TimeFormat.charAt(2);
    var compDate1 = comparableDate(date1);
    var compDate2 = comparableDate(date2);
    var compTime1 = (time1 == "") ? ("00"+timeSep+"00") : time1;
    var compTime2 = (time2 == "") ? ("00"+timeSep+"00") : time2;
    var dt1 = compDate1 + " " + compTime1;
    var dt2 = compDate2 + " " + compTime2;

    return compareDateTimes(dt1, dt2);
}

function compareTime(time1, time2)
{
    return compareString(time1, time2);
}

function compareDateTimes(dt1, dt2)
{
    return compareString(dt1, dt2);
}


/*
  FUNCTION NAME: COMPARABLEDATE
  FUNCTION DESC: Reformats a date string passed to it into a common format
  suitable for date comparisons [yyyy][sep][MM][sep][dd].
  LAST MODIFIED: 2001/07/30 - Peggy O'Toole - Internationalization (Date Handling)
*/

function comparableDate(sDate)
{
    if (sDate.length > 0)
    {
        var firstChar = toUpperCase(DateFormat.charAt(0));
        var lastChar  = toUpperCase(DateFormat.charAt(9));

        switch (firstChar)
        {
            case "Y":
                /*
                  format must be either [yyyy][sep][MM][sep][dd] or [yyyy][sep][dd][sep][MM]
                */
                var datesep1    = sDate.charAt(4);
                var datesep2    = sDate.charAt(7);

                var dateYear    = sDate.substring(0,4);

                if (lastChar == "M")
                {
                    var dateDay     = sDate.substring(5,7);
                    var dateMonth   = sDate.substring(8,10);
                }
                else
                {
                    var dateMonth   = sDate.substring(5,7);
                    var dateDay     = sDate.substring(8,10);
                }
                break;

            case "M":
                /*
                  format must be [MM][sep][dd][sep][yyyy]
                */
                var datesep1    = sDate.charAt(2);
                var datesep2    = sDate.charAt(5);

                var dateMonth   = sDate.substring(0,2);
                var dateDay     = sDate.substring(3,5);
                var dateYear    = sDate.substring(6,10);
                break;

            case "D":
                /*
                  format must be [dd][sep][MM][sep][yyyy]
                */
                var datesep1    = sDate.charAt(2);
                var datesep2    = sDate.charAt(5);

                var dateDay     = sDate.substring(0,2);
                var dateMonth   = sDate.substring(3,5);
                var dateYear    = sDate.substring(6,10);
                break;
        }
        /*
          build date in common format [yyyy][sep][MM][sep][dd] both to simplify
          validation of individual components and to support comparison of two date fields
        */
        var sNewValue = dateYear + datesep1 + dateMonth + datesep2 + dateDay;
        return sNewValue;
    }
    else
        return sDate;
}


/*
  FUNCTION NAME: ISDATE
  FUNCTION DESC: Determines whether a ten character string represents a valid date
  based on the DateFormat in effect for this language/locale.
  LAST MODIFIED: 2001/07/30 - Peggy O'Toole - Internationalization (Date Handling)
*/

function isDate(str) {
    if (str.length != 10)
        return false;
    var ymd = convertToYMD(str);
    if (ymd == null)
        return false;
  
    /*
      extract month, day, year and validate separately
    */
    var month = ymd.charAt(5) == "0" ? parseInt(ymd.substring(6,7)) : parseInt(ymd.substring(5,7));
    var day = ymd.charAt(8) == "0" ? parseInt(ymd.substring(9,10)) : parseInt(ymd.substring(8,10));
    var begin = ymd.charAt(0) == "0" ? (ymd.charAt(1) == "0" ? (ymd.charAt(2) == "0" ? 3 : 2) : 1) : 0;
    var year = parseInt(ymd.substring(begin, 4));

    if (day == 0) { return false }
    if (month == 0 || month > 12) { return false }
    if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
        if (day > 31)
            return false;
    } else {
        if (month == 4 || month == 6 || month == 9 || month == 11) {
            if (day > 30)
                return false;
        } else {
            if (year%4 != 0) {
                if (day > 28)
                    return false;
            } else {
                if (day > 29)
                    return false;
            }
        }
    }
    return true;
}

// Return the date string in ymd format 
// Codes extracted from IsDate()
function convertToYMD(str)
{
    var j; // make it local such it would interfere with the outside loop

    var datesep = getDateSep();
/*
    reformat string to ymd format to simplify validation 
    argument string is assumed to be in locale-specific DateFormat
*/      
    var ymd = comparableDate(str); 

/*
    separator characters must match declared date separator  
    date characters must be numeric (0 through 9)
*/     
    for (var j = 0, j2 = str.length; j < j2; j++) {
        if ((j == 4) || (j == 7)) {
            if (ymd.charAt(j) != datesep)
                return null;
        } else {
            if ((ymd.charAt(j) < "0") || (ymd.charAt(j) > "9"))
                return null;
        }
    }
    return ymd;
}

/*
    identify date separator in use (extract from locale-specific DateFormat)
*/  
function getDateSep()
{
    var dateSep = "/"; // default value
    var firstChar = toUpperCase(DateFormat.charAt(0)); 
    if (firstChar != 'Y')
        dateSep   = DateFormat.charAt(2);
    else
        dateSep = DateFormat.charAt(4);
    return dateSep;
}


function isTime(str) {
    var timeSep = TimeFormat.charAt(2);
    var j; // make it local such it would interfere with the outside loop
    var l = str.length;
    if (l != 5)
        return false;
    for (j = 0; j < l; j++) {
        if ((l == 5) && (j == 2)) {
            if (str.charAt(j) != timeSep)
                return false;
        } else {
            if ((str.charAt(j) < "0") || (str.charAt(j) > "9"))
                return false;
        }
    }

    var hour = str.charAt(0) == "0" ? parseInt(str.substring(1,2)) : parseInt(str.substring(0,2));
    var minute = str.charAt(3) == "0" ? parseInt(str.substring(4,5)) : parseInt(str.substring(3,5));

    if (hour < 0 || hour > 23)
        return false;
    if (minute < 0 || minute > 59)
        return false;

    return true;
}

/*
  return true if str format is valid based on functions isDate and isTime
*/
function isDateTime(str) {

    if (str.length > 0)
    {
        var iIndex  = str.indexOf(" ");
        var sHour   = str.substring(iIndex + 1, str.length);
        var sDate   = str.substring(0, iIndex);
        return isDate(sDate) && isTime(sHour);
    }
    else
        return false;
}

//****************************************************************************************
//   Convert a date string to a date object, str must be valid when checking with isDate()
//*****************************************************************************************
function convertToDateObj(str)
{
    var ymd = convertToYMD(str);
    if (ymd == null)
        return null;
/*
    extract month, day, year and validate separately
*/ 
    var month = ymd.charAt(5) == "0" ? parseInt(ymd.substring(6,7)) : parseInt(ymd.substring(5,7));
    var day = ymd.charAt(8) == "0" ? parseInt(ymd.substring(9,10)) : parseInt(ymd.substring(8,10));
    var begin = ymd.charAt(0) == "0" ? (ymd.charAt(1) == "0" ? (ymd.charAt(2) == "0" ? 3 : 2) : 1) : 0;
    var year = parseInt(ymd.substring(begin, 4));

    return new Date(year, month, day);
}

function convertToDatePickerParam(str)
{
    var ymd = convertToYMD(str);
    if (ymd == null)
        return null;
    var month = ymd.charAt(5) == "0" ? parseInt(ymd.substring(6,7)) : parseInt(ymd.substring(5,7));
    var day = ymd.charAt(8) == "0" ? parseInt(ymd.substring(9,10)) : parseInt(ymd.substring(8,10));
    var begin = ymd.charAt(0) == "0" ? (ymd.charAt(1) == "0" ? (ymd.charAt(2) == "0" ? 3 : 2) : 1) : 0;
    var year = parseInt(ymd.substring(begin, 4));
    month = month - 1;

    return year + "-" + month + "-" + day;
}

//*****************************************************************************************
// Add the number of days to the date, the input and returned date string is always in yyyy/mm/dd format.
// Date string str must be valid when checking with isDate().
// days can be positive or negative
//*****************************************************************************************
function addDays(ymd, days)
{
    if (ymd == null)
        return null;
    if (days == 0)
        return ymd;
/*
    extract month, day, year and validate separately
*/ 
    var month = ymd.charAt(5) == "0" ? parseInt(ymd.substring(6,7)) : parseInt(ymd.substring(5,7));
    var day = ymd.charAt(8) == "0" ? parseInt(ymd.substring(9,10)) : parseInt(ymd.substring(8,10));
    var begin = ymd.charAt(0) == "0" ? (ymd.charAt(1) == "0" ? (ymd.charAt(2) == "0" ? 3 : 2) : 1) : 0;
    var year = parseInt(ymd.substring(begin, 4));

    var ms = Date.UTC(year, month-1, day);
    ms = ms + (days+1) * 24 * 60 * 60 * 1000;
    var dateObj = new Date(ms);
    var sep = ymd.charAt(4);

    year = dateObj.getFullYear();
    month = dateObj.getMonth() + 1;
    day = dateObj.getDate();

    return year + sep + ((month > 9) ? month : "0"+month) + sep + ((day > 9) ? day : "0"+day);
}

//*****************************************************************************************
// Return current date in yyyy/mm/dd format
//*****************************************************************************************
function getCurDateYMD()
{
    var curDate = new Date();
    var sep = getDateSep();
    year = curDate.getFullYear();
    month = curDate.getMonth() + 1;
    day = curDate.getDate();

    return year + sep + ((month > 9) ? month : "0"+month) + sep + ((day > 9) ? day : "0"+day);
}
//===================================================================
//  Function Name: isHours
//  Description  : Determines whether a character string represents 
//  valid hours and minutes based on the HoursFormat in effect for this 
//  language/locale.
//===================================================================
function isHours(fieldValue, metaField)
{                   
    var result = true;
    var separator = HoursFormat.charAt(2);
               
    var negative = fieldValue.indexOf('-');
          
    var sIndex = fieldValue.indexOf(separator);       
    
    if(!isNumeric(fieldValue, separator))
        result = false;

    else if (!checkNumericRange(fieldValue, metaField.lowValue, metaField.lowInclusive, metaField.highValue, metaField.highInclusive))
    {
        if (metaField.lowValue == null)
        {
            var msg = metaField.highInclusive ? "NUMERIC_GT_HIGH" : "NUMERIC_GE_HIGH";
            messageAlert(msg, metaField.realName, metaField.highValue);
        }
        else if (metaField.highValue == null) 
        {
            var msg = metaField.lowInclusive ? "NUMERIC_LT_LOW" : "NUMERIC_LE_LOW";
            messageAlert(msg, metaField.realName, metaField.lowValue);
        } 
        else
        {
            var msg = metaField.lowInclusive ? (metaField.highInclusive ? "NUMERIC_RANGE_11" : "NUMERIC_RANGE_10") :
                                     (metaField.highInclusive ? "NUMERIC_RANGE_01" : "NUMERIC_RANGE_00");
            messageAlert(msg, metaField.realName, metaField.lowValue, metaField.highValue);
        }
        return false;
    }
    
    // Ensure minutes does not exceed 59    
    else if(sIndex != -1 && HoursFormat.length > 3 && (parseInt(fieldValue.substr(sIndex+1, 2)) > 59 || fieldValue.charAt(sIndex+1) > '5'))
        result = false;

    else if(sIndex != -1 && negative == 0 && (fieldValue.substr(0, sIndex)).length > (metaField.fieldIntLength-metaField.decimalPlaces+1))
        result = false;
        
    else if(sIndex != -1 && negative != 0 && (fieldValue.substr(0, sIndex)).length > (metaField.fieldIntLength-metaField.decimalPlaces))
        result = false;

    else if((fieldValue.substr(sIndex+1, fieldValue.length-sIndex)).length > metaField.decimalPlaces && sIndex != -1)
        result = false;
    
    else if(sIndex == -1 && fieldValue.length > (metaField.fieldIntLength-metaField.decimalPlaces))
        result = false;

    if(!result)
        messageAlert((HoursFormat.length > 3) ? "INVALID_HOURS_FORMAT" : "INVALID_HOURS_FORMAT_NUMERIC", metaField.realName, 
                                    metaField.fieldIntLength-metaField.decimalPlaces,separator, metaField.decimalPlaces);
    return result;
}

//===================================================================
//  Function Name: isDays
//  Description  : Determines whether a character string represents 
//  valid days and hours based on the DaysFormat in effect for this 
//  language/locale.
//===================================================================
function isDays(fieldValue, metaField)
{           
    var result = true;
    var separator = DaysFormat.charAt(2);
    var sIndex = fieldValue.indexOf(separator);      

    if(!isNumeric(fieldValue, separator))
        result = false;

    // Ensure hours does not exceed 23    
    else if(sIndex != -1 && DaysFormat.length > 3 && (parseInt(fieldValue.substr(sIndex+1, 2)) > 23 || fieldValue.charAt(sIndex+1) > '2'))
        result = false;
   
    else if(sIndex != -1 && (fieldValue.substr(0, sIndex)).length > (metaField.fieldIntLength-metaField.decimalPlaces+1))
        result = false;
        
    else if((fieldValue.substr(sIndex+1, fieldValue.length-sIndex)).length > metaField.decimalPlaces && sIndex != -1)
        result = false;
    
    else if(sIndex == -1 && fieldValue.length > (metaField.fieldIntLength-metaField.decimalPlaces))
        result = false;

    if(!result)
        messageAlert((DaysFormat.length > 3) ? "INVALID_DAYS_FORMAT" : "INVALID_HOURS_FORMAT_NUMERIC", metaField.realName, 
                                    metaField.fieldIntLength-metaField.decimalPlaces,separator, metaField.decimalPlaces);
    return result;
}

//===================================================================
//  Function Name: getDefaultTime
//  Description  : Determines the default maximum value for a time  
//  field, based on the HoursFormat in effect for this 
//  language/locale, and the size of the field.
//===================================================================
function getDefaultTime(field)
{                   
    var digits = field.fieldIntLength - field.decimalPlaces;
    var values = new Array();
    for(i = 0; i < digits; i++)
        values[i] = '9';
    var result = values.join('').concat(HoursFormat.charAt(2));
    return (HoursFormat.length > 3 ) ? result.concat("59") : result.concat("99");
}
//===================================================================
//  Function Name: isValidURLParameterList
//  Description  : Determines whether a character string represents 
//  a valid list of name=value pairs. Each pair is separated by &
//===================================================================
function isValidURLParameterList(fieldName, realName)
{
    if(fieldName.value == '')
        return true;
        
    var arrayOfStrings = fieldName.value.split('&');
    var asLen = arrayOfStrings.length;
    if(asLen < 1)
        return true;

    for (var i = 0 ; i < asLen; i++)
    {
        var nameValueEntry =  arrayOfStrings[i].split('=');
        if(nameValueEntry.length != 2 || nameValueEntry[0].length < 1)
        {
            messageAlert("INVALID_FORMAT_PARAMETER_VALUES",realName);
            fieldName.focus();
            return false;
        }
    }
    return true;
}

// Returns true if string contains only letters A-Z/a-z, digits or underscore(_) or dollar-sign ($).
function isValidJSIdentifierName(s)
{
    for (var i = 0, j = s.length; i < j; i++)
    {
        var c = s.charAt(i);
        if (!(isAsciiLetter(c) || isDigit(c) || c == '_' || c == '$'))
            return false;
    }
    return true;
}

//===================================================================
//          FormValidate
//===================================================================

/*************************************************************************************
 ** FormValidate.js - Validates and checks for required fields.  Only supports
 ** INPUT and SELECT form elements.  Supports Date per format associated with
 ** locale (DateFormat, TimeFormat, DateTimeFormat).
 **
 ** To use call the "Field" function once per form element you need to validate
 ** or make required.  Then pass the variables into an array.  And lastly call the
 ** validate(this) function from the onSubmit event of your form.
 *************************************************************************************/


/*************************************************************************************
 ** var formEltName = new Field(realname, formEltName, validationType, required, 
 **                             fieldLength, decimalPlaces, 
 **                             lowValue, lowInclusive, highValue, highInclusive
 **                             validationFunction, allowMultiple, maxValues)
 **
 ** Any of parameters starting from fieldLength may be undefined or omitted. Javascrip does 
 ** not require all parameters when function is invoked.
 **
 ** 1) realName is simply a meaningful description of the form element for use in
 **    reporting. For example, if the user forgets to fill in this field, the alert
 **    will say, "Please enter your last name."
 **
 ** 2) formEltName is very important. Note that its value is the same as the name of the
 **    corresponding element in the HTML form, and the same as the object name itself.
 **    These names must be identical.
 **
 ** 3) validationType is the form of validation you wish to apply.  Valid values are
 **    'date', 'time', 'numeric', 'alphanumeric', 'freeform', 'select', 'currency',
 **    'searchnumeric', 'searchalphanumeric' and 'alphanumericascii'.
 **
 ** 4) required is a boolean indicating if this is a required field
 **
 ** 5) fieldLength defines maximum length of the field. For 'numeric' type it defines maximum 
 **    number of digits.
 **
 ** 6) decimalPlaces defines number of digits after dot for numeric type. May be undefined.
 **
 ** 7) lowValue, highValue, lowInclusive, highInclusive defines range of values for numeric value. 
 **    When 'undefined' is passed as boundary value it is not checked for constraint.
 **    Boundaries may be inclusize or .
 **
 ** 8) validationFunction permits to define custom function.
 **    Validation function will be invoked as
 **        validationFunction(checkedValue, realName)
 **    This method must return true if validation was successful and false otherwise.
 **    If validation failed, then this method must call messageAlert function and
 **    error message must use realName - name of the invalid field in UI.
 **
 ** 9) allowMultiple if true, multiple values are allowed for this field separated by comma, i.e. "01/01/2001,01/02/2001"
 **
 ** 10) maxValues. The maximum number of values allowed in a comma delimited field (multiple values field)
 **     If allowMultiple is true, validation function restricts the maximum number of values 
 **     to be less than or equal to maxValues.
 **
 ** Example:
 **
 ** var txtDate = new Field('Due Date', 'txtDate', 'date', true);
 ** var txtNum  = new Field('Weight', 'txtNum', 'numeric', true, 11, 2, 0, false);
 **
 ** Second example defines required numeric field with 11 digits (2 after dot) and positive value.
 ** Positive value is defined as range from [0..+OO] and 0 is not included.
 *************************************************************************************/

/*************************************************************************************
 ** If complex validation is required, that involes more then one field,
 ** then validation function may be registered. On most of jsp pages this function 
 ** may be invoked explicitly as part of submit callback, but for sections registration
 ** must be used.
 **
 ** registerValidationFunction(foo);
 **
 ** During validation of the page validation function will be invoked as:
 ** foo(form);
 *************************************************************************************/

var DEBUG = false;
var DEVELOPMENT = false;
var possibleValidationTypes = new Array("freeform", "date", "time", "alphanumeric", "numeric", "currency",
                                        "select", "searchnumeric", "searchalphanumeric", "alphanumericascii");

// Checks if validationType is from the list of recognized types and return false if not
function checkType(validationType)
{
    for (var i = 0, p = possibleValidationTypes.length; i < p; i++)
    {
        if (possibleValidationTypes[i] == validationType)
        {
            return true;
        }
    }
    return false;
}

// Return meta object, that describes field of the form
function getFormFieldMeta(form, fieldName) {
    var formMetas = fields;
    var metaField = null;
    for (var i = 0, f = formMetas.length; i < f; i++)
    {
        if (formMetas[i].formEltName == fieldName)
        {
            metaField = formMetas[i];
            break;
        }
    }
    return metaField;
}

// Return meta object, that describes field of the grid
function getGridFieldMeta(form, fieldName) {
    var gridMetas = fieldsGrid;
    var metaField = null;
    for (var i = 0, g = gridMetas.length; i < g; i++)
    {
        if (gridMetas[i].formEltName == fieldName)
        {
            metaField = gridMetas[i];
            break;
        }
    }
    return metaField;
}

// Validate value of the field on the grid.
function validateGridField(form, fieldObj)
{
    return validateFieldAgainstMeta(form, fieldObj, getGridFieldMeta(form, fieldObj.name));
}

// Validate one field on the form
function validateFormField(form, fieldObj)
{
    return validateFieldAgainstMeta(form, fieldObj, getFormFieldMeta(form, fieldObj.name));
}

// Validate value of the field using meta description of the field.
function validateFieldAgainstMeta(form, fieldObj, metaField)
{
    var validationPassed = true;
    if (metaField != null)
    {
        if (metaField.maskType == null)
            validationPassed = validateField(fieldObj.value, metaField.realName, metaField.validationType,
                                             metaField.fieldLength, metaField.decimalPlaces, 
                                             metaField.lowValue, metaField.lowInclusive, 
                                             metaField.highValue, metaField.highInclusive, 
                                             metaField.validationFunction, metaField.allowMultiple,
                                             metaField.maxValues);
        else if (metaField.dependOnValue == null)
            validationPassed = validateMaskField(fieldObj.value, form, metaField);
        else
            validationPassed = validateMaskField(fieldObj.value, form, metaField);
    }
    if (!validationPassed)
    {
        fieldObj.select();
        return false;
    }
    return true;
}


// Validate value of the field on form or grid
function validateField(fieldValue, realName, validationType, fieldLength, decimalPlaces,
                       lowValue, lowInclusive, highValue, highInclusive, validationFunction,
                       allowMultiple, maxValues)
{
    if (DEBUG)
        alert("validateField fieldValue="+fieldValue+",realName="+realName+", validationType="+validationType+
              ", fieldLength="+fieldLength+", decimalPlaces="+decimalPlaces+
              ", lowValue="+lowValue+", lowInclusive="+lowInclusive+", highValue="+highValue+
              ", highInclusive="+highInclusive+
              ", validationFunction="+validationFunction+
              ", allowMultiple="+allowMultiple+", maxValues="+maxValues);

    if ((fieldLength != null) && (validationType != "numeric") && (validationType != "currency") && 
        (validationType != "searchnumeric") && (validationType != "select") && (!allowMultiple) &&
        (fieldValue.length > fieldLength))
    {
        messageAlert("MAXIMUM_LENGTH", realName, fieldLength);
        return false;
    }

    if (fieldValue != "")
    {
        if((allowMultiple == null) || (!allowMultiple))
        {
            if(!validateFieldType(fieldValue, realName, validationType, fieldLength, decimalPlaces,
                       lowValue, lowInclusive, highValue, highInclusive))
                return false;
        }
        else
        {
            fieldValue = trimBeginEnd(fieldValue);
            var wholeField = fieldValue;
            var separatorIndex;
            var fieldValueSplit;
            var validatedValues = new Array();

            if((maxValues != null) && (getNumberOfValues(fieldValue) > maxValues))
            {
                messageAlert("NUMBER_OF_VALUES_EXCEEDS_MAXIMUM", realName, maxValues);
                return false;
            }

            while((separatorIndex = wholeField.indexOf(MULTIPLE_VALUES_SEPARATOR)) >= 0)
            {
                fieldValueSplit = trimBeginEnd(wholeField.substring(0, separatorIndex));
                if(fieldValueSplit == "")
                {
                    messageAlert("MULTI_VALUES_EMPTY", fieldValueSplit, realName, MULTIPLE_VALUES_SEPARATOR);
                    return false;
                }
                if(!validateFieldType(fieldValueSplit, realName,
                        validationType, fieldLength, decimalPlaces,
                        lowValue, lowInclusive, highValue, highInclusive))
                    return false;

                for(var validatedIndex = 0, vvLen = validatedValues.length; validatedIndex < vvLen; validatedIndex++)
                    if(validatedValues[validatedIndex] == fieldValueSplit)
                    {
                        messageAlert("MULTI_VALUES_DUPLICATED", fieldValueSplit, realName);
                        return false;
                    }

                validatedValues[validatedValues.length] = fieldValueSplit;
                wholeField = wholeField.substring(separatorIndex + MULTIPLE_VALUES_SEPARATOR.length);
            }
            fieldValueSplit = wholeField;
            if((fieldValueSplit != fieldValue) && (fieldValueSplit == ""))
            {
                messageAlert("MULTI_VALUES_EMPTY", fieldValueSplit, realName, MULTIPLE_VALUES_SEPARATOR);
                return false;
            }
            if(!validateFieldType(fieldValueSplit, realName, validationType, fieldLength, decimalPlaces,
                    lowValue, lowInclusive, highValue, highInclusive))
                return false;

            for(var validatedIndex = 0, vvLen = validatedValues.length; validatedIndex < vvLen; validatedIndex++)
                if(validatedValues[validatedIndex] == fieldValueSplit)
                {
                    messageAlert("MULTI_VALUES_DUPLICATED", fieldValueSplit, realName);
                    return false;
                }
        }
    }

    if (validationFunction != null)
        return validationFunction(fieldValue, realName);
        
    return true;
}

function validateFieldType(fieldValue, realName, validationType, fieldLength, decimalPlaces,
                       lowValue, lowInclusive, highValue, highInclusive)
{
    var result = true;
    switch (validationType)
    {
        case "freeform":
            break;

        case "date":
            if (!isDate(fieldValue))
            {
                messageAlert("INVALID_DATE_FORMAT", fieldValue, realName,DisplayDateFormat);
                result = false;
            }
            break;

        case "time":
            if (!isTime(fieldValue))
            {
                messageAlert("INVALID_TIME_FORMAT", fieldValue, realName,DisplayTimeFormat);
                result = false;
            }
            break;

        case "alphanumeric":
            if (!isAlphanumeric(fieldValue))
            {
                messageAlert("ALPHANUMERIC", realName);
                result = false;
            }
            break;
        case "alphanumericascii":
            if (!isAlphanumericAscii(fieldValue))
            {
                messageAlert("ALPHANUMERICASCII", realName);
                result = false;
            }
            break;

        case "numeric":
        case "currency":
            var dsep = (validationType == "numeric") ? DefaultDecimalSeparator : MonetaryDecimalSeparator;
            if (!isNumeric(fieldValue, dsep))
            {
                messageAlert("NUMERIC", realName);
                result = false;
            } 
            else if (!checkNumericPoint(fieldValue, fieldLength, decimalPlaces, dsep))
            {
                if (decimalPlaces == null) {
                    messageAlert("NUMERIC_LENGTH", realName, fieldLength);
                } else {
                    messageAlert("FIXED_POINT", realName, fieldLength-decimalPlaces, decimalPlaces, dsep);
                }
                result = false;
            }
            else if (!checkNumericRange(fieldValue, lowValue, lowInclusive, highValue, highInclusive))
            {
                if (lowValue == null) {
                    var msg = highInclusive ? "NUMERIC_GT_HIGH" : "NUMERIC_GE_HIGH";
                    messageAlert(msg, realName, highValue);
                } else if (highValue == null) {
                    var msg = lowInclusive ? "NUMERIC_LT_LOW" : "NUMERIC_LE_LOW";
                    messageAlert(msg, realName, lowValue);
                } else {
                    var msg = lowInclusive ? 
                        (highInclusive ? "NUMERIC_RANGE_11" : "NUMERIC_RANGE_10") :
                        (highInclusive ? "NUMERIC_RANGE_01" : "NUMERIC_RANGE_00");
                    messageAlert(msg, realName, lowValue, highValue);
                }
                result = false;
            }
            break;

        case "searchnumeric":
            if (!isSearch(fieldValue, isDigit))
            {
                messageAlert("NUMERIC", realName);
                result = false;
            }
            break;

        case "searchalphanumeric":
            if (!isSearch(fieldValue, isAlphanumericChar))
            {
                messageAlert("ALPHANUMERIC", realName);
                result = false;
            }
            break;

        case "select":
            break;
    }
    return result;
}

function validateMaskField(fieldValue, form, metaField, rowIdx)
{
    if (DEBUG)
    {
        alert("validateField fieldValue="+fieldValue+",realName="+metaField.realName+", maskType="+metaField.maskType+
              ", dependOnValue="+metaField.dependOnValue+",isSearchable="+metaField.isSearchable+
              ", fieldIntLength="+metaField.fieldIntLength+", lowValue="+metaField.lowValue+", lowInclusive="+metaField.lowInclusive+
              ", highValue="+metaField.highValue+", highInclusive="+metaField.highInclusive+", rowIdx="+rowIdx);
    }
    var fieldPassed = true;

    if (fieldMaskTypes[metaField.maskType] == 'postalcode' &&
            metaField.dependOnField != null)
    {
        var dpndOnFld = null;
        if (rowIdx == undefined)
            dpndOnFld = getCombobox(form, metaField.dependOnField);
        else
            dpndOnFld = getColumnObject(form, metaField.dependOnField, rowIdx);

        for(var i = 0, fpcSize = fieldPostalCodeRequired.length; i < fpcSize; i++) 
        {
            if(fieldPostalCodeRequired[i][0] == dpndOnFld.value) 
            {
                if(!fieldPostalCodeRequired[i][1])
                    return true;
                else 
                    break;
            }
        }

        if (dpndOnFld != null && dpndOnFld.tmfocus)
        {
            if (dpndOnFld.getSelectedOptions(false).length > 1)
                return fieldPassed;
        }
    }

    if (fieldValue != "")
    {
        var dependOnValue = metaField.dependOnValue;
        if (dependOnValue == null && metaField.dependOnField != undefined)
        {
            if (rowIdx == undefined)
                dependOnValue = eval("form." + metaField.dependOnField).value;
            else
            {
                var found = false;
                var dpndOnFld = null;
                for (var i = 0, fgLen = fieldsGrid.length; i < fgLen; i++)
                {
                    if (fieldsGrid[i].formEltName == metaField.dependOnField)
                    {
                        if (fieldsGrid[i].validationType == 'select')
                        {
                            dpndOnFld = getCombobox(form, metaField.dependOnField, rowIdx);
                            dependOnValue = dpndOnFld.options[dpndOnFld.selectedIndex].value;
                            found = true;
                        }
                        else
                        {
                            dpndOnFld = getColumnObject(form, metaField.dependOnField, rowIdx);
                            dependOnValue = dpndOnFld.value;
                            found = true;
                        }
                    }
                }
                if (!found)
                {
                    var colobjs = utp.getColumnObjects(metaField.dependOnField);
                    if (colobjs.length > 0)
                        dependOnValue = colobjs[rowIdx].value;
                    else
                        dependOnValue = eval("form." + metaField.dependOnField).value;
                }
            }
        }
        
        if (metaField.isSearchable)
        {
            if (!isSearch(fieldValue, isAlphanumericChar, false))
            {
                messageAlert("ALPHANUMERIC", metaField.realName);
                return false;
            }
            for (var i = 0, scLen = searchCharacters.length; i < scLen; i++)
                if (fieldValue.indexOf(searchCharacters[i]) >= 0)
                    return true;
        }

        var masks = getMask(metaField.maskType, dependOnValue);
        
        if (masks != null)
        {
            if (!validateMasks(fieldValue, masks, metaField.maskType))
            {
                if (fieldMaskTypes[metaField.maskType] == 'currency')
                    messageAlert("INVALID_CURRENCY_FORMAT", fieldValue, metaField.realName, masks);
                else
                {
                    var formattedMasks = masks[0];
                    for (var i = 1, mkLen = masks.length; i < mkLen; i++)
                        formattedMasks = formattedMasks + ", " + masks[i];
                    
                    if (fieldMaskTypes[metaField.maskType] == 'postalcode')
                    {
                        var formattedMasks2 = "";
                        for (var i = 0, fmLen = formattedMasks.length; i < fmLen; i++)
                        {
                            if (formattedMasks.charAt(i) == ' ' && formattedMasks.charAt(i-1) != ',')
                                formattedMasks2 += '_';
                            else
                                formattedMasks2 += formattedMasks.charAt(i);
                        }
                        messageAlert("INVALID_POSTAL_MASK_FORMAT", fieldValue, metaField.realName, formattedMasks2);
                    }
                    else
                        messageAlert("INVALID_MASK_FORMAT", fieldValue, metaField.realName, formattedMasks);
                }
                fieldPassed = false;
            }
            else if (fieldMaskTypes[metaField.maskType] == 'currency')
            {
                var nbrDecPlc = getDecimalPlaces(metaField, form);
                var fieldLen = metaField.fieldIntLength;
                if (fieldLen != null)
                    fieldLen += nbrDecPlc;
                fieldPassed = validateFieldType(fieldValue, metaField.realName, 'currency', fieldLen, 
                                nbrDecPlc, metaField.lowValue, metaField.lowInclusive, metaField.highValue, 
                                metaField.highInclusive);
            }
            else if (metaField.maskType == '4' || metaField.maskType == '5')
            {
                fieldPassed = metaField.maskType == '4' ? isHours(fieldValue, metaField) : isDays(fieldValue, metaField);
            }
            else if (fieldMaskTypes[metaField.maskType] == 'postalcode')
            {
                if (dependOnValue == "CAN")
                {
                    var stateFieldName = "";
                    var pstlidx = toUpperCase(metaField.formEltName).indexOf("POSTAL");
                    if (pstlidx == 0)
                    {
                        if (rowIdx == undefined)
                            stateFieldName = "state";
                        else
                            stateFieldName = "State";
                    }
                    else
                    {
                        var prefix = metaField.formEltName.substring(0, pstlidx);
                        if (toUpperCase(prefix).indexOf("FROM") > -1 ||
                            toUpperCase(prefix).indexOf("TO") > -1)
                        {
                            if (rowIdx == undefined)
                                stateFieldName = "state";
                            else
                                stateFieldName = "State";
                        }
                        else
                            stateFieldName = prefix + "State";
                    }
                    var stateValue = "";
                    if (rowIdx == undefined)
                        stateValue = eval("form." + stateFieldName).value;
                    else
                    {
                        var statobj = getCombobox(form, stateFieldName, rowIdx);
                        stateValue = statobj.options[statobj.selectedIndex].value;
                    }
                    if (stateValue != null && stateValue.length > 0)
                    {
                        var fldFirstChar = fieldValue.charAt(0);
                        var rules = getCanadianPostalRule();
                        for (var i = 0, rLen = rules.length; i < rLen; i++)
                        {
                            var rulesByState = rules[i];
                            if (rulesByState[0] == stateValue)
                            {
                                var rulesValues = rulesByState[1];
                                var j = 0, rvLen = rulesValues.length;
                                for (j = 0; j < rvLen; j++)
                                    if (rulesValues[j] == fldFirstChar)
                                        break;

                                if (j == rvLen)
                                {
                                    messageAlert("INVALID_POSTAL_CODE_START_CHAR", rulesValues.toString(), stateValue);
                                    fieldPassed = false;
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    return fieldPassed;
}

function printFields(form)
{
    var text = "";
    for (var i = 0, fLen = fields.length; i < fLen; i++)
    {
        var filed = fields[i];
        var formObj = eval("form." + filed.formEltName);
        text = text + filed.formEltName+"["+formObj.tabIndex+"] ";
    }
    alert(text);
}

// Register new validation function
function registerValidationFunction(func)
{
    if (DEBUG)
    {
        alert("Register validation function "+func);
    }
    if (window.validateFunctions == null)
    {
        window.validateFunctions = new Array(0);
    }
    window.validateFunctions[window.validateFunctions.length] = func;
}

// Invoked validation functions if any defined on the page
function invokeValidateFunctions(form)
{
    if (window.validateFunctions != null)
    {
        for (var i = 0, vfLen = window.validateFunctions.length; i < vfLen; i++)
        {
            var validateFunction = window.validateFunctions[i];
            if (DEBUG)
            {
                alert("Invoke validation function "+validateFunction);
            }
            if (!validateFunction(form))
            {
                return false;
            }
        }
    }
    return true;
}

// Validate all formFields on the form
function validate(form, formFields)
{
    if(formFields == null)
        formFields = fields;

    var formPassed = true;

    if (DEBUG)
    {
        printFields(form);
    }

    formFields.sort(function(a,b){
        var formObjA = eval("form." + a.formEltName);
        var formObjB = eval("form." + b.formEltName);
        if (formObjA == null) {
            messageAlert("FAILED_TO_EVAL", a.formEltName);
            return -1;
        }
        if (formObjB == null) {
            messageAlert("FAILED_TO_EVAL", b.formEltName);
            return 1;
        }
        if (DEVELOPMENT && formObjB.tabIndex == formObjA.tabIndex
            && formObjB.type != 'hidden' && formObjA.type != 'hidden') {
              alert("Attribute 'tabindex' of '"+a.formEltName+"' and '"+b.formEltName+"' "+
                  "is the same and equal to "+formObjA.tabIndex);
        }
        return formObjA.tabIndex - formObjB.tabIndex;
    });

    for (var i = 0, ffLen = formFields.length; i < ffLen; i++)
    {
        formEltName = formFields[i].formEltName;
        formObj = eval("form." + formEltName);
        if (formObj == null && formFields[i].dependOnValue == null)
        {
            messageAlert("FAILED_TO_EVAL", formEltName);
            return false;
        }

        if (formFields[i].maskType == null)
            formPassed = validateField(formObj.value, formFields[i].realName, formFields[i].validationType,
                                       formFields[i].fieldLength, formFields[i].decimalPlaces, 
                                       formFields[i].lowValue, formFields[i].lowInclusive, 
                                       formFields[i].highValue, formFields[i].highInclusive, 
                                       formFields[i].validationFunction, formFields[i].allowMultiple,
                                       formFields[i].maxValues);
        else if (formFields[i].dependOnValue == null)
            formPassed = validateMaskField(formObj.value, form, formFields[i]);
        else
            formPassed = validateMaskField(formObj.value, form, formFields[i]);

        if (formPassed) {
            if (!checkFieldRequired(form, formObj, formFields[i].validationType, formFields[i].required))
            {
                messageAlert("REQUIRED_FIELD", formFields[i].realName);
                if (formFields[i].validationType == 'select')
                    comboboxToFocus(getCombobox(form, formObj.name));
                else if (formObj.focus)
                    formObj.focus();
                return false;
            }
        }

        if (DEBUG)
        {
            alert('formPassed='+formPassed);
        }
        if (!formPassed)
        {
            formObj.select();
            return false;
        }
    }
    return invokeValidateFunctions(form);
}

// Validate all fields of the grid
function validateGrid(form, removeUntouchNewRow, keepOneRow)
{
    var metaFields = fieldsGrid;
    if(!isEmptyListAllowed && ((getNumberOfRows() - getNumberOfDeletedRows()) == 0))
    {
        messageAlert("EMPTY_TABLE");
        return false;
    }
    // Remove new rows that haven't been changed by user.
    // Resize table if row(s) have been removed.

    if(keepOneRow == undefined)
      keepOneRow = false;

    if (removeUntouchNewRow == undefined)
        removeUntouchNewRow = true;

    if (removeUntouchNewRow && removeUntouchedNewRows(keepOneRow))
        resizeTables();

    var nbrOfSkippedFields = 0;
    var formPassed = true;
    for (var i = 0, mfLen = metaFields.length; i < mfLen; i++)
    {
        var metaField = metaFields[i];
        var formEltName = metaField.formEltName;
        var formObjects = eval("form." + formEltName);
        if (formObjects == null)
        {   // When a column has no associated input capable row, continue to next column.
            nbrOfSkippedFields++;
            continue;
        }

        var evaluateColumn = true;
        var multiple = (formObjects.length != null);
        var objLength = (multiple) ? formObjects.length : 0;
        var formObj;

        for (var j = 0; evaluateColumn; j++)
        {
            if (multiple)
            {
                formObj = formObjects[j];
                if (formObj == null)
                {
                    messageAlert("FAILED_TO_EVAL", formEltName);
                    return false;
                }
                evaluateColumn = j < (objLength - 1);
            }
            else
            {
                formObj = formObjects;
                evaluateColumn = false;
            }

            var fieldValidate = true;
            if (metaField.maskType == null)
                fieldValidate = validateField(formObj.value, metaField.realName, metaField.validationType, 
                                                  metaField.fieldLength, metaField.decimalPlaces,
                                                  metaField.lowValue, metaField.lowInclusive, 
                                                  metaField.highValue, metaField.highInclusive, 
                                                  metaField.validationFunction);
            else if (metaField.dependOnValue == null)
                fieldValidate = validateMaskField(formObj.value, form, metaField, j);
            else
                fieldValidate = validateMaskField(formObj.value, form, metaField, j);

            if (!fieldValidate)
            {
                formObj.select();
                return false;
            }

        } // j for

    } // i for

    if (formPassed && nbrOfSkippedFields != metaFields.length)
    {
        formPassed = checkGridRequired(form);
    }

    if (formPassed)
    {
        formPassed = invokeValidateFunctions(form);
    }

    if (formPassed)
    {
        formPassed = validateDuplicates(form);
    }

    return formPassed;

}

function validateMasks(fieldValue, masks, maskType)
{
    var failed = false;
    var mkLen = masks.length;
    var i;
    
    if (fieldMaskTypes[maskType] == 'currency')
    {
        for(i = 0; i < mkLen; i++)
        {
            var minusSignInFront = "";      // Minus sign is in the front
            var intgr = "";                 // Integer portion of amount
            var decsep = "";                // decimal separator "." or ","
            var processFraction = false;    // process fraction portion
            var fraction = "";              // Fraction protion of amount
            var minusSignAtBack = "";       // Minus sign is at the back
            var digitCount = 0;             // Count number of digits by portion in the mask
            
            var maskValue = masks;
            for (var j = (maskValue.length - 1); !failed && (j > -1); j--)
            {
                var symbol = maskValue.charAt(j);
                switch(symbol)
                {
                    case '-':
                        if (intgr.length == 0 && fraction.length == 0)
                            minusSignAtBack = "-?";  
                        else
                            minusSignInFront = "-?";
                        break;
                    case '.':
                        decsep = "\\.?";
                        processFraction = true;
                        break;
                    case ',':
                        decsep = ",?";
                        processFraction = true;
                        break;
                    case '0':
                        digitCount++;
                        break;
                    case '#':
                        digitCount++;
                        break;
                    default:
                        failed = true;
                        break;
                }
                if (!failed)
                {
                    // Decimal separator has been found.
                    if (processFraction)
                    {
                        if (digitCount > 0)
                        {
                            fraction = "\\d{0," + digitCount + "}";
                            digitCount = 0;
                        }
                        processFraction = false;
                    }
                    else if (j == 0)
                    {
                        intgr = "\\d{0," + digitCount + "}";
                    }
                }
            }
            if (!failed)
            {
                if (minusSignInFront.length == 0 && minusSignAtBack.length == 0)
                    minusSignInFront = "-?";
                var regexp = new RegExp('^' + minusSignInFront + intgr + decsep + fraction + minusSignAtBack + '$');
                if (regexp.test(fieldValue))
                    break;
            }
        }
    }
    else if(maskType == '4' || maskType == '5')
    {
        return true;
    }
    else  // Non currency mask type
    {
        for(i = 0; i < mkLen; i++)
        {
            if(masks[i].length == fieldValue.length)
            {
                failed = false;
                for(var j = 0; !failed && (j < masks[i].length) ; j++)
                {
                    var symbol = masks[i].charAt(j);
                    switch(symbol)
                    {
                        case '*':
                            failed = (!isLetter(fieldValue.charAt(j)) && !isDigit(fieldValue.charAt(j)));
                            break;
                        case '#':
                            failed = !isDigit(fieldValue.charAt(j));
                            break;
                        case '$':
                            failed = !isLetter(fieldValue.charAt(j));
                            break;
                        case ' ':
                        case '-':
                        case '(':
                        case ')':
                            failed = (fieldValue.charAt(j) != symbol);
                            break;
                        default:
                            failed = true;
                            break;
                    }
                }
                if(!failed)
                    break;
            }
        }
    }
    return (!failed && (i < mkLen));
}

//Field object definition
function Field(realName, formEltName, validationType, required, fieldLength, decimalPlaces, 
               lowValue, lowInclusive, highValue, highInclusive, validationFunction, allowMultiple, maxValues)
{
    if (DEBUG)
    {
        alert("Field realName="+realName+", formEltName="+formEltName+", validationType="+validationType+
              ", required="+required+", fieldLength="+fieldLength+", decimalPlaces="+decimalPlaces+
              ", lowValue="+lowValue+", lowInclusive="+lowInclusive+", highValue="+highValue+
              ", highInclusive="+highInclusive+
              ", validationFunction="+validationFunction+
              ", allowMultiple="+allowMultiple+", maxValues="+maxValues);
    }
    if (DEVELOPMENT && !checkType(validationType))
    {
        alert("Unknown validation type "+validationType+" for field with realName="+realName+", formEltName="+formEltName);
    }
    this.realName = realName;
    this.formEltName = formEltName;
    this.validationType = validationType;
    this.required = required;
    this.fieldLength = fieldLength;
    this.decimalPlaces = decimalPlaces;
    this.lowValue = lowValue;
    this.lowInclusive = lowInclusive;
    this.highValue = highValue;
    this.highInclusive = highInclusive;
    this.validationFunction = validationFunction;
    this.allowMultiple = allowMultiple;
    this.maxValues = maxValues;
}

//Field object definition
// fieldIntLength = Max length of the Integer part of the value (i.e. the max length on the left side of the decimal point)
function MaskField(realName, formEltName, maskType, required, dependOnValue, dependOnField, isSearchable,
                    fieldIntLength, lowValue, lowInclusive, highValue, highInclusive)
{
    if (DEBUG)
    {
        alert("Field realName="+realName+", formEltName="+formEltName+", maskType="+maskType+
              ", required="+required+", dependOnValue="+dependOnValue+", dependOnField="+dependOnField+
              ", isSearchable="+isSearchable+", fieldIntLength="+fieldIntLength+", lowValue="+lowValue+
              ", lowInclusive="+lowInclusive+", highValue="+highValue+", highInclusive="+highInclusive);
    }
    this.realName = realName;
    this.formEltName = formEltName;
    this.maskType = maskType;
    this.required = required;
    this.dependOnValue = dependOnValue;
    this.dependOnField = dependOnField;
    if(isSearchable == null)
        this.isSearchable = false;
    else
        this.isSearchable = isSearchable;
    this.fieldIntLength = fieldIntLength;
    this.lowValue = lowValue;
    this.lowInclusive = lowInclusive;
    this.highValue = highValue;
    this.highInclusive = highInclusive;
    this.validationType = fieldMaskTypes[maskType];
}

//Field object definition
// fieldIntLength = Max length of the Integer part of the value (i.e. the max length on the left side of the decimal point)
// decimalPlaces = Max length of the Decimal part of the value (i.e. the max length on the right side of the decimal point)
function MaskTimeField(realName, formEltName, maskType, required, fieldIntLength, decimalPlaces, 
                                    lowValue, lowInclusive, highValue, highInclusive)
{
    if (DEBUG)
    {
        alert("Field realName="+realName+", formEltName="+formEltName+", maskType="+maskType+
              ", required="+required+", fieldDecLength="+fieldDecLength+
              +", fieldIntLength="+fieldIntLength+", lowValue="+lowValue+
              ", lowInclusive="+lowInclusive+", highValue="+highValue+", highInclusive="+highInclusive);
    }
    this.realName = realName;
    this.formEltName = formEltName;
    this.decimalPlaces = decimalPlaces;
    this.maskType = maskType;
    this.required = required;
    this.fieldIntLength = fieldIntLength;
    this.lowValue = lowValue;
    this.lowInclusive = lowInclusive;
    this.highValue = highValue;
    this.highInclusive = highInclusive;
    this.validationType = 'numeric';
}

function checkFieldRequired(form, fieldObj, validationType, required, rowIndex)
{
    var fieldPassed = true;
    if (required)
    {
        switch (validationType)
        {
            case "select":
                if (rowIndex == undefined)
                {
                    if (getCombobox(form, fieldObj.name).selectedIndex == 0)
                        fieldPassed = false;
                }
                else
                {
                    if (getCombobox(form, fieldObj.name, rowIndex).selectedIndex == 0)
                        fieldPassed = false;
                }
                break;

            default:
                if (fieldObj.value == "")
                {
                    fieldPassed = false;
                    break;
                }
        }
    }
    return fieldPassed;
}


function checkRequired(form)
{
    var formPassed = true;

    for (var i = 0, fLen = fields.length; i < fLen; i++) {
        formEltName = fields[i].formEltName;
        formObj = eval("form." + formEltName);

        formPassed = checkFieldRequired(form, formObj, fields[i].validationType, fields[i].required);

        if (!formPassed)
            break;
    }

    if (!formPassed)
    {
        messageAlert("REQUIRED_FIELD", fields[i].realName);
        if (formObj.focus)
            formObj.focus();
    }

    return formPassed;
}

function checkGridRequired(form)
{
    var metaFields = fieldsGrid;
    for (var i = 0, mfLen = metaFields.length; i < mfLen; i++)
    {
        var metaField = metaFields[i];
        var formEltName = metaField.formEltName;
        var formObjects = eval("form." + formEltName);
        if (formObjects == null)
        {   // When a column has no associated input capable row, continue to next column.
            continue;
        }
        if(metaField.required) {
            // Get the cells for the column and rows
            var columns = getColumnObjects(formEltName);
            // Check each cell value at (i, j)
            for(var j = 0, jN = columns.length; j < jN; j++) {                
                if(!validateGridFieldRequired(metaField, columns[j])) {
                    messageAlert("REQUIRED_FIELD", metaField.realName);
                    if (columns[j].focus)
                        columns[j].focus();
                    return false;
                }
            }
        }
    }
    return true;
}

 //===========================================================
//  Determines if the 'required' cell value has been entered
//============================================================

function validateGridFieldRequired(metaField, cell) {
    return (cell.value != "");
}

function translateMessage (msg, param1, param2, param3, param4, param5)
{
    var params = new Array (param1, param2, param3, param4, param5);
    var index;
    while ((index = msg.indexOf('^')) >= 0)
    {
        var n = msg.charAt(index + 1);
        var param = params[n - 1];
        msg = msg.substring(0, index) + param + msg.substring(index + 2);
    }
    return msg;
}

//===================================================================
//          StringUtils
//===================================================================

// Returns true if string s reprezents numeric (with specified separator)
function isNumeric(s, dsep)
{
    if (DEBUG)
    {
        alert("isNumeric "+s);
    }
    if (dsep == null) 
    {
       dsep=".";
    }
    var pattern1 = RegExp("^-?\\d+\\"+dsep+"?\\d*$");  // numeric
    var pattern2 = RegExp("^-?\\"+dsep+"\\d+$");       // case when leading digit before dot is omitted
    return pattern1.test(s) || pattern2.test(s);
}

// Returns true if numeric s has specified total number of digits and digits after point
function checkNumericPoint(s, totalDigits, decimalPlaces, dsep)
{
    if (DEBUG)
    {
        alert("checkNumericPoint "+s+","+totalDigits+","+decimalPlaces);
    }
    if (s.length > 0 && (totalDigits != null))
    {
        if (decimalPlaces == null || decimalPlaces == 0)
        {
            var pattern = RegExp("^-?\\d{1,"+totalDigits+"}$");;
            return pattern.test(s);
        }
        else
        {
            var pattern = RegExp("^-?\\d{0,"+(totalDigits-decimalPlaces)+"}(\\"+dsep+"\\d{0,"+decimalPlaces+"})?$");
            return pattern.test(s);
        }
    }
    return true;
}

// Return decimal separator, corresponding to the meta
function getDecimalSeparator(metaField, form)
{
    var decimalSeparator = DefaultDecimalSeparator;
    if (metaField != null && metaField.validationType == 'currency') {
        var mask;
        if (metaField.dependOnValue != null)
            mask = getMask(metaField.maskType, metaField.dependOnValue);
        else
            mask = getMask(metaField.maskType, eval("form." + metaField.dependOnField).value);
        
        var sepFound = false;
        var firstDigitFound = false;
        for (var i = mask.length-1; i >= 0; i--)
        {
            var symbol = mask.charAt(i);
            switch(symbol)
            {
                case '-':
                    break;
                case '0':
                case '#':
                    firstDigitFound = true;
                    break;
                default:
                    if (firstDigitFound)
                    {
                        decimalSeparator = symbol;
                        sepFound = true;
                    }
            }
            if (sepFound)
                break;
        }
    }
    return decimalSeparator;
}

// Return decimal places, corresponding to the meta
function getDecimalPlaces(metaField, form)
{
    if (metaField == null)
        return 0;
    if ((metaField.validationType != undefined && metaField.validationType == 'currency') ||
        (metaField.maskType != undefined && fieldMaskTypes[metaField.maskType] == 'currency'))
    {
        var mask;
        if (metaField.dependOnValue != null)
            mask = getMask(metaField.maskType, metaField.dependOnValue);
        else
            mask = getMask(metaField.maskType, eval("form." + metaField.dependOnField).value);

        var decSep = getDecimalSeparator(metaField, form);
        var decSepIndex = mask.lastIndexOf(decSep);
        if (decSepIndex == -1)
            return 0;

        var lastDigitIndex = -1;
        for (var i = mask.length-1; i >= 0; i--)
        {
            var symbol = mask.charAt(i);
            if (symbol == '0' || symbol == '#')
            {
                lastDigitIndex = i;
                break;
            }
        }
        return (lastDigitIndex - decSepIndex);
    }
    else
        return (metaField.decimalPlaces != null) ? metaField.decimalPlaces : 0;
}

// Converts float value into String, according to the meta
// 'decPlcs' is mandatory and is the decimal places assigned within a JSP
// if 'decPlcs' >= 0, it will be used as the number of decimal places.
// if 'decPlcs' equals -1, then 'metaField' and 'form' must not be null.
function floatToString(fValue, decPlcs, metaField, form) {

    var decimalPlaces = (decPlcs > -1) ? decPlcs : getDecimalPlaces(metaField, form);

    var nnn = new Number(fValue);
    var s = nnn.toFixed(decimalPlaces);

    s = s.replace('.', getDecimalSeparator(metaField, form));
    return s;
}

// Converts numeric value from string representation to int
function parseIntNumeric(s) {
    if (s == '' || s == null) {
        return 0;
    } else {
        s = s.replace(DefaultDecimalSeparator, '.');
        return parseInt(s);
    }
}

// Converts numeric value from string representation to float
function parseFloatNumeric(s) {
    if (s == '' || s == null) {
        return 0.0;
    } else {
        s = s.replace(DefaultDecimalSeparator, '.');
        return parseFloat(s);
    }
}

// Converts currency value from string representation to float
function parseFloatCurrency(s, metaField, form) {
    if (metaField == null) {
        if (s == '' || s == null) {
            return 0.0;
        } else {
            s = s.replace(MonetaryDecimalSeparator, '.');
            return parseFloat(s);
        }
    }
    else {
        var decSep = getDecimalSeparator(metaField, form);
        var mask;
        if (metaField.dependOnValue != null)
            mask = getMask(metaField.maskType, metaField.dependOnValue);
        else
            mask = getMask(metaField.maskType, eval("form." + metaField.dependOnField).value);

        var isNegative = (s.indexOf("-") != -1);
        var svalue = '';
        for (var j = 0, sLen = s.length; j < sLen; j++)
        {
            var symbol = s.charAt(j);
            switch(symbol)
            {
                case '-':
                case decSep:
                    svalue += symbol;
                    break;
                default:
                    if (isDigit(symbol))
                        svalue += symbol;
            }
        }
        svalue = svalue.replace(decSep, '.');
        var result = parseFloat(svalue);
        if (isNegative && result > 0)
            result = result * -1;
        return result;
    }
}

// Returns true if number is in specified range.
function checkNumericRange(s, lowValue, lowInclusive, highValue, highInclusive, dsep)
{
    if (DEBUG)
    {
        alert("checkNumericRange "+s+","+lowValue+","+lowInclusive+","+highValue+","+highInclusive);
    }
    s = s.replace(dsep,'.');
    if (lowValue  != null && ((lowInclusive && s < lowValue) || (!lowInclusive && s <= lowValue)))
        return false;
    if (highValue != null && ((highInclusive && s > highValue) || (!highInclusive && s >= highValue)))
        return false;
    return true;
}

function checkNumeric(fieldValue, fieldLength, decimalPlaces, lowValue, lowInclusive, highValue, highInclusive)
{
   var dsep = DefaultDecimalSeparator;
   return isNumeric(fieldValue, dsep) && 
          checkNumericPoint(fieldValue, fieldLength, decimalPlaces, dsep) &&
          checkNumericRange(fieldValue, lowValue, lowInclusive, highValue, highInclusive);
}

function compareNumeric(valueFrom, valueTo)
{
    var result = 0;

    if(parseFloatNumeric(valueFrom) < parseFloatNumeric(valueTo))
        result = -1;
    else if(parseFloatNumeric(valueFrom) == parseFloatNumeric(valueTo))
        result =  0;
    else if(parseFloatNumeric(valueFrom) > parseFloatNumeric(valueTo))
        result =  1;

    return result;
}

// Returns true if string s contains letters(from locale properties file),
// digits, space or the following symbols: ' # $ & * ( ) _ + - = { } [ ] \ : ; . ?
function isAlphanumeric(s)
{
    var count = 0;
    for (var i = 0, sLen = s.length; i < sLen; i++)
    {
        var c = s.charAt(i);
        if(!isAlphanumericChar(c))
            return false;
        if(c == " " || c == "\t")
            count++;
    }
    return (count != s.length);
}

// Returns true if string s contains only letters A-Z/a-z or digits.
function isAlphanumericAscii(s)
{
    for (var i = 0, sLen = s.length; i < sLen; i++)
    {
        var c = s.charAt(i);
        if(!(isAsciiLetter(c) || isDigit(c)))
            return false;
    }
    return true;
}

// Returns true if symbol 'c' is a letter, digit, space or
// one of the following symbols: ' # $ & * ( ) _ + - = { } [ ] \ : ; . ?
function isAlphanumericChar(c) {
    return isLetter(c) || isDigit(c) || c == " " || 
        c == "'" || c == "#" || c == "$" || c == "&" || c == "*" ||
        c == "(" || c == ")" || c == "_" || c == "+" || c == "-" ||
        c == "=" || c == "{" || c == "}" || c == "[" || c == "]" ||
        c == "\\" || c == ":" || c == ";" || c == "." || c == "?";
}

function isSearchChar(c) {
    for (var i = 0, scLen = searchCharacters.length; i < scLen; i++)
        if(searchCharacters[i] == c)
            return true;
    return false;
}

function isSearch(s, charValidationFunction, isDuplicateAllowed) {
    var searchItems = new Array();
    var temp = s;
    var index;
    var nonSearchCharFound;
    while ((index = temp.indexOf(MULTIPLE_VALUES_SEPARATOR)) > 0) {
        searchItems[searchItems.length] = temp.substring(0, index);
        temp = temp.substring(index + 1);
    }
    if(index == 0)
        return false;
    searchItems[searchItems.length] = temp;
    for(var i = 0, siLen = searchItems.length; i < siLen; i++) {
        nonSearchCharFound = false;
        for (var j = 0, j2 = searchItems[i].length; j < j2; j++) {
            var c = searchItems[i].charAt(j);
            if(!isSearchChar(c)) {
                if (!charValidationFunction(c))
                    return false;
                nonSearchCharFound = true;
            }
            else if((c == searchCharacters[2]) && (j != 0 || i != 0) )
                return false;
        }
        if(!nonSearchCharFound)
            return false;
        if(isDuplicateAllowed != undefined && !isDuplicateAllowed)
            for(var j = i + 1, k = searchItems.length; j < k; j++)
                if(searchItems[i] == searchItems[j])
                    return false;
    }
    return true;
}

// Returns true if character c is a digit (0 .. 9).
function isDigit(c)
{
    return ((c >= "0") && (c <= "9"));
}

function isAsciiLetter(c)
{
    return (((c >= "a") && (c <= "z")) || ((c >= "A" && c <= "Z")));
}

function isLetter(c)
{
    return (((c >= "a") && (c <= "z")) || ((c >= "A" && c <= "Z")) || (c >= "\u008F"));
}

function validateDuplicates(form)
{
    var aUniqueFields = uniqueFields;
    for (var i = 0, auLen = aUniqueFields.length; i < auLen; i++)
    {
        var formEltName = aUniqueFields[i];
        var formObjects = eval("form." + formEltName);

        if (formObjects == null)
            continue;
        var multiple = ((formObjects.length != null) && (formObjects.type == null || formObjects.type != "select-one"));
        if (multiple)
        {
            var objLength = formObjects.length;

            for (var j = 0; j < objLength; j++)
            {
                var formObj = formObjects[j];
                if (formObj == null)
                {
                    messageAlert("FAILED_TO_EVAL", formEltName);
                    return false;
                }
                if (!formObj.disabled)
                {
                    var valueObj = (formObj.type == "select-one" ? (formObj.options[formObj.options.selectedIndex].text) : formObj.value);
                    for (var k = j + 1; k < objLength; k++)
                    {
                        var formObj2 = formObjects[k];
                        if (formObj2 == null)
                        {
                            messageAlert("FAILED_TO_EVAL", formEltName);
                            return false;
                        }
                        if (!formObj2.disabled)
                        {
                            var valueObj2 = (formObj2.type == "select-one" ? (formObj2.options[formObj2.options.selectedIndex].text) : formObj2.value);
                            if (valueObj == valueObj2)
                            {
                                if ((formObj.type != "select-one") || (formObj.options[formObj.options.selectedIndex].value != ""))
                                {
                                    messageAlert("DUPLICATED_VALUE", valueObj);
                                    formObj2.focus();
                                    return false;
                                }
                            }
                        }
                    }
                    if(!validateReadOnlyDuplicates(formEltName, formObj))
                        return false;
                }
            }
        }
        else if(!validateReadOnlyDuplicates(formEltName, formObjects))
            return false;
    }
    return true;           
}

function validateReadOnlyDuplicates(formEltName, formObj)
{
    var uniqueReadOnlyArray = eval("uniqueReadOnly" + formEltName);
    if (uniqueReadOnlyArray == null)
    {
        messageAlert("FAILED_TO_EVAL", formEltName);
        return false;
    }
    var valueObj = (formObj.type == "select-one" ? (formObj.options[formObj.options.selectedIndex].text) : formObj.value);
    for (var k = 0, m = uniqueReadOnlyArray.length; k < m; k++)
    {
        var formObj2 = uniqueReadOnlyArray[k];
        if (formObj2 == null)
        {
            messageAlert("FAILED_TO_EVAL", formEltName);
            return false;
        }
        if (valueObj == formObj2)
        {
            if ((formObj.type != "select-one") || (formObj.options[formObj.options.selectedIndex].value != ""))
            {
                messageAlert("DUPLICATED_VALUE", valueObj);
                formObj.focus();
                return false;
            }
        }
    }
    return true;           
}

function compareString(s1, s2)
{
    var ret = 0;

    if(s1 < s2)
        ret = -1;
    if(s1 == s2)
        ret =  0;
    if(s1 > s2)
        ret =  1;

    return ret;
}


function toUpperCase(s)
{
    var result = s.toUpperCase();
    return result;
}

function charToUpperCase(c)
{
    var result = (""+c).toUpperCase();
    return result;
}

function keyPressedToUpperCase(keyCode) {
    // If keyCode is 'Enter' or 'Esc', skip the conversion.
    if (keyCode == 13 || keyCode == 27)
        return true;
    var range = document.selection.createRange();
    range.text = String.fromCharCode(keyCode).toUpperCase();
    range.collapse();
    range.select();
    return false;
}

function pasteToUpperCase() {
    var range = document.selection.createRange();
    range.text = toUpperCase(clipboardData.getData("Text"));
    range.collapse();
    range.select();
    return false;
}

function round(number, precision)
{
    var mult = 1;
    for (i = 0; i < precision; i++)
        mult = mult * 10;
    number = number * mult;
    number = Math.round(number);
    number = number / mult;
    return number;
}

// Remove whitespace characters ( \t\n\r\f\v) which appear in the beginning and at the end of a string.
function trimBeginEnd(str)
{
    var str1 = str;
    if (str1 != null && str1.length > 0)
    {
        var sBegin = str1.search(/\S/);
        if (sBegin == -1) // string is empty
            return ("");
        var arr = str1.split("");
        arr.reverse();
        str1 = arr.join("");
        var sEnd = str1.length - str1.search(/\S/);
        if (sEnd == str1.length)
            str1 = str.substring(sBegin);
        else
            str1 = str.substring(sBegin, sEnd);
        str = null;
        arr = null;
    }
    return str1;
}

function indexInArray(array, element)
{
    for (var i = 0, j = array.length; i < j; i++)
        if (element == array[i])
            return i;
    return -1;
}

function canFocus(focusElement)
{
    var result = true;
    var owningtable = focusElement;
    while(owningtable != null) {
        var owningtable = getTag(owningtable.parentElement, "TABLE");
        if(owningtable != null && owningtable.id != "") {
            var children = owningtable.childNodes;
            for (var i = 0, iN = children.length; i < iN; i++) {
                var child = children[i];
                if (child != null && child.nodeName == 'TBODY' && 
                                    (child.id == '_containerBody' || child.id == '_containerbody' ||
                                        child.id == 'containerBodyIndent' || child.id == 'containerbody')) {
                    result = (child.style.display != 'none');
                    break;
                }
            }
            break;
        }
    }
    return result;
}

// Finds first input capable child field.
function findFirstTab(node) {
    var result = null;
    if (node.hasChildNodes()) {
        var children = node.childNodes;
        for (var i = 0, cLen = children.length; i < cLen; i++) {
            var child = children[i];
            if (child.nodeType == 1 ) { //Node.ELEMENT_NODE
                if ((child.tagName == 'INPUT' && child.type != 'hidden') || child.tagName == 'SELECT') {
                    if (!child.disabled && child.name != 'savedSearches' &&
                             (!child.style || !child.style.visibility || child.style.visibility == "visible")) {
                        result = child;
                        if(canFocus(result))
                            break;
                        else
                            result = null;
                    }
                    else if (child.name.charAt(child.name.length - 1) == '_') {
                        // Multi-select combo-box's name has '_' as the last character.
                        result = getCombobox(getTag(child, "FORM"), child.name.substring(0, child.name.length - 1));
                        if (result != undefined && canFocus(result))
                            break;
                        else
                            result = null;
                    }
                } else {
                    result = findFirstTab(child);
                    if (result != null) 
                        break;
                }
            }
        }
    }
    return result;
}


// Sets focus to the first field in the form that is input field
function putInFocus(form) {
    if (form != null) {
        var focusElement = findFirstTab(form);
        if (focusElement && focusElement.focus && !focusElement.disabled) {
            focusElement.focus();
        }
    }
}

// Sets focus to the first field in the form (sorted by tabindexes) that is input field
function changeImageButtonState(elementID, enable) {
    var entityIDColumn = document.getElementById(elementID);
    if (entityIDColumn != null) {
        var entityIDColumnSrc = '' + entityIDColumn.innerHTML;
        var patternToFind;
        var patternToReplace;
        var arrayToFind;
        var arrayToReplace;
        var hrefonclick;
        if (enable) {
            patternToFind = IMAGE_BUTTON_DISABLE_STRING;
            patternToReplace = IMAGE_BUTTON_ENABLE_STRING;
            arrayToFind = inactiveIconArray;
            arrayToReplace = activeIconArray;
            hrefonclick = IN_PROGRESS + "return;";
        }
        else {
            patternToFind = IMAGE_BUTTON_ENABLE_STRING;
            patternToReplace = IMAGE_BUTTON_DISABLE_STRING;
            arrayToFind = activeIconArray;
            arrayToReplace = inactiveIconArray;
            hrefonclick = "";
        }
        var idx0 = entityIDColumnSrc.indexOf(patternToFind);
        if (idx0 > -1)
            entityIDColumnSrc = entityIDColumnSrc.substring(0, idx0) + patternToReplace + entityIDColumnSrc.substring(idx0 + patternToFind.length);
        idx0 = entityIDColumnSrc.indexOf(patternToFind);
        if (idx0 > -1)
            entityIDColumnSrc = entityIDColumnSrc.substring(0, idx0) + patternToReplace + entityIDColumnSrc.substring(idx0 + patternToFind.length);
        for (var k = 0, m = arrayToFind.length; k < m; k++) {
            idx0 = entityIDColumnSrc.indexOf(arrayToFind[k]);
            if (idx0 > -1)
                entityIDColumnSrc = entityIDColumnSrc.substring(0, idx0) + arrayToReplace[k] + entityIDColumnSrc.substring(idx0 + arrayToFind[k].length);
        }
        entityIDColumn.innerHTML = entityIDColumnSrc;
        entityIDColumn.firstChild.onclick = hrefonclick;
    }
}

function removeLabel(elementID) {
    replaceLabel(elementID, '');
}

function replaceLabel(elementID, value) {
    var entityNameLabel;
    entityNameLabel = document.getElementById(elementID);
    if (entityNameLabel != null)
        entityNameLabel.innerHTML = value;
}

function showMessageBox(button, iconType, message, width, height) {
    return i2uiShowMessageBox("/tm/component/ModalDialog.jsp?interaction=" + button +
            "&icontype=" + iconType + "&message=" + message, width, height);
}

function encodeURLParameter(parameter) {
    return encodeURIComponent(parameter);
}

function encodeJSValue(parameter) {
    var specialChars = new Array('\'');
    var specialCharsReplaced = new Array('&#39;');
    var index;
    var result = parameter;
    for(var i = 0, scLen = specialChars.length; i < scLen; i++)
        while ((index = result.indexOf(specialChars[i])) >= 0)
            result = result.substring(0, index) + specialCharsReplaced[i] + result.substring(index + 1);
    return result;
}

function formatMaskField(field, maskType, dependOnValue, newChar)
{
    var fieldValue;
    fieldValue = field.value;
    if (DEBUG)
    {
        alert("validateField fieldValue="+fieldValue+", maskType="+maskType+
              ", dependOnValue="+dependOnValue);
    }

    var masks;
    for (var i = 0, mtLen = fieldMasks[maskType].length; i < mtLen; i++)
        if (fieldMasks[maskType][i][0] == dependOnValue)
        {
            masks = fieldMasks[maskType][i][1];
            break;
        }
    if (masks != null)
        formatMask(field, masks, newChar);
}

function formatMask(field, masks, newChar)
{
    var maskUsedIndex = -1;
    
    for(var i = 0, mkLen = masks.length; ((maskUsedIndex == -1) && (i < mkLen)); i++)
    {
        if(masks[i].length > field.value.length)
        {
            var symbol = masks[i].charAt(field.value.length);
            switch(symbol)
            {
                case '*':
                    if(isLetter(newChar) || isDigit(newChar))
                    {
                        field.value = field.value + newChar;
                        maskUsedIndex = i;
                    }
                    break;
                case '#':
                    if(isDigit(newChar))
                    {
                        field.value = field.value + newChar;
                        maskUsedIndex = i;
                    }
                    break;
                case '$':
                    if(isLetter(newChar))
                    {
                        field.value = field.value + newChar;
                        maskUsedIndex = i;
                    }
                    break;
                case ' ':
                case '-':
                case '(':
                case ')':
                    field.value = field.value + symbol;
                    maskUsedIndex = i;
                    break;
                default:
                    break;
            }
        }
    }
    if((maskUsedIndex != -1) && (masks[maskUsedIndex].length > field.value.length))
    {
        var symbolFound = true;
        var charIndex = field.value.length;
        while(symbolFound)
        {
            var symbol = masks[maskUsedIndex].charAt(charIndex);
            switch(symbol)
            {
                case ' ':
                case '-':
                case '(':
                case ')':
                    field.value = field.value + symbol;
                    break;
                default:
                    symbolFound = false;
                    break;
            }
            charIndex++;
        }
    }
    field.value = toUpperCase(field.value);
}

function onMaskChanged(event, maskType, formField, dependOnCode, dependOnField)
{
    var dpndOnCode = dependOnCode;
    if (dependOnField != undefined)
    {
        var gridFlds = fieldsGrid;
        for (var i = 0, gfLen = gridFlds.length; i < gfLen; i++)
        {
            if (gridFlds[i].formEltName == dependOnField)
            {
                if (gridFlds[i].validationType == 'select')
                {
                    var dpndOnFld = getCombobox(utp.form, dependOnField, utp.getRowIndex(event.srcElement));
                    dpndOnCode = dpndOnFld.options[dpndOnFld.selectedIndex].value;
                }
                else
                    dpndOnCode = getColumnObject(utp.form, dependOnField, rowIdx).value;
            }
        }
    }
    formatMaskField(formField, maskType, dpndOnCode, String.fromCharCode(event.keyCode));
}

var timeLastKeyPressed = 0;
var keyPressedBuffer = "";

var comboBoxName = "";
var comboBoxSelectedIndex = 0;
var comboBoxIndex = -1;
var secondarySelectedIndex = -1;
var tabKey = false;
var charInput = false;
var directionKey = false;
var uptoOnClick = false;
var mouseUpExecuted = false;
var focusOnState = false;

function executeComboBoxOnMouseDown()
{
    var sndr = window.event.srcElement;
    focusOnState = false;
}

function executeComboBoxOnMouseUp()
{
    var sndr = window.event.srcElement;
    mouseUpExecuted = true;
}

function executeComboBoxOnKeyDown()
{
    var sndr = window.event.srcElement;
    if (!sndr.multiple)
    {
        onComboBoxKeyDown(sndr);
    }
}

function executeComboBoxOnClick()
{
    var sndr = window.event.srcElement;
    if (!sndr.multiple)
    {
        if (uptoOnClick)
        {
            if (secondarySelectedIndex != -1)
                sndr.options.selectedIndex = secondarySelectedIndex;

            prepareComboBoxSelection(sndr);
        }
        uptoOnClick = false;
        secondarySelectedIndex = -1;
        tabKey = false;
        charInput = false;
    }
}

function executeComboBoxOnChange()
{
    var sndr = window.event.srcElement;
    if (!sndr.multiple)
    {
        if (tabKey)
        {
            tabKey = false;
        }
        else if (!charInput)
        {
            prepareComboBoxSelection(sndr);
            setComboBoxSelection(sndr);
        }
        else if (directionKey)
        {
            if (mouseUpExecuted)
                prepareComboBoxSelection(sndr);
            else
                setComboBoxSelection(sndr);

            directionKey = false;
        }
        else if (sndr.options.selectedIndex != 0)
        {
            if (mouseUpExecuted)
                prepareComboBoxSelection(sndr);

            setComboBoxSelection(sndr);
            secondarySelectedIndex = -1;
            uptoOnClick = false;
        }
        else
        {
            if (mouseUpExecuted)
            {
                secondarySelectedIndex = sndr.options.selectedIndex;
                uptoOnClick = true;
            }
            else
            {
                setComboBoxSelection(sndr);
                uptoOnClick = false;
            }
        }
        charInput = false;
        mouseUpExecuted = false;
        return;
    }
}

function executeComboBoxOnBlur()
{
    var sndr = window.event.srcElement;
    if (!sndr.multiple)
    {
        timeLastKeyPressed = 0;
        setComboBoxSelection(sndr);
        tabKey = false;
        charInput = false;
        mouseUpExecuted = false;
        lastComboBox = null;
    }
}

function selectKeyPress(sndr, key) 
{
    var comboBoxVisibleRowsWhenExpanded = 10;
    var char = String.fromCharCode(key);
    var now = ((new Date()).getTime());
    if(now - timeLastKeyPressed > 1000)
        keyPressedBuffer = "";

    window.event.returnValue = false;
    window.event.cancelBubble = true;
    timeLastKeyPressed = now;
    directionKey = true;

    var selectedIdx = sndr.options.selectedIndex;
    var optslen = sndr.options.length;
    switch (key)
    {
        case 33: // PgUp
                if (selectedIdx == -1)
                    sndr.options.selectedIndex = optslen - 1;
                else if ((selectedIdx - comboBoxVisibleRowsWhenExpanded) > 0)
                    sndr.options.selectedIndex -= comboBoxVisibleRowsWhenExpanded;
                else
                    sndr.options.selectedIndex = 0;
                break;
        case 34: // PgDown
                if (selectedIdx == -1)
                    sndr.options.selectedIndex = 0;
                else if ((selectedIdx + comboBoxVisibleRowsWhenExpanded) < (optslen - 1))
                {
                    if (((optslen - 1) - (selectedIdx + comboBoxVisibleRowsWhenExpanded)) < comboBoxVisibleRowsWhenExpanded)
                        sndr.options.selectedIndex = optslen - 1;
                    else
                        sndr.options.selectedIndex += comboBoxVisibleRowsWhenExpanded;
                }
                else
                    sndr.options.selectedIndex = optslen - 1;
                break;
        case 35: // End
                if (selectedIdx != optslen - 1)
                    sndr.options.selectedIndex = optslen - 1;
                break;
        case 36: // Home
                if (selectedIdx != 0)
                    sndr.options.selectedIndex = 0;
                break;
        case 38: // Up
                if (selectedIdx > 0)
                    sndr.options.selectedIndex--;
                break;
        case 40: // Down
                if (selectedIdx < (optslen - 1))
                    sndr.options.selectedIndex++;
                break;
        default:
            directionKey = false;
            for(var i = 0; i < optslen; i++) 
            {
                if((sndr.options[i].value != "") &&
                   (startsWith(sndr.options[i].text, keyPressedBuffer + char)))
                {
                    sndr.options[i].selected = true;
                    keyPressedBuffer += char;
                    break;
                }
            }
            break;
    }
    prepareComboBoxSelection(sndr);
    charInput = true;
    tabKey = false;
    return true;
}

function onComboBoxKeyDown()
{
    var sndr = window.event.srcElement;
    if (!sndr.multiple)
    {
        tabKey = false;
        var key = window.event.keyCode;
        window.event.returnValue = true;
        if (key == 13)  // Enter
        {
            window.event.cancelBubble = false;
            return;
        }
        if (key == 9)   // Tab
        {
            focusOnState = !(window.event.shiftKey);  // Meaningful only for country combo-box
            window.event.cancelBubble = true;
            prepareComboBoxSelection(sndr);
            tabKey = true;
            charInput = false;
            directionKey = false;
        }
        else
        {
            selectKeyPress(sndr, key);
        }
        mouseUpExecuted = false;
        return true;
    }
}

function prepareComboBoxSelection(sndr)
{
    comboBoxName = sndr.name;
    comboBoxSelectedIndex = sndr.options.selectedIndex;
    comboBoxIndex = sndr.uniqueNumber;
}

var lastComboBox;

function setComboBoxSelection(sndr)
{
    if (comboBoxName != "")
    {
        if (lastComboBox == undefined)
        {
            if (sndr.name == comboBoxName && sndr.options.length > 0 && comboBoxSelectedIndex > -1)
                sndr.options[comboBoxSelectedIndex].selected = true;
        }
        else
        {
            if ((lastComboBox.name == comboBoxName) && (lastComboBox.name == sndr.name) && (sndr.uniqueNumber == comboBoxIndex))
            {
                if (sndr.options.length > 0 && comboBoxSelectedIndex > -1)
                    sndr.options[comboBoxSelectedIndex].selected = true;
            }
        }
    }
}

function startsWith(source, toFind) 
{
    for(var i = 0, j = toFind.length; i < j; i++) 
    {
        if(toUpperCase(toFind.charAt(i)) != toUpperCase(source.charAt(i)))
            return false;
    }
    return true;
}

var duallistboxmoveitokay = true;
function tmuiduallistboxmoveit(fromlistbox, tolistbox, mandatoryItems, picked)
{
    duallistboxmoveitokay = true;
    if (picked == null)
        picked = fromlistbox.selectedIndex;
    if (picked >= 0)
    {
        if (mandatoryItems != null)
        {
            var miLen = mandatoryItems.length;
            if (miLen > 0)
            {
                for (var i = 0; i < miLen; i++)
                {
                    if (fromlistbox.options[picked].value == mandatoryItems[i])
                    {
                        messageAlert("CANNOT_UNSELECT_MANDATORY_ITEM", fromlistbox.options[picked].text);
                        duallistboxmoveitokay = false;
                        return;
                    }
                }
            }
        }
        var len = tolistbox.options.length;
        tolistbox.options.length++;
        tolistbox.options[len].text = fromlistbox.options[picked].text;
        tolistbox.options[len].value = fromlistbox.options[picked].value;
        fromlistbox.options[picked].selected = false;
        if (document.layers)
        {
            var len2 = fromlistbox.options.length;
            for (var i=picked; i<len2-1; i++)
            {
                fromlistbox.options[i].text = fromlistbox.options[i+1].text;
                fromlistbox.options[i].value = fromlistbox.options[i+1].value;
                fromlistbox.options[i].selected = fromlistbox.options[i+1].selected;
            }
            if (len2 > 0)
                fromlistbox.options.length--;
        }
        else if (document.all)
        {
            fromlistbox.options.remove(picked);
        }
        else
        {
            fromlistbox.options[picked] = null;
        }
    }
    if (fromlistbox.selectedIndex >= 0)
        tmuiduallistboxmoveit(fromlistbox, tolistbox, mandatoryItems);
}

function tmuiduallistboxmoveall(fromlistbox, tolistbox, mandatoryItems)
{
    var index = 0;
    fromlistbox.selectedIndex = -1;
    while(index < fromlistbox.options.length)
    {
        tmuiduallistboxmoveit(fromlistbox, tolistbox, mandatoryItems, index);
        if(!duallistboxmoveitokay)
            index++;
    }
}

// For List Customization Screen
function tmuiduallistboxmoveup(tolistbox, picked)
{
    if (picked == null)
        picked = tolistbox.selectedIndex;
    if (picked >= 1)
    {
        var tmpValue = tolistbox.options[picked].value;
        var tmpText = tolistbox.options[picked].text;
        tolistbox.options[picked].value = tolistbox.options[picked-1].value;
        tolistbox.options[picked].text = tolistbox.options[picked-1].text;
        tolistbox.options[picked-1].value = tmpValue;
        tolistbox.options[picked-1].text = tmpText;
        tolistbox.selectedIndex = picked-1;
    }
}

// For List Customization Screen
function tmuiduallistboxmovedown(tolistbox, picked)
{
    if (picked == null)
        picked = tolistbox.selectedIndex;
    if (picked >=0 &&  picked < tolistbox.options.length-1)
    {
        var tmpValue = tolistbox.options[picked].value;
        var tmpText = tolistbox.options[picked].text;
        tolistbox.options[picked].value = tolistbox.options[picked+1].value;
        tolistbox.options[picked].text = tolistbox.options[picked+1].text;
        tolistbox.options[picked+1].value = tmpValue;
        tolistbox.options[picked+1].text = tmpText;
        tolistbox.selectedIndex = picked+1;
    }
}

function isSelectionOK(listbox, selectedIndices)
{
    var idx = 0;
    for (var i = 0, lbLen = listbox.length; i < lbLen; i++)
    {
        if (listbox.options[i].selected == true)
        {
            selectedIndices[idx++] = i;
            if ((idx > 1) && ((selectedIndices[idx - 2] + 1) != selectedIndices[idx - 1]))
            {
                messageAlert("MULTIPLE_ITEMS_MUST_BE_SELECTED_CONSECUTIVELY");
                return false;
            }
        }
    }
    return true;
}

function listboxmovetotop(listbox)
{
    var selectedIndices = new Array();
    if (isSelectionOK(listbox, selectedIndices))
    {
        var picked = selectedIndices[0];
        if (picked >= 1)
        {
            var selectedSize = selectedIndices.length;
            var tmpValue = new Array(selectedSize);
            var tmpText = new Array(selectedSize);
            for (var i = 0; i < selectedSize; i++)
            {
                tmpValue[i] = listbox.options[selectedIndices[i]].value;
                tmpText[i] = listbox.options[selectedIndices[i]].text;
            }
            for (var i = selectedIndices[selectedSize - 1], j = (selectedSize - 1); i > j; i--)
            {
                listbox.options[i].value = listbox.options[i - selectedSize].value;
                listbox.options[i].text = listbox.options[i - selectedSize].text;
                listbox.options[i].selected = false;
            }
            for (var i = 0; i < selectedSize; i++)
            {
                listbox.options[i].value = tmpValue[i];
                listbox.options[i].text = tmpText[i];
                listbox.options[i].selected = true;
            }
        }
    }
}

function listboxmovetobottom(listbox)
{
    var selectedIndices = new Array();
    if (isSelectionOK(listbox, selectedIndices))
    {
        var picked = selectedIndices[selectedIndices.length - 1];
        var listboxsize = listbox.options.length;
        if ((picked >= 0) && (picked < (listboxsize - 1)))
        {
            var selectedSize = selectedIndices.length;
            var tmpValue = new Array(selectedSize);
            var tmpText = new Array(selectedSize);
            for (var i = 0; i < selectedSize; i++)
            {
                tmpValue[i] = listbox.options[selectedIndices[i]].value;
                tmpText[i] = listbox.options[selectedIndices[i]].text;
            }
            for (var i = selectedIndices[0], j = (listboxsize - selectedSize); i < j; i++)
            {
                listbox.options[i].value = listbox.options[i + selectedSize].value;
                listbox.options[i].text = listbox.options[i + selectedSize].text;
                listbox.options[i].selected = false;
            }
            for (var i = (listboxsize - selectedSize), j = 0; i < listboxsize; i++, j++)
            {
                listbox.options[i].value = tmpValue[j];
                listbox.options[i].text = tmpText[j];
                listbox.options[i].selected = true;
            }
        }
    }
}

function listboxmoveup(listbox)
{
    var selectedIndices = new Array();
    if (isSelectionOK(listbox, selectedIndices))
    {
        var picked = selectedIndices[0];
        if (picked >= 1)
        {
            var selectedSize = selectedIndices.length;
            var tmpValue = listbox.options[picked - 1].value;
            var tmpText = listbox.options[picked - 1].text;
            var tmpidx = picked + selectedSize - 1;
            for (var i = picked - 1; i < tmpidx; i++)
            {
                listbox.options[i].value = listbox.options[i + 1].value;
                listbox.options[i].text = listbox.options[i + 1].text;
                listbox.options[i].selected = true;
            }
            listbox.options[tmpidx].value = tmpValue;
            listbox.options[tmpidx].text = tmpText;
            listbox.options[tmpidx].selected = false;
        }
    }
}

function listboxmovedown(listbox)
{
    var selectedIndices = new Array();
    if (isSelectionOK(listbox, selectedIndices))
    {
        var picked = selectedIndices[selectedIndices.length - 1];
        var selectedSize = selectedIndices.length;
        if (picked >= 0 && picked < listbox.options.length - 1)
        {
            var tmpValue = listbox.options[picked + 1].value;
            var tmpText = listbox.options[picked + 1].text;
            var tmpidx = picked - selectedSize + 1;
            for (var i = picked + 1; i > tmpidx; i--)
            {
                listbox.options[i].value = listbox.options[i - 1].value;
                listbox.options[i].text = listbox.options[i - 1].text;
                listbox.options[i].selected = true;
            }
            listbox.options[tmpidx].value = tmpValue;
            listbox.options[tmpidx].text = tmpText;
            listbox.options[tmpidx].selected = false;
        }
    }
}

function removeListboxItem(listbox, idx)
{
    if (document.layers)
    {
        for (var i = idx; i < listbox.options.length - 1; i++)
        {
            listbox.options[i].value = listbox.options[i + 1].value;
            listbox.options[i].text = listbox.options[i + 1].text;
        }
        listbox.options.length--;
    }
    else if (document.all)
    {
        listbox.options.remove(idx);
    }
    else
    {
        listbox.options[idx] = null;
    }
}

// columnValues is an array.
function determineColumnType(columnValues)
{
    var cvLen = columnValues.length;
    if (cvLen > 0)
    {
        var i = 0;
        // Check for Date
        var found = true;
        var valueLen = 10;
        do
        {
            var value = trimBeginEnd(columnValues[i]);
            if (value.length > 0)
            {
                if (value.length == 1 && value.charCodeAt(0) == 160)
                    i++;
                else if (isNaN(Date.parse(columnValues[i])))
                {
                    found = false;
                    break;
                }
                else
                {
                    if (columnValues[i].length > valueLen)
                        valueLen = columnValues[i].length;
                    i++;
                }
            }
            else
                i++;
        } while (i < cvLen);
        if (found)
        {
            if (valueLen > 10)
                return 3;   // Date and Time
            else
                return 2;   // Date only
        }

        // Check for numeric
        found = true;
        i = 0;
        do
        {
            var value = trimBeginEnd(columnValues[i]);
            if (value.length > 0)
            {
                if ((value.length == 1 && value.charCodeAt(0) == 160) ||
                        isNumeric(value, DefaultDecimalSeparator))
                    i++;
                else
                {
                    found = false;
                    break;
                }
            }
            else
                i++;
        } while (i < cvLen);
        if (found)
            return 1;   // Numeric
    }
    // Default is String
    return 0;
}

function parseDate(dateValue, pattern)
{
    if (pattern == null || pattern.length == 0)
        pattern = DateFormat;

    var dpattern = 'ymd';
    var part1 = pattern.substring(0, 1);
    if (part1 == 'M' || part1 == 'm')
        dpattern = 'mdy';
    else if (part1 == 'D' || part1 == 'd')
        dpattern = 'dmy';

    var dyear = '';
    var dmonth = '';
    var dday = '';
    if (dateValue.length == 1 && dateValue.charCodeAt(0) == 160)
    {
    }
    else
    {
        if (dpattern == 'mdy')
        {
            dmonth = dateValue.substring(0, 2);
            dday = dateValue.substring(3, 5);
            dyear = dateValue.substring(6);
        }
        else if (dpattern == 'dmy')
        {
            dday = dateValue.substring(0, 2);
            dmonth = dateValue.substring(3, 5);
            dyear = dateValue.substring(6);
        }
        else
        {
            dyear = dateValue.substring(0, 4);
            dmonth = dateValue.substring(5, 7);
            dday = dateValue.substring(8);
        }
    }
    return dyear+dmonth+dday;
}

function parseTime(timeValue, pattern)
{
    if (pattern == null || pattern.length == 0)
        pattern = TimeFormat;

    var tpattern = 'hm';
    if (pattern.length > 5)
        tpattern = 'hms';

    var thour = '';
    var tminute = '';
    var tsecond = '';
    if (timeValue.length == 1 && timeValue.charCodeAt(0) == 160)
    {
    }
    else
    {
        if (tpattern == 'hms')
        {
            thour = timeValue.substring(0, 2);
            tminute = timeValue.substring(3, 5);
            tsecond = timeValue.substring(6);
        }
        else
        {
            thour = timeValue.substring(0, 2);
            tminute = timeValue.substring(3);
        }
    }
    return thour+tminute+tsecond;
}

function parseDateTime(dateTimeValue)
{
    var pattern = DateAndTimeFormat;
    var datePattern = pattern.substring(0, 10);
    var timePattern = pattern.substring(11);
    if (dateTimeValue.length == 16)
    {
        var dateValue = dateTimeValue.substring(0, 10);
        var timeValue = dateTimeValue.substring(11);
        return parseDate(dateValue, datePattern) + parseTime(timeValue, timePattern);
    }
    else
        return dateTimeValue;
}

function getMask(maskType, dependOnValue)
{
    var retVal = null;
    if (dependOnValue != null && dependOnValue.length > 0)
    {
        for (var i = 0, fmLen = fieldMasks[maskType].length; i < fmLen; i++)
            if(fieldMasks[maskType][i][0] == dependOnValue)
            {
                retVal = fieldMasks[maskType][i][1];
                break;
            }
    }
    else
    {
        if (fieldMaskTypes[maskType] == 'currency')
            retVal = "";
        else if(maskType == '4' || maskType == '5')
        {
            
            retVal = new Array();
            retVal[0] = maskType == '4' ? HoursFormat : DaysFormat;
        }
        else
            retVal = new Array();
    }
    return retVal;
}

function tmuiToggleNavarea(doc, frameId, frameName, colWidth, toggleButtonName, buttonSrc1, button1txt, buttonSrc2, button2txt)
{
    if (doc.layers)
        return;
    var item = doc.getElementById(frameId);
    if (item != null)
    {
        var navbutton = document.getElementById(toggleButtonName);
        if (navbutton != null)
        {
            if(navbutton.src.indexOf(buttonSrc1) > -1)
            {
                navbutton.src = buttonSrc2;
                navbutton.alt = button2txt;
                isNavPadOpen = 1;
            }
            else
            {
                navbutton.src = buttonSrc1;
                navbutton.alt = button1txt;
                isNavPadOpen = 0;
            }
        }

        if (item.tagName == "IFRAME" || item.tagName == "DIV")
        {
            if (item.style.display == "none")
            {
                item.style.display = "";
                item.style.visibility = "visible";
            }
            else
            {
                item.style.display = "none";
            }
        }
        else if (item.tagName == "FRAME")
        {
            var colarray = item.parentElement.cols.split(",");
            var result = "";
            for (var i = 0, j = item.parentElement.children.length; i < j; i++)
            {
                if (item.parentElement.children[i].name == frameName)
                {
                    if (item.style.display == "none")
                    {
                        item.style.display = "";
                        item.style.visibility = "visible";
                        colarray[i] = colWidth;
                    }
                    else
                    {
                        item.style.display = "none";
                        colarray[i] = 0;
                    }
                }
                if (i > 0)
                    result += ",";
                result += colarray[i];
            }
            item.parentElement.cols = result;
        }
    }
}

function setNavButton(doc, frameId, frameName, toggleButtonName, buttonSrc1, button1txt, buttonSrc2, button2txt)
{
    var navbutton = document.getElementById(toggleButtonName);
    if (navbutton != null)
    {
        if (doc.layers)
            return;
        var item = doc.getElementById(frameId);
        if (item != null)
        {
            if (item.tagName == "IFRAME" || item.tagName == "DIV")
            {
                if (item.style.display == "none")
                {
                    navbutton.src = buttonSrc1;
                    navbutton.alt = button1txt;
                    isNavPadOpen = 0;
                }
                else
                {
                    navbutton.src = buttonSrc2;
                    navbutton.alt = button2txt;
                    isNavPadOpen = 1;
                }
            }
            else if (item.tagName == "FRAME")
            {
                for (var i = 0, j = item.parentElement.children.length; i < j; i++)
                {
                    if (item.parentElement.children[i].name == frameName)
                    {
                        if (item.style.display == "none")
                        {
                            navbutton.src = buttonSrc1;
                            navbutton.alt = button1txt;
                            isNavPadOpen = 0;
                        }
                        else
                        {
                            navbutton.src = buttonSrc2;
                            navbutton.alt = button2txt;
                            isNavPadOpen = 1;
                        }
                        break;
                    }
                }
            }
        }
    }
}

function resetSortIcon(tableID, colIndex, startIndex, endIndex, unsortIconsrc)
{
    for (var k = startIndex; k <= endIndex; k++) {
        if (k != colIndex) {
            var sortIcon = document.getElementById(tableID + k);
            if (sortIcon != null)
                sortIcon.src = unsortIconsrc;
        }
    }
}

/**
 *  Make sure those extra and hidden column headers' field ('SelectAll') has tabIndex = '-1' in order to avoid tabbing into.
 */
function fixSelectAll(form)
{
    if (form != null && form != undefined)
    {
        if (form.SelectAll != undefined && form.SelectAll.length != undefined && form.SelectAll.length > 1)
        {
            var SAlen = form.SelectAll.length - 1;
            for (var i = SAlen; i > 0; i--)
                form.SelectAll[i].tabIndex = '-1';
        }
    }
}

/**
 *  Make sure the top frame (which shows user name and logout link) is loaded before trying to update the user information.
 */
function restoretop(elementid)
{
    var topframedata = top.i2ui_shell_top.document.getElementById(elementid);
    if (topframedata == null || topframedata == undefined)
    {
        cmd = function(){restoretop(elementid);}
        setTimeout("cmd()", 25);
    }
    else
        resetShellActionsAndUsername();  // this function is defined in entry.jsp
}

function jump(form, jumpAction, totalPages, jumptext)
{
    var jumpfield = eval("form."+jumpAction);
    if(!validateFieldType(jumpfield.value, jumptext, 'numeric', 4, 0, 1, true, totalPages, true))
    {
        jumpfield.focus();
        jumpfield.select();
    }
    else
    {
        window.document.body.style.cursor = 'progress';
        showStatusMessage();
        form.ControllerAction.value = jumpAction;
        form.submit();
    }
}

function jumpDate(form, jumpAction, jumptext)
{
    var jumpfield = eval("form."+jumpAction);
    if(!validateFieldType(jumpfield.value, jumptext, 'date'))
    {
        jumpfield.focus();
        jumpfield.select();
    }
    else
    {
        window.document.body.style.cursor = 'progress';
        showStatusMessage();
        form.ControllerAction.value = jumpAction;
        form.submit();
    }
}

function refreshList(form, savedSearchAction)
{
    form.ControllerAction.value = savedSearchAction;
    form.submit();
}

function sort(tableObj, tableID, colIndex)
{
    window.document.body.style.cursor = 'wait';
    cmd = function(){doSort(tableObj, tableID, colIndex);}
    setTimeout("cmd()",1);
}

function doSort(tableObj, tableID, colIndex)
{
    tableObj.doSorting(tableID, colIndex);

    if (tableObj.isFixedHeader)
        resizeTables();

    window.document.body.style.cursor = 'auto';
}

function resizeTables()
{
    for (var i = 0, j = tableObjects.length; i < j; i++)
    {
        var table = tableObjects[i];
        if (table instanceof GanttChart2)
            table.resizeGanttTable();
        else
            resizeTable(table);
        if (table.isFixedHeader && !(table instanceof GanttChart) && !(table instanceof GanttChart2))
            resizeTable(table);
    }
}

function resizeTable(tableObj)
{
    var tableWidthAdjmnt = 54;
    var tableHeaderHeight = 54;
    var scrollWidthAdjmnt = 400;
    var offsetWidth = document.body.offsetWidth;
    var tableWidth = offsetWidth - tableWidthAdjmnt;

    if (tableWidth < 777)
        tableWidth = 777;

    if (tableObj instanceof GanttChart) {
        tableObj.resizeTable(tableWidth);
        return true;
    }

    var displayHeight = tableObj.displayHeight;

    if (tableObj.narrowTable)
    {
        tableWidth = (tableWidth%2 == 0) ? (tableWidth-50)/2 : (tableWidth-51)/2;
        scrollWidthAdjmnt = (scrollWidthAdjmnt%2 == 0) ? (scrollWidthAdjmnt-20)/2 : (scrollWidthAdjmnt-21)/2;
    }

    if (!tableObj.isFixedHeader)
    {
        var t = tableObj.main_table_node;
        var ts = document.getElementById(tableObj.maintableid+'_scroller');
        if (t != undefined && ts != undefined)
        {
            //expand table if it's too narrow
            if (t.width < tableWidth)
                t.style.width = tableWidth;

            //adjust scroller width
            ts.style.width = tableWidth+16;

            //adjust scroller height
            var h = displayHeight + t.rows[0].clientHeight;
            if (h > t.clientHeight)
                h = t.clientHeight;

            ts.style.height = h+16;

            ts.scrollLeft = 0;

            //set 'tooltips'
            var trows = t.rows;

            var headerDescs = tableObj.headerDescs;
            if (headerDescs != null && headerDescs.length > 0)
            {
                var adjust = (tableObj.form.RowKey != undefined) ? 1 : 0;
                if (tableObj instanceof UpdateableTable)
                    adjust = 1;

                var tblWidth = tableObj.tablewidth + adjust;
                for (var i = 1, trLen = trows.length; i < trLen; i++) //rows loop
                {
                    var tcells = trows[i].cells;
                    for (var j = adjust; j < tblWidth; j++)
                    {
                        tcells[j].title = headerDescs[j-adjust];
                    }
                }
            }
        }
    }
    else if (tableObj instanceof UpdateableTable)
    {
        var tableid = tableObj.maintableid.substring(0, tableObj.maintableid.indexOf('_data'));
        i2uiResizeColumns(tableid);
        i2uiResizeScrollableArea(tableid, displayHeight, tableWidth, null, 20);
    }
    else if (tableObj.fixedColumns == 0)
    {
        i2uiResizeColumns(tableObj.maintableid, 1, 0, 0, tableHeaderHeight);
        if (tableObj.tableHeight > 0)
            i2uiResizeScrollableArea(tableObj.maintableid, displayHeight, tableWidth, null, 20);
        else
            i2uiResizeScrollableArea(tableObj.maintableid, displayHeight, tableWidth - scrollWidthAdjmnt);
    }
    else
    {
        if (offsetWidth < 831)
            scrollWidthAdjmnt -= 142;

        i2uiResizeScrollableArea(tableObj.secondarytableid, displayHeight, tableWidth - scrollWidthAdjmnt, tableObj.maintableid, tableWidthAdjmnt);
        i2uiResizeColumns(tableObj.maintableid, 1, 0, 0, tableHeaderHeight);
        i2uiResizeColumns(tableObj.secondarytableid, 1, 0, 0, tableHeaderHeight);
    }

    if (tableObj instanceof ROTable)
        fixSelectAll(tableObj.form);
}

function registeringKeyEvent(formName)
{
    demoObj = document.getElementById(formName);
    demoObj.addEventListener("keypress", keyPressed, false);
}

function setTDNodeValueById(tdnodeId, newValue)
{
    var tdnode = document.getElementById(tdnodeId);
    var anode = tdnode.childNodes[0];
    anode.nodeValue = newValue;
}

function registerOnLoadBody(onLoadFunc)
{
    if (document.onLoadFunctions == null) {
       document.onLoadFunctions = new Array();
    }
    document.onLoadFunctions[document.onLoadFunctions.length] = onLoadFunc;
}

function getNumberOfValues(fieldValue)
{
    var count = 0;

    if(fieldValue == null || fieldValue == "")
        return count;

    for(var fromIndex = 0 ; (fromIndex = fieldValue.indexOf(MULTIPLE_VALUES_SEPARATOR, fromIndex)) != -1 ; fromIndex++, count++)
         ;

    return count;
}

function dumpObject(obj) {
    var dump = "";
    for (var i in obj) {
        try {
            dump += ";"+i+"=";
            dump += obj[i];
        } catch(error) {
        }
    }
    i2uitrace(0, dump);
}

function OpenSecondWindow(url, windowName)
{
    var height = 400;
    var width  = 600;
    var windTop  = (screen.height - height - 130)/2;
    var windLeft = (screen.width - width)/2;

    window.open(url, windowName, 'height=' + height + ', width=' + width + ', top=' + windTop + ', left=' + windLeft + ', screenX=' + windLeft + ', screenY=' + windTop + ', resizable=yes, menubar=yes, toolbar=no, statusbar=yes, status=yes, scrollbars=yes');
}

function getComboBoxSelectedValues(srcobj)
{
    var result = new Array();
    var len = srcobj.options.length;
    for (var i = 0, j = 0; i < len; i++)
    {
        if (srcobj.options[i].selected && srcobj.options[i].value.length > 0)
            result[j++] = srcobj.options[i].value;
    }
    return result;
}

function getComboBoxSelectedText(srcobj)
{
    var result = new Array();
    var len = srcobj.options.length;
    for (var i = 0, j = 0; i < len; i++)
    {
        if (srcobj.options[i].selected && srcobj.options[i].value.length > 0)
            result[j++] = srcobj.options[i].text;
    }
    return result;
}

function i2uiCollapseContainerIgnoreIndicator(id)
{
    i2uiCollapseContainer(id);
}

function i2uiExpandContainerIgnoreIndicator(id)
{
    i2uiExpandContainer(id);
}

function setConstraintIndicator(tableid)
{
    var owningtable = document.getElementById(tableid);
    if (owningtable != undefined)
    {
        var parntnode = owningtable.rows[0].cells[0];
        if (parntnode != undefined)
            checkSectionInput(owningtable, parntnode);
    }
}

function tmToggleConstraintIndicator(item)
{
    var owningtable = getTag(item, "TABLE");
    var parntnode = item.parentNode;
    checkSectionInput(owningtable, parntnode);
}

function checkSectionInput(owningtable, parntnode)
{
    var len = owningtable.tBodies.length;
    var contenttbody;
    for (var i = 0; i < len; i++)
    {
        contenttbody = owningtable.tBodies[i];
        if (contenttbody.id == '_containerBody' || contenttbody.id == '_containerbody' ||
                contenttbody.id == 'containerBodyIndent' ||contenttbody.id == 'containerbody')
            break;
    }
    if (contenttbody != undefined)
    {
        len = contenttbody.rows[0].cells[0].childNodes.length;
        var anode;
        for (var i = 0; i < len; i++)
        {
            anode = contenttbody.rows[0].cells[0].childNodes[i];
            if (anode.tagName == "TABLE")
                break;
        }
        if (anode != undefined)
        {
            contenttbody = anode.tBodies[0];
            var trows = contenttbody.rows.length;
            var hasData = false;
            for (var i = 0; (!hasData && i < trows); i++)
            {
                var tcells = contenttbody.rows[i].cells.length;
                for (var j = 0; (!hasData && j < tcells); j++)
                {
                    var chldNodes = contenttbody.rows[i].cells[j].childNodes;
                    for (var k = 0, m = chldNodes.length; (!hasData && (k < m)); k++)
                    {
                        var chldnode = chldNodes[k];
                        if (chldnode.nodeName == "INPUT")
                        {
                            var nodeType = chldnode.type.toUpperCase();
                            if ((nodeType == "TEXT" && chldnode.value.length > 0) ||
                                    ((nodeType == "CHECKBOX" || nodeType == "RADIO") && chldnode.checked))
                                hasData = true;
                        }
                        else if (chldnode.nodeName == "SELECT" && chldnode.value.length > 0)
                            hasData = true;
                    }
                }
            }
            var lastChld = parntnode.lastChild;
            if (hasData)
            {
                if (lastChld.nodeName == "IMG")
                {
                    if (lastChld.src.indexOf(constraintIcon) < 0)
                    {
                        parntnode.appendChild(document.createTextNode(" "));
                        parntnode.appendChild(getIcon(constraint));
                    }
                }
                else
                {
                    parntnode.appendChild(document.createTextNode(" "));
                    parntnode.appendChild(getIcon(constraint));
                }
            }
            else
            {
                if (lastChld.nodeName == "IMG" && lastChld.src.indexOf(constraintIcon) > -1)
                {
                    parntnode.removeChild(lastChld.previousSibling);
                    parntnode.removeChild(lastChld);
                }
            }
        }
    }
}

function validateMaximumSelection(form)
{
    var maxSelection = 80;
    var selection = form.RowKey;
    if (selection != undefined && selection.length != undefined)
    {
        var cnt = 0;
        for (var i = 0, j = selection.length; i < j; i++)
            if (selection[i].checked)
                cnt++;

        if (cnt > maxSelection)
        {
            messageAlert("MAXIMUM_SELECTION_EXCEEDED", maxSelection);
            return false;
        }
    }
    return true;
}

function selectTab(action, form)
{
    window.document.body.style.cursor = 'progress';
    showStatusMessage();
    cntrlAction = eval("form." + "ControllerAction");
    cntrlAction.value = action;
    form.submit();
}

function extraValidation(name)
{
    var newName = 'Check' + name;
    if((typeof(this[newName]) != 'undefined') && (typeof(this[newName]) == 'function'))
        return (eval(newName)());
    return true;
}

var pageSubmitted = false;
function setSubmitted()
{
    pageSubmitted = true;
}

function resetSubmitted()
{
    pageSubmitted = false;
}

function isSubmitted()
{
    return pageSubmitted;
}

function getSelectedIndexes(obj)
{
    var result = new Array();
    var idx = obj.selectedIndex;
    while (idx > -1)
    {
        result[result.length] = idx;
        obj.options[idx].selected = false;
        idx = obj.selectedIndex;
    }

    for (var i = 0, j = result.length; i < j; i++)
        obj.options[result[i]].selected = true;

    return result;
}

/**************************************************************************************************
    Support for TM comboboxes with multiselect.
***************************************************************************************************/
// Safe method to get name of combobox control.
function getCombobox(form, name, rowIdx) {
    if (rowIdx == undefined)
    {
        var result = form[name+"_"];
        if (!result)
            result = form[name];
        return result;
    }
    else
    {
        var colobjs = getColumnObjects(name+"_");
        if (colobjs.length == 0)
            colobjs = getColumnObjects(name);
        return colobjs[rowIdx];
    }
}
function showComboboxSelection(combobox) {
    if (combobox.tmcomboboxName)
        window[combobox.tmcomboboxName].showSelected();
}
function comboboxToFocus(combobox) {
    if (combobox.tmcomboboxName) {
        if (combobox.tmfocus) {
            combobox.tmfocus();
        }
        else {
            combobox.focus();
        }
    }
    else
        combobox.focus();
}
function TMComboBoxNative(name) {
    this.name=name;
    this.objectName=name+"_tmcombobox";
    if (window[this.objectName])
        alert("duplicated name of combobox "+this.name);
    window[this.objectName]=this;
    this.size=11;
    this.minSize=3;
    this.tabIndex=0;
    this.width="180px";
    this.height="14px";
    this.timeLastKeyPressed = 0;
    this.keyPressedBuffer = "";
    this.onchange = null;
    this.maxInTitle = 10;
    this.hasHiddenParam=true;   // If true then defines hidden parameter with comma separated list of values
    this.isDisabled=false;
}
TMComboBoxNative.prototype.error = function(error) {alert(error); throw error;}
TMComboBoxNative.prototype.setHiddenParam = function(hasHiddenParam) {this.hasHiddenParam=hasHiddenParam;}
TMComboBoxNative.prototype.setName = function(name) {this.name=name;}
TMComboBoxNative.prototype.setTabIndex = function(tabIndex) {this.tabIndex=tabIndex;}
TMComboBoxNative.prototype.setSize = function(size) {this.size=size;}
TMComboBoxNative.prototype.setWidth = function(width) {this.width=width;}
TMComboBoxNative.prototype.setOptions = function(options) {this.options=options;}
TMComboBoxNative.prototype.setOnchange = function(onchange) {this.onchange=onchange;}
TMComboBoxNative.prototype.isSelected = function(option) {return ((option.length == 3) && (option[2] == 1));}
TMComboBoxNative.prototype.activate = function() { 
    this.head = document.getElementById(this.name+"_id");
    this.options = document.getElementById(this.name+"_options");
    this.options.tmcomboboxName = this.objectName;
    this.optionsShown = 0;
    var childNodes = this.head.childNodes;

    for(var i = 0, cnLen = childNodes.length; i < cnLen; i++) {
        var child = childNodes[i];
        if (child.nodeType == 1) {
            if(child.tagName == "SPAN") {
                this.headText = child;
            }
            else if (child.tagName == "IMG") {
                this.headIcon = child;
            }
        }
    }

    if (this.hasHiddenParam) {
        this.hiddenParam = document.getElementById(this.name+"_value");;
    }
    this.showSelected();
    if (this.onchange) {
        this.prevSelectedOptions = this.getSelectedOptions(false);
    }

    this.options.prevFocus = this.options.focus;
    try {
        this.options.focus = new Function("window[\'"+this.objectName+"\'].optionsFocus()");
    } catch(e) {
        this.options.tmfocus = new Function("window[\'"+this.objectName+"\'].optionsFocus()");
    }
}
TMComboBoxNative.prototype.optionsFocus = function() { 
    if (this.optionsShown == 0) {
        this.headText.focus();
    } else {
        this.options.prevFocus();
    }
}
TMComboBoxNative.prototype.headFocus = function() { 
    this.headText.focus();
}
TMComboBoxNative.prototype.toggleOptions = function () {
    if (this.optionsShown == 0) {
        this.expandOptions();
    }
    else {
        this.collapseOptions(); this.headFocus();
    }
}
TMComboBoxNative.prototype.onHeadKeyPress = function () {
    this.doSearchByLetter();
    return false;
}
TMComboBoxNative.prototype.onHeadKeyDown = function () {
    var keyCode = window.event.keyCode;
    var cont = false;
    var isChanged = false;
    var options = this.options.options;
    switch (keyCode) {
        case 40: // Down
            if (window.event.altKey) {
                this.expandOptions();
            } else {
                if (options.selectedIndex == -1) {
                    options.selectedIndex = 0;
                    isChanged = true;
                } else if (options.selectedIndex < options.length - 1) {
                    options.selectedIndex++;
                    isChanged = true;
                }
            }
            break;
        case 38: // Up
            if (window.event.altKey) {
                this.expandOptions();
            } else {
                if (options.selectedIndex == -1) {
                    options.selectedIndex = options.length - 1;
                    isChanged = true;
                } else if (options.selectedIndex > 0) {
                    options.selectedIndex--;
                    isChanged = true;
                } else {
                    options.selectedIndex = 0;
                    isChanged = true;
                }
            }
            break;
        case 34: // PgDown
            if (options.selectedIndex == -1) {
                options.selectedIndex = 0;
                isChanged = true;
            } else if (options.selectedIndex+this.size < options.length - 1) {
                options.selectedIndex += this.size;
                isChanged = true;
            } else {
                options.selectedIndex = options.length - 1;
                isChanged = true;
            }
            break;
        case 33: // PgUp
            if (options.selectedIndex == -1) {
                options.selectedIndex = options.length - 1;
                isChanged = true;
            } else if (options.selectedIndex-this.size > 0) {
                options.selectedIndex -= this.size;
                isChanged = true;
            } else {
                options.selectedIndex = 0;
                isChanged = true;
            }
            break;
        case 36: // Home
            if (options.selectedIndex != null || this.getSelectedOptions(true).length > 1) {
                options.selectedIndex = 0;
                isChanged = true;
            }
            break;
        case 35: // End
            if (options.selectedIndex != options.length - 1) {
                options.selectedIndex = options.length - 1;
                isChanged = true;
            }
            break;
        default:
            cont = this.doSearchByLetter();
            break;
    }
    if (isChanged) {
        this.showSelected();
        this.doOnChange();
    }
    if (!cont) {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
    }
}
TMComboBoxNative.prototype.doSearchByLetter = function () {
    var result = true;
    var now = (new Date()).getTime();
    if(now - this.timeLastKeyPressed > 1000) {
        this.keyPressedBuffer = "";
    }
    this.timeLastKeyPressed = now;

    var startText = this.keyPressedBuffer + String.fromCharCode(window.event.keyCode);

    var options = this.options.options;
    for(var i = 0, j = options.length; i < j; i++) {
        var option = options[i];
        if((option.value != "") && (startsWith(option.text, startText))) {
            this.options.selectedIndex=i;
            this.keyPressedBuffer = startText;
            window.event.returnValue = false;
            window.event.cancelBubble = true;
            this.showSelected();
            result = false;
            break;
        }
    }
    return result;
}
TMComboBoxNative.prototype.onOptionKeyDown = function () {
    var keyCode = window.event.keyCode;
    if (keyCode == 27) //ESC
    {
        this.headFocus(); // closes options as side-effect of onblur for options
    }
    else if (keyCode == 9) // Tab 
    {
        window.event.returnValue = false;
        window.event.cancelBubble = true;
        this.headFocus(); // closes options as side-effect of onblur for options
    } 
    else if ((keyCode == 13) || // Enter
            ((keyCode == 40) && window.event.altKey) ||  // Alt+Down
            ((keyCode == 38) && window.event.altKey))    // Alt+Up 
    {
        window.event.returnValue = false;
        window.event.cancelBubble = true;
        this.headFocus(); // closes options as side-effect of onblur for options
    }
    else if (window.event.shiftKey && keyCode == 119)
    { // toggle multiselect mode
        this.keystrokeMultiselectMode = !this.keystrokeMultiselectMode;
    }
    return true;
}
TMComboBoxNative.prototype.onOptionKeyPress = function () {
    var keyCode = window.event.keyCode;
    if (keyCode != 32 &&                // space
        !this.keystrokeMultiselectMode) // disable i2 search in multiselect mode
    {
        this.doSearchByLetter();
        return false;
    }
    return true;
}
TMComboBoxNative.prototype.onClick = function () {
    if (!window.event.ctrlKey) {  // If CTRL is not pressed - hide control (like simple select)
        this.headFocus();
    }
    return true;
}
TMComboBoxNative.prototype.filterOptions = function () {
    var selected = 0;
    var withoutvalue = 0;
    if (this.options.selectedIndex != -1) {
        var options = this.options.options;
        var opLen = options.length;
        for (var i = 0; i < opLen; i++) {
            var option = options[i];
            if (option.selected) {
                selected++;
                if (option.value.length == 0)
                    withoutvalue++;
            }
        }
        if (selected > 0 && selected > withoutvalue) {
            for (var i = 0; i < opLen; i++) {
                var option = options[i];
                if (option.selected && option.value.length == 0) {
                    option.selected = false;
                }
            }
        }
    }
}
TMComboBoxNative.prototype.showSelected = function () {
    this.filterOptions();
    var display = "";
    var codes = "";
    var alt = "";
    var selectedNum = 0;
    if (this.options.selectedIndex != -1) {
        var options = this.options.options;
        for (var i = 0, opLen = options.length; i < opLen; i++) {
            var option = options[i];
            if (option.selected) {
                selectedNum++;
                if (display.length > 0) {
                    display += MULTIPLE_VALUES_SEPARATOR;
                }
                if (codes.length > 0 && option.value.length > 0) {
                    codes += MULTIPLE_VALUES_SEPARATOR;
                }
                display += option.text;
                codes += option.value;
                if (selectedNum <= this.maxInTitle) {
                    if (alt.length > 0) {
                        alt += "\n";
                    }
                    if (selectedNum == this.maxInTitle) {
                        alt += "...";
                    } else {
                        alt += option.text;
                    }
                }
            }
        }
    }
    if (selectedNum > 1) {
        display = "+" + display;
    }
    this.setHeadText(display);
    this.setTitleText(alt);
    if (this.hiddenParam) {
        this.hiddenParam.value=codes;
    }
}
TMComboBoxNative.prototype.setHeadText = function (text) {
    var childNodes = this.headText.childNodes;
    for (var i = 0, cnLen = childNodes.length; i < cnLen; i++) {
       var wrkChild = childNodes[i];
       if (wrkChild.nodeName == "#text") {
          wrkChild.nodeValue = text;
          break;
       }
    }
}
TMComboBoxNative.prototype.setTitleText = function (text) {
    this.headText.title=text;
    this.headIcon.title=text;
}
TMComboBoxNative.prototype.onHeadMouseDown = function () {this.headMouseDown = true}
TMComboBoxNative.prototype.onHeadMouseUp = function () {this.headMouseDown = false}
TMComboBoxNative.prototype.onHeadMove = function () {
    // Head moves in two cases:
    // - when parent windows resizes
    // - sometimes the head is not put into right position by IE when browser is resized and 
    //   combobox head may jump up/down, when options are expanded.
    // This method helps to keep expanded options together with the head.
    if (this.optionsShown == 1) {
        this.options.style.left = this.head.offsetLeft;
        this.options.style.width = this.head.offsetWidth;
        this.options.style.pixelTop = this.calculateOptionsTop();
    }
}
TMComboBoxNative.prototype.computeTop = function (obj) {
    if (document.layers)
        return;

    if (typeof obj == "string")
        obj = document.getElementById(obj);

    var y = 0;
    if (obj != null && obj.offsetTop != null)
        y = obj.offsetTop;

    if (obj != null && obj.offsetParent != null) {
        var parnt = obj.offsetParent;
        if(parnt.tagName == "DIV")
            parnt = getTag(parnt, "BODY");
        return y + this.computeTop(parnt);
    }
    return y;
}
TMComboBoxNative.prototype.calculateOptionsTop = function () {
    // This code compensates for invalid calculation of options position inside of TD elements.
    // Probably compensation code would become more complex when new cases are found.
    var top = this.computeTop(this.head) + this.head.offsetHeight;
    var parentElement = this.head.parentElement;
    if (parentElement && parentElement.tagName == "TD") {
        if(parentElement.vAlign == "middle" || parentElement.vAlign == "") {
            top -= (parentElement.offsetHeight - this.head.offsetHeight)/2;
        }
    }

    // If element does not fit into the window - change position/size
    var winScrollTop = document.body.scrollTop;
    var winHeight = document.body.clientHeight;
    var listHeight = this.options.offsetHeight;
    while (true && listHeight != 0) {
        var listHeight = this.options.offsetHeight;
        if (top+listHeight <= winScrollTop+winHeight) {
            break;
        } if (top-this.head.offsetHeight-listHeight > winScrollTop || this.options.size <= this.minSize) {
            top = top-this.head.offsetHeight-listHeight;
            break;
        } else {
            this.options.size = parseInt(this.options.size) - 1;
        }
    }
    return top;
}
TMComboBoxNative.prototype.expandOptions = function () {
    this.options.style.left = this.head.offsetLeft;
    this.options.style.width = this.head.offsetWidth;
    this.options.style.pixelTop = this.calculateOptionsTop();

    this.options.style.visibility = "visible";
    this.optionsShown = 1;
    this.keystrokeMultiselectMode = false;
    this.options.focus();
    this.scrollToFirstSelected();
}
TMComboBoxNative.prototype.getSelectedOptions = function (includingNoValue) {
    var selected = new Array();
    if (this.options.selectedIndex != -1) {
        var options = this.options.options;
        for (var i = 0, opLen = options.length; i < opLen; i++) {
            var option = options[i];
            if (option.selected && (includingNoValue || option.value.length > 0)) {
                selected[selected.length] = i;
            }
        }
    }
    return selected;
}
TMComboBoxNative.prototype.scrollToFirstSelected = function () {
    // IE does not provide explicit functions to scroll multiselect combobox to selected values.
    // But it does it implicitly, options is becoming selected.
    var selectedIndex = this.options.selectedIndex;
    if (selectedIndex != -1) {
        var options = this.options.options;
        options[selectedIndex].selected = false;
        options[selectedIndex].selected = true;
    }
}
TMComboBoxNative.prototype.doOnChange = function () {
    if (this.onchange) {
        var nowSelectedOptions = this.getSelectedOptions(false);
        var isChanged = (nowSelectedOptions.length != this.prevSelectedOptions.length);
        if (!isChanged) {
            for (var i = 0, nsoLen = nowSelectedOptions.length; i < nsoLen; i++) {
                if (nowSelectedOptions[i] != this.prevSelectedOptions[i]) {
                    isChanged = true;
                    break;
                }
            }
        }
        if (isChanged) {
            this.prevSelectedOptions = nowSelectedOptions;
            eval(this.onchange);
        }
    }
}
TMComboBoxNative.prototype.collapseOptions = function () {
    // Click on combobox header will result in the following sequence of events:
    // 1) header.mousedown  --> headMouseDown=true
    // 2) options.onblur    --> invokes collapseOptions
    // 3) header.mouseup    --> headMouseUp=false
    // 4) header.mouseclick --> invokes toggleOptions and it would invoke expandOptions
    // Check the headMouseDown so collapseOptions do not hide and options will be hidden by toggleOptions
    if (!this.headMouseDown) {
        this.options.style.zindex = 0;
        this.options.style.visibility = "hidden";
        this.optionsShown = 0;
        this.doOnChange();
    }
}
TMComboBoxNative.prototype.onFocus = function () {
    this.headText.style.background="navy";
    this.headText.style.color="white";
}
TMComboBoxNative.prototype.onBlur = function () {
    this.headText.style.background="white";
    this.headText.style.color="black";
    this.doOnChange();
}
TMComboBoxNative.prototype.validate = function () {
}
TMComboBoxNative.prototype.toString = function () {
    // - Event keypress is not generated for keys related to movement, like PgUp, etc.
    //   So event keydown is used instead.
    // - Event keydown is used on text, not on head element to avoid problems with passing
    //   focus to text, when options are opened.
    this.validate();
    var EOL="\n";
    var IE50 = true;
    var IE60 = false;

    // Output head
    var html = "<span id=\""+this.name+"_id\""+
                " onmousedown=\"return "+this.objectName+".onHeadMouseDown();\""+
                " onmove=\"return "+this.objectName+".onHeadMove();\""+
                " onmouseup=\"return "+this.objectName+".onHeadMouseUp();\""+
                " onclick=\"return "+this.objectName+".toggleOptions();\"";
    if (this.isDisabled) {
        html +=" disabled";
    }
    html += " class=tmPullDownHead style=\"width:"+this.width+";height:"+this.height+";overflow:none;";
    if (IE50) {
        //html +=         "border:1px solid #999999;"; Moved to css
    } else if (IE60) {
        html += "border-bottom:1px solid #d4d0c8;border-right:1px solid #d4d0c8;"+
                "border-left:1px solid #808080;border-top:1px solid #808080;word-spacing:-4;";
    }
    html += "vertical-align:top;white-space:nowrap;\">"+EOL+"<span "+
            " onkeydown=\"return "+this.objectName+".onHeadKeyDown();\""+
            " onkeypress=\"return "+this.objectName+".onHeadKeyPress();\""+
            " onfocus=\"return "+this.objectName+".onFocus();\""+
            " onblur=\"return "+this.objectName+".onBlur();\""+
            " tabindex=\""+this.tabIndex+"\""+
            " style='width:"+this.width+";margin:0px;";
    if (IE50) {
        html += "border:0px;";
    } else if (IE60) {
        html += "border-right:0px;border-bottom:0px;border-top:1px solid #404040;border-left:1px solid #404040;word-spacing:0;";
    }
    html += "padding:1px;overflow-x:hidden;white-space:nowrap;vertical-align:top;"+
            "'>&nbsp;</span>"+EOL+"<img src=\"/tm/images/btn_multibox.gif\""+
            " onfocus=\"blur();\" style=\"border:0;margin:0;padding:0;";
    if (IE60) {
        html += "border-top:1px solid #404040;";
    }
    html += "vertical-align:top;\">"+EOL+"</span>"+EOL;

    // Output body
    var size = this.size;
    if (size > this.options.length) size = this.options.length;
    html += "<select"+
            " name=\""+(this.hasHiddenParam ? (this.name+"_") : this.name)+"\""+
            " size=\""+this.size+"\" multiple id=\""+this.name+"_options\""+
            " onblur=\"return "+this.objectName+".collapseOptions();\""+
            " onclick=\"return "+this.objectName+".onClick();\""+
            " onkeydown=\"return "+this.objectName+".onOptionKeyDown();\"" +
            " onkeypress=\"return "+this.objectName+".onOptionKeyPress();\"" +
            " onchange=\""+this.objectName+".showSelected();\""+
            " class=pulldown" +
            " style=\"position:absolute;top:0px;left:0px;visibility:hidden;z-index:20;\" >"+EOL;
    for (var i = 0, j = this.options.length; i < j; i++) {
        var option = this.options[i];
        if (option.length > 0) {
            html += "<option value=\""+option[0]+"\"";
            if (this.isSelected(option)) html+=" selected";
            html += ">"+option[1]+"</option>"+EOL;
        }
    }
    html += "</select>"+EOL;
    if(this.hasHiddenParam) {
        html += "<input id=\""+this.name+"_value\" name=\""+this.name+"\" type=hidden />"+EOL;
    }
    //  i2uitrace(0, html);
    html += "<script language=\"JavaScript\">"+
            this.objectName+".activate();"+
            "</script>"+EOL;
    return html;
}

function refreshCountriesStates(formObj)
{
    var _idx = formObj.name.indexOf("ountry");
    if(_idx != -1) {
        var stateName = "States";
        if(_idx > 1)
            stateName = toUpperCase(formObj.name.charAt(0)) + formObj.name.substring(1, (_idx - 1)) + "States";

        func = eval("refresh" + stateName);
        func();
    }
}

function getCanadianPostalRule()
{
    var pstlRule = new Array();
    pstlRule[0] = new Array();
    pstlRule[0][0] = "AB";
    pstlRule[0][1] = new Array();
    pstlRule[0][1][0] = "T";
    pstlRule[1] = new Array();
    pstlRule[1][0] = "BC";
    pstlRule[1][1] = new Array();
    pstlRule[1][1][0] = "V";
    pstlRule[2] = new Array();
    pstlRule[2][0] = "MB";
    pstlRule[2][1] = new Array();
    pstlRule[2][1][0] = "R";
    pstlRule[3] = new Array();
    pstlRule[3][0] = "NB";
    pstlRule[3][1] = new Array();
    pstlRule[3][1][0] = "E";
    pstlRule[4] = new Array();
    pstlRule[4][0] = "NL";
    pstlRule[4][1] = new Array();
    pstlRule[4][1][0] = "A";
    pstlRule[5] = new Array();
    pstlRule[5][0] = "NS";
    pstlRule[5][1] = new Array();
    pstlRule[5][1][0] = "B";
    pstlRule[6] = new Array();
    pstlRule[6][0] = "NT";
    pstlRule[6][1] = new Array();
    pstlRule[6][1][0] = "X";
    pstlRule[7] = new Array();
    pstlRule[7][0] = "NU";
    pstlRule[7][1] = new Array();
    pstlRule[7][1][0] = "X";
    pstlRule[8] = new Array();
    pstlRule[8][0] = "ON";
    pstlRule[8][1] = new Array();
    pstlRule[8][1][0] = "K";
    pstlRule[8][1][1] = "L";
    pstlRule[8][1][2] = "M";
    pstlRule[8][1][3] = "N";
    pstlRule[8][1][4] = "P";
    pstlRule[9] = new Array();
    pstlRule[9][0] = "PE";
    pstlRule[9][1] = new Array();
    pstlRule[9][1][0] = "C";
    pstlRule[10] = new Array();
    pstlRule[10][0] = "QC";
    pstlRule[10][1] = new Array();
    pstlRule[10][1][0] = "G";
    pstlRule[10][1][1] = "H";
    pstlRule[10][1][2] = "J";
    pstlRule[10][1][3] = "K";
    pstlRule[11] = new Array();
    pstlRule[11][0] = "SK";
    pstlRule[11][1] = new Array();
    pstlRule[11][1][0] = "S";
    pstlRule[12] = new Array();
    pstlRule[12][0] = "YT";
    pstlRule[12][1] = new Array();
    pstlRule[12][1][0] = "Y";

    return pstlRule;
}

function GetXmlHttpObject()
{
    var xmlHttp = null;
    try
    {
        // Firefox, Opera 8.0+, Safari
        xmlHttp = new XMLHttpRequest();
    }
    catch (e)
    {
        // Internet Explorer
        try
        {
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e)
        {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    return xmlHttp;
}

function isCtrlKeyPressed(event)
{
    var ctrlKeyPressed = event.ctrlLeft;
    if (ctrlKeyPressed == undefined || !ctrlKeyPressed)
        ctrlKeyPressed = event.ctrlKey;
    if (ctrlKeyPressed == undefined)
        return false;
    return ctrlKeyPressed;
}

function treeSelectWithCtrlKey(id, nodeID, type)
{
    var existed = false;
    var i = 0;
    for (i = 0; i < treeSelectedItems.length; i++)
    {
        if (treeSelectedItems[i] == id)
        {// click on existing item means unselect.
            tmuiUnHighlightMultiplePadItem(id);
            existed = true;
            break;
        }
    }
    if (!existed)
    {
        tmuiHighlightMultiplePadItem(id, nodeID, type);
    }
}

function treeSelectWithoutCtrlKey(id, nodeID, type)
{
    if (treeSelectedItems.length == 0)
    {
        tmuiHighlightMultiplePadItem(id, nodeID, type);
    }
    else if (treeSelectedItems.length == 1)
    {
        if (nodeID != selectedNodeIDs[0])
        {
            tmuiUnHighlightMultiplePadItem(treeSelectedItems[0]);
            tmuiHighlightMultiplePadItem(id, nodeID, type);
        }
    }
    else
    {
        var i = 0;
        for (i = 0; i < selectedNodeIDs.length; i++)
        {
            if (nodeID == selectedNodeIDs[i])
                break;
        }
        if (i == selectedNodeIDs.length)
        {
            var len = treeSelectedItems.length;
            for (i = 0; i < len; i++)
            {
                tmuiUnHighlightMultiplePadItem(treeSelectedItems[0]);
            }
            tmuiHighlightMultiplePadItem(id, nodeID, type);
        }
    }
}

function tmuiHighlightMultiplePadItem(id, nodeID, type)
{
    var obj = document.getElementById(id);
    if (obj != null)
    {
        obj = obj.parentNode;
        if (obj != null)
        {
            if (obj.tagName == 'TR')
            {
                if (treeSelectedItems.length > 0)
                {
                    if (type == treeSelectedType)   // must be same type as existing items.
                    {
                        obj.style.backgroundColor = '#fff6a6';
                        treeSelectedItems[treeSelectedItems.length] = id;
                        selectedNodeIDs[selectedNodeIDs.length] = nodeID;
                    }
                    else
                    {
                        messageAlert("Selected element not compatible with existing selections.");
                    }
                }
                else
                {
                    obj.style.backgroundColor = '#fff6a6';
                    treeSelectedItems[treeSelectedItems.length] = id;
                    selectedNodeIDs[selectedNodeIDs.length] = nodeID;
                    treeSelectedType = type;    // set selection type for first item.
                }
            }
        }
    }
}

function tmuiUnHighlightMultiplePadItem(id)
{
    var obj = document.getElementById(id);
    if (obj != null)
    {
        obj = obj.parentNode;
        if (obj != null)
        {
            if (obj.tagName == 'TR')
            {
                obj.style.backgroundColor = '#ffffff';
                var len = treeSelectedItems.length;
                for (var i = 0; i < len; i++)
                {
                    if (treeSelectedItems[i] == id)
                    {// remove item from arrays.
                        treeSelectedItems.splice(i, 1);
                        selectedNodeIDs.splice(i, 1);
                        break;
                    }
                }
                // If no more items, reset selection type.
                if (treeSelectedItems.length == 0)
                    treeSelectedType = '';
            }
        }
    }
}

//========================================================================
//  Function Name: validTreeNodesSelected
//  Description  : Determines if valid number of Tree Nodes selected
//========================================================================

function validTreeNodesSelected(form, selectionMode, selectedNodeIDs)
{
    var selectedNodes = (selectedNodeIDs != undefined)  ? selectedNodeIDs.length : 0;                            
    if(selectionMode == 'ONE' || selectionMode == 'ZEROONETWO')
    {
        var maxNum = (selectionMode == 'ONE') ? "1" : "2";
        if(selectedNodes > maxNum)
        {
            messageAlert((selectionMode == 'ONE') ? "MULTI_SELECT_NOT_ALLOW_FOR_ACTION" : "NO_MORE_THAN_TWO_ENTRIES_CAN_BE_SELECTED");
            return false;
        }
    }
    return true;
}
//========================================================================
//  Function Name: canAddChildren
//  Description  : Determines if TreeNode can be added to Parent Node
//=======================================================================

function canAddChildren(imageID)
{
    var obj = document.getElementById(imageID);
    if(obj) {
        var src = obj.getAttribute('src');
        if(src) {
            return(src.indexOf('minus') != -1);
        }
    }
    return false;
}

//========================================================================
//  Function Name: updateTableRows
//  Description  : Updates Table Rows (TR) with data from rspText
//=======================================================================

function updateTableRows(rspText)
{
    var header_ = "_h";
    var row_ = '_r';
    var record = rspText.split('~');
    for(var i = 0, iN = record.length; i < iN; i += 2)
    {
        var row = document.getElementById(record[i]);
        if(row)
        {
            row.deleteCell(0);
            var cell = row.insertCell(0);
            if(cell)
            {
                cell.innerHTML = record[i+1];
                cell.id = row.id.replace((row.id.indexOf(header_) != -1) ? row_+header_ : row_,'');
                cell.noWrap = true;
            }
        }
    }
}

function removeNodes(parentID, masterTableName)
{
    var header = "_h";
    var index = parentID.indexOf('r');
    var treeSubID = parentID.substr(0, index);
    var parentRow = document.getElementById(parentID);

    if(!parentRow) 
        parentRow = document.getElementById(parentID+header);

    if(parentRow)
    {
        var tableRows = document.getElementById(masterTableName).rows;
        for(var i = parentRow.rowIndex+1; i < tableRows.length && ((tableRows[i].id).indexOf(treeSubID) != -1); i++)
        {
            var row = document.getElementById(tableRows[i].id);
            if(row)
                row.parentNode.removeChild(row);
            --i;
        }
    }
}

function updateNodes(trParentID, rspText, masterTableName)
{
    removeNodes(trParentID, masterTableName);
    
    var header = "_h";
    var row_ = '_r';
    var record = rspText.split('~');
    var previousRowIndex = 0;
    
    for(var i = 0, iN = record.length; i < iN-1; i += 2)
    {
        if(record[i])
        {
            var row = document.getElementById(record[i]);
            if(row)
            {
                row.deleteCell(0);
                var cell = row.insertCell(0);
                if(cell)
                {
                    cell.innerHTML = record[i+1];
                    cell.id = row.id.replace((row.id.indexOf(header) != -1) ? row_ + header : row_,'');
                    cell.noWrap = true;
                }
                previousRowIndex = row.rowIndex;
            }
            else
            {
                var row = document.getElementById(masterTableName).insertRow(++previousRowIndex);
                if(row)
                {
                    row.id = record[i];
                    row.className = "solutionPadContent1";
                    var cell = row.insertCell(0);
                    if(cell)
                    {
                        cell.innerHTML = record[i+1];
                        cell.id = row.id.replace((row.id.indexOf(header) != -1) ? row_ + header : row_,'');
                        cell.noWrap = true;
                    }
                    previousRowIndex = row.rowIndex;
                }
            }
        }
    }
}


/* These three methods are required for OptimizationRequestLoadSearch.jsp and OptimizationRequestTripSearch.jsp
   The "search" fields on both pages do not support the exclusion search symbol (SearchExclusionSymbol) at this time.
*/

function isValidSearchField(s, charValidationFunction, isDuplicateAllowed) {
    var searchItems = new Array();
    var temp = s;
    var index;
    var nonSearchCharFound;
    while ((index = temp.indexOf(searchCharacters[1])) > 0) {
        searchItems[searchItems.length] = temp.substring(0, index);
        temp = temp.substring(index + 1);
    }
    if(index == 0)
        return false;
    searchItems[searchItems.length] = temp;
    for(var i = 0, siLen = searchItems.length; i < siLen; i++) {
        nonSearchCharFound = false;
        for (var j = 0, j2 = searchItems[i].length; j < j2; j++) {
            var c = searchItems[i].charAt(j);
            if(!isValidSearchChar(c)) {
                if (!charValidationFunction(c))
                    return false;
                nonSearchCharFound = true;
            }
        }
        if(!nonSearchCharFound)
            return false;
        if(isDuplicateAllowed != undefined && !isDuplicateAllowed)
            for(var j = i + 1, k = searchItems.length; j < k; j++)
                if(searchItems[i] == searchItems[j])
                    return false;
    }
    return true;
}

function isValidSearchChar(c) {
    for (var i = 0, scLen = searchCharacters.length; i < scLen; i++)
        if(searchCharacters[i] == c && i != 2)
            return true;
    return false;
}

/*
 * The followings are for Tabs and Tab Scrollers handling.
 * Providing the capabilities of showing the effect of tab scrolling left and right
 * when the screen width cannot display all available tabs.
 */
var lefthidden = -1;
var righthidden = -1;

function getTabDescLen(str)
{
    return ((str * 7) + 10);
}

function tmuiManageTabs(id, allowedwidth, isReset)
{
    if (document.layers)
        return;
    var obj = document.getElementById(id);
    if (obj != null)
    {
        lefthidden = -1;
        righthidden = -1;
        if (allowedwidth == null)
        {
            eval("allowedwidth = "+id+"_allowed_width");
            if (allowedwidth == 0)
                allowedwidth = document.body.clientWidth - 45;
        }
        else
        {
            eval(id+"_allowed_width="+allowedwidth);
        }
        if (isReset == undefined)
            isReset = false;

        var row = obj.rows[0];
        var tablen = row.cells.length;
        var tds = tablen - 5;
        var i = 0;
        var k = 0;
        var tabTotalLen = 0;
        while (i < tds)
        {
            if ((row.cells[i].style.display != "none") || isReset)
            {
                var tdL = getTabDescLen(tabDescLen[k]);
                if (((tabTotalLen + tdL) <= allowedwidth) && (righthidden == -1))
                {
                    if (tabTotalLen == 0)
                        lefthidden = k-1;
                    tabTotalLen += tdL;
                    row.cells[i].style.display = "";
                    row.cells[i++].style.visibility = "visible";
                    row.cells[i].style.display = "";
                    row.cells[i++].style.visibility = "visible";
                    row.cells[i].style.display = "";
                    row.cells[i++].style.visibility = "visible";
                    if (i > 3)
                    {
                        row.cells[i].style.display = "";
                        row.cells[i++].style.visibility = "visible";
                    }
                }
                else
                {
                    row.cells[i].style.display = "none";
                    row.cells[i++].style.visibility = "";
                    row.cells[i].style.display = "none";
                    row.cells[i++].style.visibility = "";
                    row.cells[i].style.display = "none";
                    row.cells[i++].style.visibility = "";
                    if (i > 3)
                    {
                        row.cells[i].style.display = "none";
                        row.cells[i++].style.visibility = "";
                    }
                    if (righthidden == -1)
                        righthidden = k;
                }
            }
            k++;
        }
        tmuiSetTabScrollers(id, row);
    }
}

function tmuiSetTabScrollers(id, row)
{
    var tablen = row.cells.length;
    if ((lefthidden > -1) || (righthidden > -1))
    {
        row.cells[tablen-4].style.display = "";
        row.cells[tablen-4].style.visibility = "visible";
        if (lefthidden == -1)
            row.cells[tablen-4].innerHTML = "<IMG border=\"0\" id=\""+id+"_tabscrollerleft\" src=\""+i2uiImageDirectory+"/scrollbar_left_disabled.gif\">";
        else
            row.cells[tablen-4].innerHTML = "<A href=\"javascript:tmuiScrollTabsRight('"+id+"')\"><IMG border=\"0\" id=\""+id+"_tabscrollerleft\" src=\""+i2uiImageDirectory+"/scrollbar_left.gif\"></A>";

        row.cells[tablen-2].style.display = "";
        row.cells[tablen-2].style.visibility = "visible";
        if (righthidden == -1)
            row.cells[tablen-2].innerHTML = "<IMG border=\"0\" id=\""+id+"_tabscrollerright\" src=\""+i2uiImageDirectory+"/scrollbar_right_disabled.gif\">";
        else
            row.cells[tablen-2].innerHTML = "<A href=\"javascript:tmuiScrollTabsLeft('"+id+"')\"><IMG border=\"0\" id=\""+id+"_tabscrollerright\" src=\""+i2uiImageDirectory+"/scrollbar_right.gif\"></A>";
    }
    else
    {
        row.cells[tablen-4].style.display = "none";
        row.cells[tablen-2].style.display = "none";
    }
}

function tmuiResetTabs(id, allowedwidth)
{
    if (document.layers)
        return;
    var obj = document.getElementById(id);
    if (obj != null)
    {
        if (allowedwidth == null)
        {
            eval("allowedwidth = "+id+"_allowed_width");
            if (allowedwidth == 0)
                allowedwidth = document.body.clientWidth - 45;
        }
        else
        {
            eval(id+"_allowed_width="+allowedwidth);
        }
        tmuiManageTabs(id, allowedwidth, true);
    }
}

function tmuiScrollTabsLeft(id)
{
    if (document.layers)
        return;
    var obj = document.getElementById(id);
    if (obj != null)
    {
        var allowedwidth = document.body.clientWidth - 45;
        var row = obj.rows[0];
        var tablen = row.cells.length;
        var tabTotalLen = 0;
        var z = (righthidden > -1) ? righthidden : tabDescLen.length;
        for (var i = lefthidden + 2; i < z; i++)
            tabTotalLen += getTabDescLen(tabDescLen[i]);

        var i = (lefthidden == -1) ? 0 : ((lefthidden + 1) * 4 - 1);
        row.cells[i++].style.display = "none";
        row.cells[i++].style.display = "none";
        row.cells[i++].style.display = "none";
        if (i > 3)
            row.cells[i].style.display = "none";
        lefthidden++;

        var tdL = getTabDescLen(tabDescLen[righthidden]);
        while ((tabTotalLen + tdL) <= allowedwidth)
        {
            tabTotalLen += tdL;
            i = righthidden * 4 - 1;
            row.cells[i].style.display = "";
            row.cells[i++].style.visibility = "visible";
            row.cells[i].style.display = "";
            row.cells[i++].style.visibility = "visible";
            row.cells[i].style.display = "";
            row.cells[i++].style.visibility = "visible";
            if (i > 3)
            {
                row.cells[i].style.display = "";
                row.cells[i].style.visibility = "visible";
            }
            righthidden = (righthidden == tabDescLen.length - 1) ? -1 : (righthidden + 1); 
            if (righthidden > -1)
                tdL = getTabDescLen(tabDescLen[righthidden]);
            else
                break;
        }
        tmuiSetTabScrollers(id, row);
    }
}

function tmuiScrollTabsRight(id)
{
    if (document.layers)
        return;
    var obj = document.getElementById(id);
    if (obj != null)
    {
        var allowedwidth = document.body.clientWidth - 45;
        var row = obj.rows[0];
        var tablen = row.cells.length;
        var tabTotalLen = 0;
        var z = lefthidden;
        for (var i = (righthidden == -1) ? (tabDescLen.length - 2) : righthidden - 2; i > z; i--)
            tabTotalLen += getTabDescLen(tabDescLen[i]);

        var i = (righthidden == -1) ? (tablen - 6) : (righthidden * 4 - 2);
        row.cells[i--].style.display = "none";
        row.cells[i--].style.display = "none";
        row.cells[i--].style.display = "none";
        if (i > 0)
            row.cells[i--].style.display = "none";
        righthidden = (righthidden == -1) ? (tabDescLen.length - 1) : (righthidden - 1);

        var tdL = getTabDescLen(tabDescLen[lefthidden]);
        while ((tabTotalLen + tdL) <= allowedwidth)
        {
            tabTotalLen += tdL;
            i = (lefthidden == 0) ? lefthidden : (lefthidden * 4 - 1);
            row.cells[i].style.display = "";
            row.cells[i++].style.visibility = "visible";
            row.cells[i].style.display = "";
            row.cells[i++].style.visibility = "visible";
            row.cells[i].style.display = "";
            row.cells[i++].style.visibility = "visible";
            if (i > 3)
            {
                row.cells[i].style.display = "";
                row.cells[i].style.visibility = "visible";
            }
            lefthidden--;
            if (lefthidden > -1)
                tdL = getTabDescLen(tabDescLen[lefthidden]);
            else
                break;
        }
        tmuiSetTabScrollers(id, row);
    }
}

// Encryption methods
function gcd (a, b)
{
    var r;
    while (b > 0)
    {
        r = a % b;
        a = b;
        b = r;
    }
    return a;
}

function reltv_prime(phi)
{
    var rel = 5;
    while (gcd(phi, rel) != 1)
        rel++;
    return rel;
}

function power(n, expo)
{
    var i, tmp = 1;
    for(i = 1; i <= expo; i++)
        tmp *= n;
    return tmp;
}

function encrypt(e, N, M)
{
    var r, i = 0, prod = 1, rem_mod = 0;
    while (e > 0)
    {
        r = e % 2;
        if (i++ == 0)
            rem_mod = M % N;
        else
            rem_mod = power(rem_mod, 2) % N;
        if (r == 1)
        {
            prod *= rem_mod;
            prod = prod % N;
        }
        e = parseInt(e / 2);
    }
    return prod;
}

function calculate_d(phi, e)
{
    var x, x1, x2, y, y1, y2, tmp, r, orig_phi;
    orig_phi = phi;
    x1 = 0;
    x2 = 1;
    y1 = 1;
    y2 = 0;
    while (e > 0)
    {
        tmp = parseInt(phi / e);
        r = phi - tmp * e;
        x = x2 - tmp * x1;
        y = y2 - tmp * y1;
        phi = e;
        e = r;
        x2 = x1;
        x1 = x;
        y2 = y1;
        y1 = y;
        if (phi == 1)
        {
            y2 += orig_phi;
            break;
        }
    }
    return y2;
}

function decrypt(d, N, c)
{
    var r, i = 0, prod = 1, rem_mod = 0;
    while (d > 0)
    {
        r = d % 2;
        if (i++ == 0)
            rem_mod = c % N;
        else
            rem_mod = power(rem_mod, 2) % N;
        if (r == 1)
        {
            prod *= rem_mod;
            prod = prod % N;
        }
        d = parseInt(d / 2);
    }
    return prod;
}

function encipher(obj1, obj2, obj3)
{
    if ((obj1 != undefined) && (obj2 != undefined))
    {
        var result = "";
        var text = obj2.value;
        if (text != null && text.length > 0)
        {
            for (var i = 0 ; i < text.length ; i++)
                result += encrypt(basicEncryptionGCD, basicEncryptionPublicKey, text.charCodeAt(i)) + basicEncryptionSeparator;
        }
        text = "";
        obj1.value = result;
        obj2.value = disguise(obj2.value);
        if (obj3 != undefined)
            obj3.value = obj2.value;
    }
}

function disguise(str)
{
    var newstr = "";
    if ((str != null) && (str.length > 0))
    {
        var len = str.length;
        for (var i = 0; i < len; i++)
            newstr += "*";
    }
    return newstr;
}

function clone(obj)
{
    var newObj = (obj instanceof Array) ? [] : {};
    for (i in obj)
    {
        if (i == "clone")
            continue;
        if (typeof obj[i] == "object")
            newObj[i] = clone(obj[i]);
        else
            newObj[i] = obj[i];
    }
    return newObj;
}

var lastTag;

// mouseOver
function msOver()
{
    lastTag = window.event.srcElement;
}

var ajaxSessionTimeoutMessage = "SESSION_TIMEOUT";

function refreshTableRecordCount(url)
{
    ajaxReq = GetXmlHttpObject();
    if (ajaxReq != null)
    {
        var url = url + "&TimeStampID=" + (new Date()).getTime();
        ajaxReq.onreadystatechange = function() {if ((ajaxReq.readyState == 4) && (ajaxReq.status == 200)) {updateRecordCount()}};
        ajaxReq.open("GET", url, true);
        ajaxReq.send(null);
    }
}

function getElementChild(parentObj, childElemType)
{
    for (var i = 0, j = parentObj.childNodes.length; i < j; i++)
    {
        var achild = parentObj.childNodes[i];
        if (achild.nodeName == childElemType)
            return achild;
    }
    return null;
}

function updateRecordCount()
{
    var resptxt = trimBeginEnd(ajaxReq.responseText);
    if (resptxt.indexOf(ajaxSessionTimeoutMessage) > -1)
        window.document.forms[0].submit();
    else
    {
        var result = resptxt.split('~');   // result = {id, total page#, total count text, pagenavid, form name, 'i18n Jump Text'};
        var snode = document.getElementById(result[0]);
        var fchild = snode.firstChild;  // DOM object of the Total Count text.
        if (fchild != undefined)
        {
            // Update Total Count.
            var updatePagingButtons = (fchild.nodeValue.indexOf('?') > -1);
            fchild.nodeValue = result[1] + '  ';
            var tbtbody = document.getElementById(result[3]).tBodies[0];
            var tr = tbtbody.rows[0];
            if (updatePagingButtons)
            {
                // Update the Jump to Last Page button.
                var nxttbl = getElementChild(tr.cells[2], "TABLE");
                var nxt = nxttbl.tBodies[0].rows[0].cells[0];
                var nxtchild = getElementChild(nxt, "A");
                var lsttbl = getElementChild(tr.cells[3], "TABLE");
                var lst = lsttbl.tBodies[0].rows[0].cells[0];
                var cntr = getElementChild(lst, "CENTER");
                var cntrimg = getElementChild(cntr, "IMG");
                var idx = cntrimg.src.indexOf("_inact");
                cntrimg.src = cntrimg.src.substring(0, idx) + cntrimg.src.substr(idx+6);
                lsttbl.className = nxttbl.className;
                lst.id = nxt.id;
                lst.className = nxt.className;
                var newnode = document.createElement("A");
                newnode.onclick = nxtchild.onclick;
                var idx = nxtchild.href.indexOf('=');
                newnode.href = nxtchild.href.substring(0, idx+1) + "JumpLast";
                newnode.appendChild(lst.removeChild(cntr));
                lst.appendChild(newnode);
                // Update Jump field
                var fjumpTo = getElementChild(tr.cells[4], "INPUT");
                fjumpTo.disabled = false;
            }
            // Update Jump button
            var jmptbl = getElementChild(tr.cells[5], "TABLE");
            var jmp = jmptbl.tBodies[0].rows[0].cells[0];
            var idx = jmptbl.className.indexOf("Disabled");
            if (idx > -1)
            {
                jmptbl.className = jmptbl.className.substring(0, idx);
                idx = jmp.id.indexOf("Disabled");
                jmp.id = jmp.id.substring(0, idx) + "Regular";
                idx = jmp.className.indexOf("Disabled");
                jmp.className = jmp.className.substring(0, idx);
                var newnode = document.createElement("A");
                newnode.href = "javascript:jump(document." + result[4] + ", 'JumpTo', " + result[2] + ", '" + result[5] + "');";
                newnode.tabindex = fjumpTo.tabindex;
                newnode.appendChild(jmp.removeChild(jmp.firstChild));
                jmp.appendChild(newnode);
            }
            else
            {
                var anode = getElementChild(jmp, "A");
                anode.href = "javascript:jump(document." + result[4] + ", 'JumpTo', " + result[2] + ", '" + result[5] + "');";
            }
        }
    }
}

function ajaxSimpleServerUpdate(url)
{
    ajaxReq = GetXmlHttpObject();
    if (ajaxReq != null)
    {
        url += "&TimeStampID=" + (new Date()).getTime();
        ajaxReq.onreadystatechange = null;
        ajaxReq.open("GET", url, true);
        ajaxReq.send(null);
    }
}

// args is an argument array
// args[0] = ajax url
// args[1] = action name
// args[2] = initiate field name
// args[3] = target element name
// if there is a need, more arguments can be passed along for future usage.
function ajaxRefresh(args, form)
{
    ajaxReq = GetXmlHttpObject();
    if (ajaxReq != null)
    {
        var srcfld = eval("form." + args[2]);
        var srcfldprm = srcfld.value;
        var tgtfldname = args[3];
        var tgtfld = eval("form." + tgtfldname);
        var tgtfldprm = tgtfld.value;
        var url = args[0] + "&srcfld=" + args[2] + "&" + args[2] + "=" + srcfldprm + 
                    "&tgtfld=" + tgtfldname + "&" + tgtfldname + "=" + tgtfldprm;

        var tgt = document.getElementById(tgtfldname + '_');
        if (tgt != undefined)
            url += "&firstLineEmpty=yes";
        else if ((tgtfld.type == 'select-one') || (tgtfld.type == 'select-multiple'))
        {
            if ((tgtfld.options.length > 0) && (tgtfld.options[0].value == ''))
                url += "&firstLineEmpty=yes";
            else
                url += "&firstLineEmpty=no";
        }
        else
            url += "&firstLineEmpty=no";

        url += "&TimeStampID=" + (new Date()).getTime();
        ajaxReq.onreadystatechange = function() {if ((ajaxReq.readyState == 4) && (ajaxReq.status == 200)) {updatePageElements(args)}};
        ajaxReq.open("GET", url, true);
        ajaxReq.send(null);
    }
}

function updatePageElements(args)
{
    var resptxt = trimBeginEnd(ajaxReq.responseText);
    if (resptxt.indexOf(ajaxSessionTimeoutMessage) == -1)
    {
        if (args[1] == 'RefreshLogisticsGroups')
            updateLogisticsGroups(args);

        args = null;
    }
    else
    {
        args = null;
        window.document.forms[0].submit();
    }
}

function updateLogisticsGroups(args)
{
    var resptxt = trimBeginEnd(ajaxReq.responseText);
    if (resptxt.length > 0)
    {
        resptxt = eval(resptxt);
        var selectobj = document.getElementById(args[3] + "_options");
        if (selectobj != undefined)
        {
            selectobj.innerHTML = "";
            var opts = null, op = null;
            for (var i = 0, size = resptxt.length; i < size; i++)
            {
                opts = resptxt[i];
                op = document.createElement('option');
                op.value = opts[0];
                op.text = opts[1];
                selectobj.add(op);
                selectobj.options[i].selected = (opts[2] == 1);
            }
            if (selectobj.name == (args[3] + '_'))
                eval(args[3] + "_tmcombobox.showSelected()");
            opts = null;
            op = null;
        }
        selectobj = null;
        resptxt = null;
    }
}

function exportData(url, ajaxurl, dwidth, dheight)
{
    ajaxReq = GetXmlHttpObject();
    if (ajaxReq != null)
    {
        ajaxurl = ajaxurl + "&TimeStampID=" + (new Date()).getTime();
        ajaxReq.onreadystatechange = function() {if ((ajaxReq.readyState == 4) && (ajaxReq.status == 200)) {showModalWindow(url, dwidth, dheight)}};
        ajaxReq.open("GET", ajaxurl, true);
        ajaxReq.send(null);
    }
}

function showModalWindow(url, dwidth, dheight)
{
    var resptxt = trimBeginEnd(ajaxReq.responseText);
    if (resptxt.indexOf(ajaxSessionTimeoutMessage) != -1)
        window.document.forms[0].submit();
    else if (resptxt.length > 0)
    {
        var args = new Object();
        args.window = window;
        showModalDialog(url, args, 'dialogWidth:'+dwidth+'px;dialogHeight:'+dheight+'px;status:0;scroll:0');
    }
}

function showHeaderMessage()
{
    var objlink = document.getElementById("tmMessageLink");
    var msgspan = document.getElementById("hdrmsgid");
    msgspan.className = "tooltipShow";
    msgspan.style.left = (objlink.offsetLeft + 8) + "em";
    msgspan.style.top = (objlink.offsetTop - 2) + "px";
    var swidth = objlink.offsetWidth;
    if (swidth > (document.body.clientWidth - 150))
        swidth = (document.body.clientWidth - 150);
    msgspan.style.width = Math.floor(swidth * ((swidth < 251) ? 0.94 : 0.9)) + "px";
}

function hideHeaderMessage()
{
    var msgspan = document.getElementById("hdrmsgid");
    msgspan.className = "tooltipHidden";
}

// Functions for TM Suggestion processing.
var ajaxReq = GetXmlHttpObject();
var currentSuggestObj = null;

function TMSuggestBox(id, formName, urlPrefix, controller, charCount, utpObj)
{
    this.id = id;
    this.objectName = id + "_suggest";
    window[this.objectName] = this;
    this.formName = formName;
    this.form = eval("document." + formName);
    this.urlPrefix = urlPrefix + controller + "?ControllerAction=SEARCH_SUGGEST_";
    this.charCount = charCount;
    this.utpObj = utpObj; // for updateable table
    this.initialized = false;
}

TMSuggestBox.prototype.activate = function(isAssociateFieldInUtp, associatedField, isDependOnFieldInUtp, dependOnField, dependOnValue)
{
    if (!this.initialized)
    {
        var form = this.form;
        var rowIndex = -1;
        this.isAssociateFieldInUtp = isAssociateFieldInUtp;
        if (isAssociateFieldInUtp)
        {
            rowIndex = this.utpObj.getRowIndex(window.event.srcElement);
            this.associateField = this.utpObj.getColumnObject(this.form, associatedField, rowIndex);
            this.associateValue = this.associateField.value;
        }
        else
        {
            this.associateField = eval("form." + associatedField);
            this.associateValue = this.associateField.value;
        }
        this.isDependOnFieldInUtp = isDependOnFieldInUtp;
        if (isDependOnFieldInUtp)
        {
            this.dependOnField = this.utpObj.getColumnObject(this.form, dependOnField, rowIndex);
            this.dependOnValue = this.dependOnField.value;
        }
        else
        {
            if (dependOnField != undefined)
            {
                this.dependOnField = eval("form." + dependOnField);
                this.dependOnValue = this.dependOnField.value;
            }
            else
            {
                this.dependOnField = null;
                this.dependOnValue = dependOnValue;
            }
        }
        this.displayed = 0;
        this.selectedItem = -1;
        this.listSize = 0;
        this.initialized = true;
    }
}

TMSuggestBox.prototype.onMouseOver = function()
{
    this.displayed = 1;
}

TMSuggestBox.prototype.onMouseOut = function()
{
    this.displayed = 0;
}

TMSuggestBox.prototype.onBlur = function()
{
    this.close();
}

TMSuggestBox.prototype.close = function()
{
    var ss = document.getElementById(this.objectName);
    ss.innerHTML = "";
    ss.style.height = 0;
    ss.style.width = 0;
    this.displayed = 0;
    this.selectedItem = -1;
    this.listSize = 0;
    this.initialized = false;
}

TMSuggestBox.prototype.calculateSelectionTop = function()
{
    return i2uiComputeTop(this.associateField) + this.associateField.offsetHeight;
}

handleSearchSuggest = function()
{
    if (ajaxReq.readyState == 4)
    {
        var ss = document.getElementById(currentSuggestObj.objectName);
        ss.innerHTML = '';
        var resptxt = trimBeginEnd(ajaxReq.responseText);
        if (resptxt.length > 0)
        {
            var str = resptxt.split(",");
            var strLen = str.length;
            currentSuggestObj.listSize = strLen;
            if ((strLen > 1) || ((strLen == 1) && (str[0].length > 0)))
            {
                for(i = 0; i < strLen; i++)
                {
                    /*
                    var suggest = '<div onmouseover="javascript:suggestOver(this);" ';
                    suggest += 'onmouseout="javascript:suggestOut(this);" ';
                    suggest += 'onclick=\"javascript:setTMSuggestion(this.innerHTML);\" ';
                    suggest += 'class="suggest_link">' + str[i] + '</div>';
                    */
                    var suggest = '<div id="sdiv'+i+'" ';
        			suggest += 'onclick=\"javascript:setTMSuggestion(this.id, this.innerHTML);\" ';
                    if (i == 0)
        			    suggest += 'class="suggest_link_over"';
                    else
                        suggest += 'class="suggest_link"';
                    suggest += '>' + str[i] + '</div>';
        			ss.innerHTML += suggest;
                    currentSuggestObj.selectedItem = 0;
        		}
                var hgt = 34;
                if (strLen > 1)
                {
                    if (strLen < 6)
                        hgt += (strLen - 1) * 17;
                    else
                        hgt = 102;
                }
                ss.style.height = (hgt + 1);
                ss.style.pixelTop = currentSuggestObj.calculateSelectionTop();
                var styleWidth = currentSuggestObj.associateField.offsetWidth + 16;
                ss.style.width = styleWidth;
                var osl = currentSuggestObj.associateField.parentElement.offsetLeft;
                osl += (currentSuggestObj.utpObj == undefined) ? 11 : 17;
                var cw = document.body.clientWidth;
                if ((osl + styleWidth) > cw)
                    osl = cw - styleWidth;
                ss.style.left = osl;
            }
        }
        else
        {
            currentSuggestObj.close();
        }
    }
}

function searchTMSuggest(suggestObj, valObj, isLocation)
{
    currentSuggestObj = suggestObj;
    var val = null;
    if (valObj instanceof UpdateableTable)
        val = suggestObj.associateField.value;
    else
        val = valObj;

    var keycode = window.event.keyCode;
    switch (keycode)
    {
        case 27:    // escape
            suggestObj.associateField.value = suggestObj.associateValue;
            suggestObj.close();
            break;

        case 38:    // Up
            setHighlight(true);
            break;

        case 40:    // Down
            setHighlight(false);
            break;
/*
        case 13:    // Enter
            var divid = "sdiv"+currentSuggestObj.selectedItem;
            setTMSuggestion(divid, document.getElementById(divid).innerHTML);
            break;
*/
        default:
            if (val.length == 0)
                suggestObj.close();
            else if ((val.length >= suggestObj.charCount) && (suggestObj.associateValue != val))
                submitSearchRequest(suggestObj, val, isLocation);
            else
                suggestObj.associateValue = val;
    }
    window.event.cancelBubble = true;
    window.event.returnValue = false;
}

function setHighlight(isUp)
{
    if (isUp)
    {
        if (currentSuggestObj.selectedItem > 0)
        {
            suggestOut(document.getElementById("sdiv" + currentSuggestObj.selectedItem));
            suggestOver(document.getElementById("sdiv" + (currentSuggestObj.selectedItem - 1)));
            currentSuggestObj.selectedItem--;
        }
    }
    else
    {
        if (currentSuggestObj.selectedItem < (currentSuggestObj.listSize - 1))
        {
            suggestOut(document.getElementById("sdiv" + currentSuggestObj.selectedItem));
            suggestOver(document.getElementById("sdiv" + (currentSuggestObj.selectedItem + 1)));
            currentSuggestObj.selectedItem++;
        }
    }
}

function submitSearchRequest(suggestObj, val, isLocation)
{
    suggestObj.associateValue = val;
    if (isLocation && suggestObj.dependOnValue == '')
        return false;

    if (ajaxReq.readyState == 4 || ajaxReq.readyState == 0)
    {
        var url = suggestObj.urlPrefix + "&entityType=" + suggestObj.dependOnValue + "&isLocation=" + (isLocation ? 1 : 0) + "&hint=" + escape(val) + "&TimeStampID=" + (new Date()).getTime();
        ajaxReq.open("GET", url, true);
        ajaxReq.onreadystatechange = handleSearchSuggest;
        ajaxReq.send(null);
    }
}

function setTMSuggestion(id, val)
{
    currentSuggestObj.associateField.value = val;
    currentSuggestObj.associateValue = val;
    currentSuggestObj.selectedItem = id.substring(4);
//    currentSuggestObj.associateField.focus();
    currentSuggestObj.close();
}

function suggestAssociateOnBlur()
{
    if ((currentSuggestObj != undefined))
    {
        currentSuggestObj.associateValue = currentSuggestObj.associateField.value;
        if (currentSuggestObj.displayed == 0)
            currentSuggestObj.close();
    }
}

function suggestOver(div_obj)
{
    div_obj.className = 'suggest_link_over';
}

function suggestOut(div_obj)
{
    div_obj.className = 'suggest_link';
}

function i2uiSyncdScrollVertical(mastertableid, slavetableid)
{
    var masterscrolleritem;
    var slavescrolleritem;
    masterscrolleritem = document.getElementById(mastertableid + "_scroller");
    slavescrolleritem  = document.getElementById(slavetableid + "_scroller");
    if (slavescrolleritem != null && masterscrolleritem != null)
    {
        slavescrolleritem.scrollTop = masterscrolleritem.scrollTop;
    }
}
function i2uiSyncdScrollHorizontal(mastertableid, slavetableid)
{
    var masterscrolleritem;
    var slavescrolleritem;
    masterscrolleritem = document.getElementById(mastertableid + "_scroller");
    slavescrolleritem  = document.getElementById(slavetableid + "_scroller");
    if (slavescrolleritem != null && masterscrolleritem != null)
    {
        slavescrolleritem.scrollLeft = masterscrolleritem.scrollLeft;
    }
}


