/*<!-- @#$ Copyright Start

© 1999 - 2002 Primavera Systems, In-  All rights reserved.

THE SERVICES AND SOFTWARE BEING ACCESSED MAY CONTAIN CONFIDENTIAL INFORMATION AND TRADE SECRETS OF PRIMAVERA SYSTEMS.
USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF PRIMAVERA SYSTEMS.

Copyright End @#$ -->*/

<!-- //Begin

/* ------------- Table of Contents -------------
1. Page Loading Progress
  - clearProgressIndicator()

2. Event Handling/Debugging Utilities
  - displayError(msg, error, debugLevel)
  - warning(message)
  - handleError(err, url, line)
  - displayProperties(thisThing)
  - displayFormElements(thisForm)
  - reportArguments(theArguments)
  - startTimer()
  - stopTimer()

3. Security Utilities

4. Browser and OS Utilities

5. System Utilities
  - getURLParams(pName)
  - setURLParams(pName, value)
  - getStyleClass(className, attrib)
  - setStyleClassAttrib(className, attrib, value)
  - pageUp()
  - pageDown()
  - scrollTop()
  - scrollBottom()
  - haltActions()
  - attemptedAction()
  - disabledAction()
  - captureActionMouseOver()
  - resumeActions()

6. TextArea and Input Field Utilities
  - setSelectionRange(input, selectionStart, selectionEnd)
  - setCaretToEnd(input)
  - setCaretToBegin(input)
  - setCaretToPos(input, pos)
  - selectString(input, string)
  - replaceSelection(input, replaceString)
  - enforceLimit(fieldObj)
  - limitText(fieldObj, sysEvent)
  - newCursorPos()

7. Date Utilities
  - checkDate(dateFld)
  - populateCFDate()
  - popUpCalendar()

8. Header Utilities
  - setProjectTitle(projectName)
  - unsetProjectTitle()
  - showTransQueue()
  - showChangeGroup()
  - clearHeaderActions()
  - showHelp(aHelpUrl)
  - setHelpUrl(aHelpUrl)
  - setSysItemType(aSysItemType)
  - unsetSysItemType()
  - getSysItemType()
  - setTransmittalQueueCount(count)

9. Anchor Utilities
  - debugHiddenFrame()
  - debugUtilitiesFrame()
  - debugSpellcheckerFrame()
  - debugPreferencesFrame()
  - showAnchorFrame()
  - hideAnchorFrame()
  - setModuleName(moduleName)
  - setModuleNameSuffix(moduleNameSuffix)
  - getModuleName()
  - unsetModuleName()
  - unsetModuleNameSuffix()
  - pushBreadCrumb(crumb, crumbLink)
  - clearBreadCrumb()
  - setJumpBack(jumpBackTitle, jumpBackLink)
  - setJumpBackMasterKey(jumpBackMasterKey)
  - clearCMJumpBack()
  - clearJumpBack()
  - showExpansion()
  - hideExpansion()
  - showSelection()
  - hideSelection()
  - setAnchorActions()
  - setAnchorButtonStates(astrButtonNames, astrButtonStates)
  - addAnchor(type)
  - addSpecialAnchor(link, image, anchorName, twistStateName, twistUpdFuncName)
  - setAnchors()
  - unsetAnchors()
  - setDetailAnchors()
  - gotoAnchor(anchor)

10. Action Utilities
  - showActionFrame()
  - toggleActionFrame()
  - showTreeFrame()
  - showSplitLogFrame()
  - showTotalsLogFrame()
  - resetLogFrame()
  - showLogNavigationFrame()
  - hideLogNavigationFrame()
  - setLogHref(toSysItemType, returnToLogPage, findText)
  - setDocHref(strHref)
  - setActions(displayNames, pictures, links, permittedFlags)
  - setActionsForButtons(displayNames, pictures, links, permittedFlags)
  - setWhatIsLogFrame(str)
  - getWhatIsLogFrame()
  - makeLogLinkInvisible()

11. Preferences Utilities
  - enableTwisties()
  - disableTwisties()
  - setTwistieExpand(imageId)
  - setTwistieCollapse(imageId)
  - getTwistieState(module, number)
  - setTwistieState(module, number, value)
  - getLogSplitScrollModule(module)
  - setLogSplitScrollModule(module, splitScrollData)
  - savePreferences()
  - refreshPreferences()

12. Image Utilities
  - changeImage(imageId, newImage)
  - ImageAnimator(imgName, imgURLs, spd)
  - ImageAnimator_play(play) - prototype function
  - ImageAnimator_animateLoop() - prototype function
  - ImageAnimator_animateCycle() - prototype function
  - ImageAnimator_animate() - prototype function

13. Struts Form Element Handler Utilities
  - returnElementIndex(theForm, elementName)
  - setInputFromThisSelect(theFormName, inputElement, thisElement)
  - updateHiddenTextArea(theFormName, hiddenElement, thisElement)

14. Popup Utilities
  - centerWindow(width, height, window)
  - positionWindow(width, height, position, window)
  - autoResizeWindow()
  - popupChildWindow(strHref, windowName, strFeatures)
  - popupPickerWindow(strHref, windowName)
  - popupDocumentWindow(strHref)
  - popupActivityInfo(strTaskCode)
  - popupUserInfo(strHref)
  - popupContactInfo(strHref)
  - popupCostDistribution(strAnchor, strHref)
  - contactPickerPopUp(pickerType, isAddressNeeded, isMultiSelect, organiseBy, sortBy, selectedVendorCode, selectedInitials, selectedCompany, isJobTitleNeeded, isTelephoneNeeded, isEnterpriseTypeNeeded)
  - submittalPickerPopUp(organiseBy, sortBy, selectedMasterKeys, selectedParentKeys, selectedTitles, selectedSubmittalNos, selectedPackageNumbers)
  - changeDocPickerPopUp()
  - contractPickerPopUp()
  - activityPickerPopUp()
  - projectPickerPopUp()
  - packagePickerPopup()
  - materialPickerPopUp()
  - safetyViolationPickerPopUp()

15. Cookie Utilities
  - setCookie(cookieName, cookieValue, expires, path, domain, secure)
  - getCookie(cookieName)
  - deleteCookie(cookieName)
  - setSessionCookie(cookieName, cookieValue)
  - setPersistentCookie(cookieName, cookieValue)
  - setTemporaryCookie(cookieName, cookieValue, days)

16. Form Verification Utilities
  - isValidEmail(element, emailID)
  - isElementNotNull(formElement, errorMsg)
  - convertFormCase(formElement, changeCase)

17. String Utilities
  - replaceStringWithString(theStr, replaceStr, withStr)
  - trim(trimText)
  - replaceEscapeChars(value)
  - replaceQuotes(value)
  - filter(value)
  - reverseFilter(value)
  - convertCase(value, changeCase)
  - populateMessage(msg, arr)
  - expEncode(value)
  - expDecode(value)

18. Currency Utilties
  - Number_toFixed(d) - prototype function
  - validateNumber(value)
  - validatePositiveNumber(value, allowThousSeparator)
  - validRange(value, min, max)
  - decimalFormatter(value, decimal)
  - currencyFormatter(value, decimal)
  - toFixed(value, decimal)
  - setThousandSeparator(value)
  - validateCurrency(value)
  - validateMaxLength(value, maxLength)
  - removeCommas(value)

19. LUW Utilities
  - setFormClean()
  - setFormDirty()
  - isFormDirty()
  - cleanDirtyChildren()
  - addDirtyChildren(childSection)
  - isChildDirty()
  - getDirtyChildren()
  - setChildClean()
  - setChildDirty()
  - triggerDirty(theDocument)
  - openConfirmWindow(type)
  - cancelProcessRequest()
  - processPopupRequest(strPageAnchor, strHref, windowName, strFeatures)
  - processPickerRequest(strPageAnchor, strHref, windowName, strFeatures)
  - confirmCancel()
  - confirmChildCancel()
  - confirmChildSave(strHref)
  - confirmLeave(strHref)
  - confirmBreadCrumbLeave(strHref)
  - confirmLogout()
  - saveAndEditNextChild(strHref)
  - saveAndAddAnotherChild(strHref)
  - selectFirstElement()

20. Spell Checker Utilities
  - checkSpelling()
  - closeSpellChecker()
  - popUpSpellCheckCompleteMessage()

21. Edit Utilities
  - processEdit()

22. Delete Utilities
  - processDelete()
  - processChildGridDelete(strPageAnchor, strHref, strGotoId)

23. Link Processing Utilities
  - navigateLink(strHref, newWindow)
  - processLinkRequest(strHref, jumpBackTitle, jumpBackLink)
  - confirmUnlink(strHref)
  - processUnlink(strHref)
  - relativeHREF(strHref)
  - normalizeHREF(strHref)

24. Attachment Processing Utilities
  - confirmDetachment(strHref)
  - processDetachment(strHref)

25. Table Sorting Utilities
  - createRowsArray(table)
  - insertSortedRows(table, sortRows)
  - insertReversedOrderRows(table, sortRows)
  - sortTable(table, sortFun, preSortFun)
  - idThisSortColumn(node)
  - refreshSortedTable(table)
  - refreshSortedTableRow(row, r)
  - sortTableASC(table, col) - Sort Data Types
  - sortTableDESC(table, col) - Sort Data Types
  - sortTableASCHidden(table, col) - Sort Data Types
  - sortTableDESCHidden(table, col) - Sort Data Types
  - sortTableASCNumerical(table, col) - Sort Data Types
  - sortTableDESCNumerical(table, col) - Sort Data Types
  - sortTableASCHiddenNumerical(table, col) - Sort Data Types
  - sortTableDESCHiddenNumerical(table, col) - Sort Data Types
  - sortTableASCLinkHref(table, col) - Sort Data Types
  - sortTableDESCLinkHref(table, col) - Sort Data Types
  - sortTableASCLinkText(table, col) - Sort Data Types
  - sortTableDESCLinkText(table, col) - Sort Data Types
  - sortRowsAlphaASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsAlphaCaseASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsAlphaDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsAlphaCaseDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsHiddenAlphaASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsHiddenAlphaCaseASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsHiddenAlphaDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsHiddenAlphaCaseDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsNumberASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsNumberDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsHiddenNumberASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsHiddenNumberDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsLinkASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsLinkCaseASC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsLinkDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES
  - sortRowsLinkCaseDESC(row1, row2) - Row Sorting Schemes - NOT INTENDED TO BE CALLED FROM ANY FUNCTION OTHER THAN THE SORT DATA TYPES

26. DOM Parsing Utilities
  - findBodyParent(node)
  - findTableParent(node)
  - findDivParent(node)
  - findRowParent(node)
  - findCellParent(node)
  - findFirstLinkChild(node)
  - findFirstSelectChild(node)
  - findFirstHiddenChild(node)
  - findFirstCheckboxChild(node)
  - findFirstRadiodialChild(node)
  - findFirstInputChild(node)
  - getTextNodes(node)
  - getFirstElementNodeValue(node, nodeName, tagName, type, attr)
  - rowNumber(node)

27. Table Formatting Utilities
  - mimicTable(masterTable, table)
  - equalizeTables()
  - equalizeTableObjects()
  - updateChildGridTotals()
  - synchronizeChildGridTotalScroll(childGrid)

28. Big Decimal Utilities
  - addBigDecimal(x, y)
  - subtractBigDecimal(x, y)
  - multiplyBigDecimal(x, y)
  - divideBigDecimal(x, y)
  - divideBigDecimalToScale(x, y, scale)

29. Admin App Utilities
  - setAdminModule(moduleName)
  - adminDynamicResize()
  - confirmLeaveInAdmin(strHref)
  - adminProcessDelete()
  - splitStringCheckDelimiter(astrOriginal, aDelimiter)
  - checkCarrot(astrElement)

30. Status Header Utilities
  - setStatusHeaderBIC(bic)
  - setStatusHeaderPriority(priority)
  - setStatusHeaderDescription(desc)
  - setStatusHeader(bic, priority, desc)

31. Schedule Header Utilties
  - setScheduleHeaderBIC(bic)
  - setScheduleHeaderPriority(priority)
  - setScheduleHeaderDescription(desc)
  - setScheduleHeader(bic, priority, desc)

32. Custom Field Utilties
  - setCheckboxValue(checkBox) {
  - popupCustomFieldDicionaryPicker(masterKey, customFieldID) {
  - setCustomFieldFromPicker(value) {
  - clearCustomFieldDictionary(customFieldID) {

------------- END Table of Contents ------------- */
// ------------------------------------------------------------
// global variables

// default status message
  window.defaultStatus = 'Primavera';

// Temporary variable for twistie width
// Used for subtwistie grids
  var twistiePlaceHolderWidth = 21;

// ------------------------------------------------------------
// ------------------------------------------------------------
// Set a reference to the utiltiesfrmae
// ---------------------------

  var UTILSFRAME = top.utilitiesframe;

  // we might be in a child window
  if ((UTILSFRAME == null) || (UTILSFRAME.name != "utilitiesframe")) {
    try{
      var parentWindow = window.top.opener;
      while (((UTILSFRAME == null) || (UTILSFRAME.name != "utilitiesframe")) && (parentWindow != null)) {
        UTILSFRAME = parentWindow.top.utilitiesframe;
        parentWindow = parentWindow.top.opener;
      }
    } catch(e) { displayError("utilities.js: initializing UTILSFRAME",e,DEBUGWARNING); }
  }

// ------------------------------------------------------------
// ------------------------------------------------------------
// Page Loading Progress
// ---------------------------

  // turn this off by setting the innerHTML of element id 'loadingpage' to ""
  var loadingPageMsg = "";
  var progressTIMEOUT = null;
  try { loadingPageMsg = UTILSFRAME.loadingPageMsg; } catch(uf) { loadingPageMsg = "Loading Page"; }
  if ((loadingPageMsg == null) || (loadingPageMsg == "")) loadingPageMsg = "Loading Page"
  if (window.name == "logframe" || window.name == "VIEWER" || (window.name == "" && location.search != "")) {
    window.status = loadingPageMsg.toLowerCase();
    document.write("<a name='progressindicator'></a>");
    document.write("<span id='loadingpage' style='visibility:hidden'><table height=100% width=100% border=0><tr height=100%><td class=\"processingtext\" width=100% align=center valign=center><img src=\"img/process_meter.gif\" border=0 id=\"progressimage\"><br><br>");
    document.write(loadingPageMsg);
    document.write("</td></tr></table></span>");
    progressTIMEOUT = setTimeout("gotoAnchor('progressindicator',false);document.getElementById('loadingpage').style.visibility='';", 1500); // visible is implied
  }

  // current triggers which also turn this off: setProjectTitle, unsetProjectTitle
  function clearProgressIndicator() {
    try {
      clearTimeout(progressTIMEOUT);

      window.status = '';

      var doc = top.logframe;
      if ((doc == null) || (doc == "undefined")) {
        doc = document;
      }
      else {
        doc = doc.document;
      }

      if (doc.getElementById('loadingpage') != null) {
        doc.getElementById('loadingpage').innerHTML="";
      }
    } catch(e) { displayError("utilities:clearProgressIndicator.",e,DEBUGALL); }
  } // ENDS clearProgressIndicator

// -- END Page Loading Progress --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Event Handling/Debugging Utilities
// ---------------------------

  // ** DO NOT CHANGE MASTERDEBUGLEVEL -- Production default 1
  var MASTERDEBUGLEVEL = 1;

  // override the MASTERDEBUGLEVEL with the debug level in the debug cookie
  var expeditionDebugCookie = "expedition_debug_level";
  var gotCookie = getCookie(expeditionDebugCookie);
  if (gotCookie != null) {
    MASTERDEBUGLEVEL = gotCookie;
    window.status = "master debug level set to "+MASTERDEBUGLEVEL;
  }

  // constants for debug level used to pass into displayError
  var DEBUGALL      = 4;  // Display all errors
  var DEBUGMODERATE = 3;  // Error may occur but should not
  var DEBUGWARNING  = 2;  // Error could occur dependent on special situation
  var DEBUGERROR    = 1;  // Must be a true error

  function displayError(msg, error, debugLevel) {
    if ((debugLevel == null) || (debugLevel == "")) debugLevel = 0;

    if (MASTERDEBUGLEVEL >= debugLevel) {
      msg += ":\n    ";
      if (error.name!=null) msg += error.name + "\n";
      if (error.message!=null) msg += "msg:" + error.message + " - ";
      if (error.number!=null) msg += "code:" + (error.number & 0xFFFF) + "\n";
      if (error.description!=null) msg += error.description;

      var errorMsg = "Error:";
      try { errorMsg = UTILSFRAME.errorMsg; } catch(uf) { errorMsg = "Error:"; }

      // developer tool needs to be alert
      alert(errorMsg+"\n  " + msg);
    }

    return true;
  } // ENDS displayError

  // our modal alert window
  var mAlertWindow
  var useJSAlert = false;
  var useAppletAlert = false;

  function warning(message) {
    var warningMsg = "";

    if (useJSAlert) {
      try { warningMsg = UTILSFRAME.warningMsg; } catch(uf) { warningMsg = "Warning:"; }
      message = warningMsg + "\n" + message;
    }

    expAlert(message, "", 0, 0, "showalerticon");
    return true;
  }

  function expAlert(message) {
    if (useJSAlert) {
      alert(message);
      return;
    }
    else if (useAppletAlert){
      UTILSFRAME.UtilitiesApplet.debugPopup(message);
      return;
    }

    // default height and width
    var height=150;
    var width=250;

    if ((arguments[2] != null) && (!isNaN(arguments[2])) && (arguments[2] > 0)) height = arguments[2];
    if ((arguments[3] != null) && (!isNaN(arguments[3])) && (arguments[3] > 0)) width = arguments[3];

    if ((!mAlertWindow) || (mAlertWindow.closed)) {
      var alertName = "ALERT";
      var strHref = "alertwindow.jsp?message=" + expEncode(replaceStringWithString(message, "\n", "<br>"));

      if ((arguments[4] != null) && (arguments[4] == "showalerticon")) {
        alertName = "WARNING";
        strHref = strHref + "&showalerticon=showalerticon";
      }

      if ((arguments[1] != null) && (arguments[1] != "")) {
        strHref = strHref + "&continueprocess="+arguments[1];
      }

      var strFeatures = "scrollbars=no,resizable=no,height="+height+",width="+width+","+centerWindow(width, height);

      mAlertWindow = window.open(strHref, alertName, strFeatures);
      if (mAlertWindow.opener == null) mAlertWindow.opener = self;
    }
    else {
      //don't open a new alert window if one already exsists
      mAlertWindow.focus();
    }
  } // ENDS expAlert

  // set our error handler
  if (MASTERDEBUGLEVEL <= DEBUGWARNING) {
    window.onerror = handleError;
  }

  function handleError(err, url, line) {
    if (MASTERDEBUGLEVEL >= DEBUGWARNING) {
      var errorMsg = "Error:";
      try { errorMsg = UTILSFRAME.errorMsg; } catch(uf) { errorMsg = "Error:"; }

      if (err.indexOf("is not defined") != -1) {
        // developer tool needs to be alert
        alert(errorMsg+"\n  item is not defined - \n  "+err+"\n  "+url+"\n  on line: "+line);
        return true;
      }
      else {
        // developer tool needs to be alert
        alert(errorMsg+"\n  error not handled - \n  "+err+"\n  "+url+"\n  on line: "+line);
        return false;
      }
    }
    else {
      return true;
    }
  } // ENDS handleError

  // report all HTML/DOM properties of an HTML Object
  function displayProperties(thisThing) {
    var showFull = false;
    if (arguments[1] != null && arguments[1] == "full") showFull = true;

    var properties = "";
    var i = 0;

    for (var property in thisThing) {
      var propertyValue = "thisThing."+property;
      try {
        propertyValue = eval(propertyValue);
      }
      catch(e) {
        propertyValue = "<error>";
      }
      if (!showFull && (""+propertyValue).length > 10) {
        propertyValue = (""+propertyValue).substring(0, 10)+"...";
      }
      properties+=property+" = "+propertyValue;
      if (i<=2) { properties+="     \t"; i++; }
      else { properties+="\n"; i=0; }
    }

    if (properties == "") {
      try {
        for (var i=0; i<thisThing.length; i++) {
          properties += "["+i+"] "+thisThing[i]+"\n";
        }
      }
      catch(e) { /* do nothing */ }
    }

    return properties;
  } // ENDS displayProperties

  // report all Form element name/value pairs for a given Form
  function displayFormElements(thisForm) {
    var report = "";
    var i = 0;
    for (var e = 0; e < thisForm.elements.length; e++) {
      report+=thisForm.elements[e].name+" = "+thisForm.elements[e].value;
      if (i<=2) { report+="     \t"; i++; }
      else { report+="\n"; i=0; }
    }
    return report
  } // ENDS displayFormElements

  // report the argument values and indexes
  function reportArguments(theArguments) {
    var results = "\n";
    for (var i=0;i<theArguments.length;i++) {
      results=results+"["+i+"] "+theArguments[i]+"\n";
    }
    return results;
  } // ENDS reportArguments

  var timerStart = "stopped";
  var timeReport = '';

  function startTimer() {
    if (timerStart == "stopped") {
      timerStart = ''+(new Date()).getTime()/1000;
      timeReport = '';
    }
    else timerStart = '{'+(new Date()).getTime()/1000+"}"+timerStart;
  }

  function stopTimer() {
    if (timerStart == "stopped") {
      // developer tool needs to be alert
      alert("Timer not started");
    }

    var lapped = '';
    var elapsedTime = '';
    if (timerStart.indexOf('{') != -1) {
      var laps = timerStart.indexOf('{');
      var lape = timerStart.indexOf('}');

      elapsedTime = timerStart.substring(laps+1,lape);
      lapped = timerStart.substring(lape+1)
    }

    if (elapsedTime == '') elapsedTime = timerStart;

    timeReport = timeReport + ((arguments[0] == null) ? "" : ((arguments[1] == null) ? "" : arguments[0])) + " time elapsed = " + (((new Date()).getTime()/1000) - elapsedTime).toFixed(2) + " secs {" + ((arguments[0] == null) ? "" : ((arguments[1] == null) ? arguments[0] : arguments[1])) + "} \n";

    if (lapped == '') timerStart = "stopped";
    else timerStart = lapped;

    if (timerStart == "stopped") {
      // developer tool needs to be alert
      alert("Time Report:"+"\n"+timeReport);
    }
  } // ENDS stopTimer

// -- END Event Handling Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Security Utilities
// ---------------------------

  var sessionId = "o,i81b4.u812?so[3mta3]";
  var expeditionCookie = "expedition_logged_on";

  if (top.window.name == "") {
    // window name is "" when entering the system not from the logon page
    // such as a hack or email link
    top.window.name = "VIEWER";
  }
  // developer tool needs to be alert
  //alert("(utilities) top.window.name = "+top.window.name);

  if (top.window.name == "LOGGEDOUT") {
    // we have logged out - don't go back to the logout page
    top.location.replace("logon.jsp");
  }

// -- End Security Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Browser and OS Utilities
// ---------------------------

  // *** browser and os detection from -
  // *** http://developer.netscape.com/docs/examples/javascript/browser_type_oo.html
  // convert all characters to lowercase to simplify testing
  var agt         = navigator.userAgent.toLowerCase();

  // ************************************************************************************
  // *** BROWSER VERSION ***
  // Note: On IE5, these return 4, so use is_ie5up to detect IE5.
  var is_major    = parseInt(navigator.appVersion);
  var is_minor    = parseFloat(navigator.appVersion);

  // Note: Opera and WebTV spoof Navigator.  We do strict client detection.
  // If you want to allow spoofing, take out the tests for opera and webtv.

  var is_major    = parseInt(navigator.appVersion);
  var is_minor    = parseFloat(navigator.appVersion);

  var is_nav      = ((agt.indexOf('mozilla') != -1) && (agt.indexOf('spoofer') == -1)
                    && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera') == -1)
                    && (agt.indexOf('webtv') == -1) && (agt.indexOf('hotjava') == -1));
  var is_nav2     = (is_nav && (is_major == 2));
  var is_nav3     = (is_nav && (is_major == 3));
  var is_nav4     = (is_nav && (is_major == 4));
  var is_nav4up   = (is_nav && (is_major >= 4));
  var is_navonly  = (is_nav && ((agt.indexOf(";nav") != -1) || (agt.indexOf("; nav") != -1)));
  var is_nav6     = (is_nav && (is_major == 5));
  var is_nav6up   = (is_nav && (is_major >= 5));
  var is_moz7     = (agt.indexOf('0.7') != -1)
  var is_gecko    = (agt.indexOf('gecko') != -1);

  var is_ie       = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
  var is_ie3      = (is_ie && (is_major < 4));
  var is_ie4      = (is_ie && (is_major == 4) && (agt.indexOf("msie 4")!=-1));
  var is_ie4up    = (is_ie && (is_major >= 4));
  var is_ie5      = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0")!=-1));
  var is_ie5up    = (is_ie && !is_ie3 && !is_ie4);
  var is_ie5_5    = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.5") !=-1));
  var is_ie5_5up  = (is_ie && !is_ie3 && !is_ie4 && !is_ie5);
  var is_ie6      = (is_ie && (is_major == 4) && (agt.indexOf("msie 6.")!=-1));
  var is_ie6up    = (is_ie && !is_ie3 && !is_ie4 && !is_ie5 && !is_ie5_5);

  // KNOWN BUG: On AOL4, returns false if IE3 is embedded browser
  // or if this is the first browser window opened.  Thus the
  // variables is_aol, is_aol3, and is_aol4 aren't 100% reliable.
  var is_aol      = (agt.indexOf("aol") != -1);
  var is_aol3     = (is_aol && is_ie3);
  var is_aol4     = (is_aol && is_ie4);
  var is_aol5     = (agt.indexOf("aol 5") != -1);
  var is_aol6     = (agt.indexOf("aol 6") != -1);

  var is_opera    = (agt.indexOf("opera") != -1);
  var is_opera2   = (agt.indexOf("opera 2") != -1 || agt.indexOf("opera/2") != -1);
  var is_opera3   = (agt.indexOf("opera 3") != -1 || agt.indexOf("opera/3") != -1);
  var is_opera4   = (agt.indexOf("opera 4") != -1 || agt.indexOf("opera/4") != -1);
  var is_opera5   = (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1);
  var is_opera5up = (is_opera && !is_opera2 && !is_opera3 && !is_opera4);

  var is_webtv    = (agt.indexOf("webtv") != -1);

  var is_TVNavigator = ((agt.indexOf("navio") != -1) || (agt.indexOf("navio_aoltv") != -1));
  var is_AOLTV    = is_TVNavigator;

  var is_hotjava  = (agt.indexOf("hotjava") != -1);
  var is_hotjava3 = (is_hotjava && (is_major == 3));
  var is_hotjava3up = (is_hotjava && (is_major >= 3));

  // ************************************************************************************
  // *** JAVASCRIPT VERSION CHECK ***
  var is_js;
  if (is_nav2 || is_ie3) is_js         = 1.0;
  else if (is_nav3) is_js              = 1.1;
  else if (is_opera5up) is_js          = 1.3;
  else if (is_opera) is_js             = 1.1;
  else if ((is_nav4 && (is_minor <= 4.05)) || is_ie4) is_js  = 1.2;
  else if ((is_nav4 && (is_minor > 4.05)) || is_ie5) is_js   = 1.3;
  else if (is_hotjava3up) is_js        = 1.4;
  else if (is_nav6 || is_gecko) is_js  = 1.5;
  // NOTE: In the future, update this code when newer versions of JS
  // are released. For now, we try to provide some upward compatibility
  // so that future versions of Nav and IE will show they are at
  // *least* JS 1.x capable. Always check for JS version compatibility
  // with > or >=.
  else if (is_nav6up) is_js            = 1.5;
  // NOTE: ie5up on mac is 1.4
  else if (is_ie5up) is_js             = 1.3

  // HACK: no idea for other browsers; always check for JS version with > or >=
  else is_js                           = 0.0;

  // ************************************************************************************
  // *** PLATFORM VERSION ***
  var is_win      = ((agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1));
  // NOTE: On Opera 3.0, the userAgent string includes "Windows 95/NT4" on all
  //        Win32, so you can't distinguish between Win95 and WinNT.
  var is_win95    = ((agt.indexOf("win95")!=-1) || (agt.indexOf("windows 95")!=-1));

  // is this a 16 bit compiled version?
  var is_win16    = ((agt.indexOf("win16")!=-1) ||
                    (agt.indexOf("16bit")!=-1) || (agt.indexOf("windows 3.1")!=-1) ||
                    (agt.indexOf("windows 16-bit")!=-1));

  var is_win31    = ((agt.indexOf("windows 3.1")!=-1) || (agt.indexOf("win16")!=-1) ||
                    (agt.indexOf("windows 16-bit")!=-1));

  var is_winme    = ((agt.indexOf("win 9x 4.90")!=-1));
  var is_win2k    = ((agt.indexOf("windows nt 5.0")!=-1));

  // NOTE: Reliable detection of Win98 may not be possible. It appears that:
  //       - On Nav 4.x and before you'll get plain "Windows" in userAgent.
  //       - On Mercury client, the 32-bit version will return "Win98", but
  //         the 16-bit version running on Win98 will still return "Win95".
  var is_win98    = ((agt.indexOf("win98")!=-1) || (agt.indexOf("windows 98")!=-1));
  var is_winnt    = ((agt.indexOf("winnt")!=-1) || (agt.indexOf("windows nt")!=-1));
  var is_winvista = ((agt.indexOf("windows nt 6.0")!=-1) || (navigator.appVersion.indexOf("windows nt 6.0")!=-1)) ;
  var is_win32    = (is_win95 || is_winnt || is_win98 ||
                    ((is_major >= 4) && (navigator.platform == "Win32")) ||
                    (agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1));

  var is_os2      = ((agt.indexOf("os/2")!=-1) ||
                    (navigator.appVersion.indexOf("OS/2")!=-1) ||
                    (agt.indexOf("ibm-webexplorer")!=-1));

  var is_mac      = (agt.indexOf("mac")!=-1);
  // hack ie5 js version for mac
  if (is_mac && is_ie5up) is_js = 1.4;
  var is_mac68k   = (is_mac && ((agt.indexOf("68k")!=-1) || (agt.indexOf("68000")!=-1)));
  var is_macppc   = (is_mac && ((agt.indexOf("ppc")!=-1) || (agt.indexOf("powerpc")!=-1)));

  var is_sun      = (agt.indexOf("sunos")!=-1);
  var is_sun4     = (agt.indexOf("sunos 4")!=-1);
  var is_sun5     = (agt.indexOf("sunos 5")!=-1);
  var is_suni86   = (is_sun && (agt.indexOf("i86")!=-1));
  var is_irix     = (agt.indexOf("irix") !=-1);    // SGI
  var is_irix5    = (agt.indexOf("irix 5") !=-1);
  var is_irix6    = ((agt.indexOf("irix 6") !=-1) || (agt.indexOf("irix6") !=-1));
  var is_hpux     = (agt.indexOf("hp-ux")!=-1);
  var is_hpux9    = (is_hpux && (agt.indexOf("09.")!=-1));
  var is_hpux10   = (is_hpux && (agt.indexOf("10.")!=-1));
  var is_aix      = (agt.indexOf("aix") !=-1);      // IBM
  var is_aix1     = (agt.indexOf("aix 1") !=-1);
  var is_aix2     = (agt.indexOf("aix 2") !=-1);
  var is_aix3     = (agt.indexOf("aix 3") !=-1);
  var is_aix4     = (agt.indexOf("aix 4") !=-1);
  var is_linux    = (agt.indexOf("inux")!=-1);
  var is_sco      = (agt.indexOf("sco")!=-1) || (agt.indexOf("unix_sv")!=-1);
  var is_unixware = (agt.indexOf("unix_system_v")!=-1);
  var is_mpras    = (agt.indexOf("ncr")!=-1);
  var is_reliant  = (agt.indexOf("reliantunix")!=-1);
  var is_dec      = ((agt.indexOf("dec")!=-1) || (agt.indexOf("osf1")!=-1) ||
                    (agt.indexOf("dec_alpha")!=-1) || (agt.indexOf("alphaserver")!=-1) ||
                    (agt.indexOf("ultrix")!=-1) || (agt.indexOf("alphastation")!=-1));
  var is_sinix    = (agt.indexOf("sinix")!=-1);
  var is_freebsd  = (agt.indexOf("freebsd")!=-1);
  var is_bsd      = (agt.indexOf("bsd")!=-1);
  var is_unix     = ((agt.indexOf("x11")!=-1) || is_sun || is_irix || is_hpux ||
                    is_sco ||is_unixware || is_mpras || is_reliant ||
                    is_dec || is_sinix || is_aix || is_linux || is_bsd || is_freebsd);

  var is_vms      = ((agt.indexOf("vax")!=-1) || (agt.indexOf("openvms")!=-1));

// -- End Browswer and OS Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// System Utilities
// ---------------------------

  // NOTE: this function does not support nested paramters within quotes
  function getURLParams(pName) {
    var urlLoc = location.search;

	if (arguments[1] != null) { // use a url location which is passed in
      urlLoc = arguments[1];
      urlLoc = urlLoc.substring(urlLoc.indexOf("?"));
      urlLoc = reverseFilter(urlLoc);
    }

    var query = urlLoc.charAt(0) == '?' ? urlLoc.substring(1) : urlLoc;
    var args = new Object();
    if (query) {
      var fields = query.split('&');
      for (var f = 0; f < fields.length; f++) {
        var field = fields[f].split('=');
        if ((field[0] != null) && (field[0] != '')) {
          if ((field[1] != null) && (field[1] != '')) {
            args[expDecode(field[0].replace(/\+/g,' '))] = expDecode(field[1].replace(/\+/g,' '));
          }
          else {
            args[expDecode(field[0].replace(/\+/g,' '))] = ''; // null
          }
        }
      }
    }

    // if no name/value pair is requested then return all name/value pairs
    if (arguments[0] == null || arguments[0] == "") return args;

    // if the name is in the arguments then return its value
    if (args[pName] != null)
    {
    	if( "custommessage" == pName )
    	{
    		return unescape(args[pName]);
    	}
    	return args[pName];
    }

    return "";
  } // ENDS getURLParams

  // NOTE: this function does not support nested paramters within quotes
  function setURLParams(pName, value) {
    var urlLoc = location.search;

    if (arguments[2] != null) { // use a url location which is passed in
      urlLoc = arguments[2];
      urlLoc = reverseFilter(urlLoc);
    }

    var startRip = urlLoc.indexOf("&"+pName);
    if (startRip == -1) {
      startRip = urlLoc.indexOf("?"+pName);
      if (startRip == -1) {
        return urlLoc+"&"+pName+"="+expEncode(value); // the parameter does not exist
      }
      else {
        startRip = startRip + 1;
      }
    }
    var endRip = urlLoc.indexOf("&", startRip+1);
    var cleanquery = urlLoc.substring(0,startRip)
    if (endRip > 0) {
      if (cleanquery.substring(cleanquery.length-1) == "?") {
        endRip = endRip + 1;
      }
      cleanquery = cleanquery + urlLoc.substring(endRip);
    }
    return cleanquery+"&"+pName+"="+expEncode(value);
  }

  function getStyleClass(className, attrib) {
    for (var s = 0; s < document.styleSheets.length; s++) {
      if (is_ie4up) {
        for (var r = 0; r < document.styleSheets[s].rules.length; r++)
          if (document.styleSheets[s].rules[r].selectorText == '.' + className)
            if (attrib == null || attrib == "") return document.styleSheets[s].rules[r].style;
            else return document.styleSheets[s].rules[r].style[attrib];
      } else if (document.getElementById) {
        for (var r = 0; r < document.styleSheets[s].cssRules.length; r++)
          if (document.styleSheets[s].cssRules[r].selectorText == '.' + className)
            if (attrib == null || attrib == "") return document.styleSheets[s].cssRules[r].style;
            else return document.styleSheets[s].cssRules[r].style[attrib];
      }
    }
    return null;
  } // ENDS getStyleClass

  function setStyleClassAttrib(className, attrib, value) {
    for (var s = 0; s < document.styleSheets.length; s++) {
      if (is_ie4up) {
        for (var r = 0; r < document.styleSheets[s].rules.length; r++)
          if (document.styleSheets[s].rules[r].selectorText == '.' + className)
            document.styleSheets[s].rules[r].style[attrib]=value;
      } else if (document.getElementById) {
        for (var r = 0; r < document.styleSheets[s].cssRules.length; r++)
          if (document.styleSheets[s].cssRules[r].selectorText == '.' + className)
            document.styleSheets[s].cssRules[r].style[attrib]=value;
      }
    }
  } // ENDS setStyleClassAttrib

  // set the scroll by paging up
  function pageUp() {
    try {
      window.scrollBy(0, window.innerHeight ? -window.innerHeight : -document.body.clientHeight);
    } catch(e) { displayError("utilities:pageUp.",e,DEBUGWARNING); }
  }

  // set the scroll by paging down
  function pageDown() {
    try {
      window.scrollBy(0, window.innerHeight ? window.innerHeight :  document.body.clientHeight);
    } catch(e) { displayError("utilities:pageDown.",e,DEBUGWARNING); }
  }

  // set the scroll to the top of the page
  // ------------------------------
  // there is 1 optional parameter
  // if the parameter is a number is used as an offset value, where the scroll is set to the top but down the amount of the offset
  // if the paramter is "home" then the scroll is set to the top and to the far left
  function scrollTop() {
    var topOffset = 0;
    var homePosition = ((is_ie) ? document.body.scrollLeft : window.pageYOffset);

    if (arguments[0] != null) {
      if (!isNaN(arguments[0])) topOffset = arguments[0];
      else if (arguments[0] == "home") homePosition = 0;
    }

    try {
      window.scrollTo(homePosition, 0+topOffset);
    } catch(e) { displayError("utilities:scrollTop.",e,DEBUGWARNING); }
  }

  // set the scroll to the bottom of the page
  // ------------------------------
  // there is 1 optional parameter
  // if the parameter is a number is used as an offset value, where the scroll is set to the bottom but up the amount of the offset
  // if the paramter is "home" then the scroll is set to the bottom and to the far left
  function scrollBottom() {
    var bottomOffset = 0;
    var homePosition = ((is_ie) ? document.body.scrollLeft : window.pageYOffset);

    if (arguments[0] != null) {
      if (!isNaN(arguments[0])) bottomOffset = arguments[0];
      else if (arguments[0] == "home") homePosition = 0;
    }

    try {
      window.scrollTo(homePosition, (document.height ? document.height : document.body.scrollHeight)-bottomOffset);
    } catch(e) { displayError("utilities:scrollBotton.",e,DEBUGWARNING); }
  }

  // first argument is the id of the element which called the halt
  // second argument is the message to display when the action is tried again (this should always be passed in)
  // go thru the remaining arguments (presumed to be associated buttons or links)
  // set the halted attribute of the element and set the appropriate attributes
  // to a halted state
  function haltActions() {
    try {
      if (arguments.length < 2) return; // must have at least 2 arguments

      trigger = document.getElementById(arguments[0]);
      isButton = trigger.type == "button"; // or a link

      actionerror = arguments[1];

      if (actionerror=="") try { actionerror = UTILSFRAME.haltActionsErrorMsg; } catch(uf) { actionerror = "processing... please wait."; } // the default text which can not be localized

      if (isButton) {
        disabledBColor = getStyleClass('disabledbutton', 'color');
      }
      else {
        disabledLColor = getStyleClass('disabled', 'color'); // is a link
      }

      trigger.halted = "halted";
      trigger.style.cursor = "default";
      trigger.actionerror = actionerror;

      trigger.oldcolor = trigger.style.color;
      if (isButton) {
        trigger.style.color = disabledBColor;
      }
      else {
        trigger.style.color = disabledLColor; // is a link
      }

      if ((trigger.href != null) && (trigger.href != "undefined")) {
        trigger.oldhref = trigger.href;
        trigger.href = "javascript:void 0;";
      }

      if ((trigger.onclick != null) && (trigger.onclick != "undefined")) {
        trigger.oldonclick = trigger.onclick;
        trigger.onclick = attemptedAction;
      }

      if ((trigger.title != null) && (trigger.title != "undefined")) {
        trigger.oldtitle = trigger.title;
        trigger.title = actionerror;
      }

      if ((trigger.alt != null) && (trigger.alt != "undefined")) {
        trigger.oldalt = trigger.alt;
        trigger.alt = actionerror;
      }

      if ((trigger.onmouseover != null) && (trigger.onmouseover != "undefined")) {
        trigger.oldonmouseover = trigger.onmouseover;
        trigger.onmouseover = captureActionMouseOver;
      }

      for (i=2; i<arguments.length; i++) {
        nextElement = document.getElementById(arguments[i]);

        try {
          nextElement.halted = "halted";
          nextElement.style.cursor = "default";
          nextElement.actionerror = actionerror;

          nextElement.oldcolor = nextElement.style.color;
          if (nextElement.type == "button") {
            nextElement.style.color = disabledBColor;
          }
          else {
            nextElement.style.color = disabledLColor; // is a link
          }

          if ((nextElement.href != null) && (nextElement.href != "undefined")) {
            nextElement.oldhref = nextElement.href;
            nextElement.href="javascript:void 0;";
          }

          if ((nextElement.onclick != null) && (nextElement.onclick != "undefined")) {
            nextElement.oldonclick = nextElement.onclick;
            nextElement.onclick = disabledAction;
          }

          if ((nextElement.title != null) && (nextElement.title != "undefined")) {
            nextElement.oldtitle = nextElement.title;
            nextElement.title = actionerror;
          }

          if ((nextElement.alt != null) && (nextElement.alt != "undefined")) {
            nextElement.oldalt = nextElement.alt;
            nextElement.alt = actionerror;
          }

          if ((nextElement.onmouseover != null) && (nextElement.onmouseover != "undefined")) {
            nextElement.oldonmouseover = nextElement.onmouseover;
            nextElement.onmouseover = captureActionMouseOver;
          }
        } catch(skipit) { /* if the id element doesn't exist - skip it */ }
      }
    } catch(e) { displayError("utilities:haltActions.",e,DEBUGWARNING); }
  } // ENDS haltActions

  // displays the action message when there are multiple attempts
  function attemptedAction() {
    if ((this.actionerror != null) && (this.actionerror != "undefined")) {
      useAppletAlert = true; // either we use the javascript alert or the applet alert
      warning(this.actionerror); // we really need to pause the code execution
      useAppletAlert = false; // set back to default value
    }
    return false;
  }

  // the disabled action
  function disabledAction() {
    window.status = "";
    return false;
  }

  // displays action message
  function captureActionMouseOver() {
    if ((this.actionerror != null) && (this.actionerror != "undefined")) {
      window.status = this.actionerror;
    }
    else {
      window.status = "";
    }
    return true;
  } // ENDS captureActionMouseOver

  // go thru the given document elements (presumed to be buttons or links) and resets
  // where appropriate (indicated by the halted attribute of the element)
  // the appropriate attributes back to what they were originally set to
  function resumeActions() {
    try {
      for (i=0; i<arguments.length; i++) {
        nextElement = document.getElementById(arguments[i]);

        if (nextElement != null) {
          isButton = nextElement.type == "button"; // or a link

          if (nextElement.halted == "halted") {
            nextElement.style.color = nextElement.oldcolor;
            nextElement.oldcolor = null;

            if ((nextElement.oldhref != null) && (nextElement.oldhref != "undefined")) {
              nextElement.href = nextElement.oldhref;
              nextElement.href = null;
            }

            if ((nextElement.oldonclick != null) && (nextElement.oldonclick != "undefined")) {
              nextElement.onclick = nextElement.oldonclick;
              nextElement.oldonclick = null;
            }

            if ((nextElement.oldtitle != null) && (nextElement.oldtitle != "undefined")) {
              nextElement.title = nextElement.oldtitle;
              nextElement.oldtitle = null;
            }

            if ((nextElement.oldalt != null) && (nextElement.oldalt != "undefined")) {
              nextElement.alt = nextElement.oldalt;
              nextElement.oldalt = null;
            }

            if ((nextElement.oldonmouseover != null) && (nextElement.oldonmouseover != "undefined")) {
              nextElement.onmouseover = nextElement.oldonmouseover;
              nextElement.oldonmouseover = null;
            }

            nextElement.actionerror = null;
            nextElement.style.cursor = "hand"
            nextElement.halted = null;
          }
        }
      }
    } catch(e) { displayError("utilities:resumeActions.",e,DEBUGMODERATE); }
  } // ENDS resumeActions

// -- End System Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// TextArea and Input Field Utilities
// ---------------------------

  function setSelectionRange(input, selectionStart, selectionEnd) {
    if (input.createTextRange) {
      var range = input.createTextRange();
      range.collapse(true);
      range.moveEnd('character', selectionEnd);
      range.moveStart('character', selectionStart);
      range.select();
    }
  //  else { // NOT YET IN NS6
  //    if (input.setSelectionRange) {
  //      input.focus();
  //      input.setSelectionRange(selectionStart, selectionEnd);
  //    }
  //  }
  } // ENDS setSelectionRange

  function setCaretToEnd(input) {
    setSelectionRange(input, input.value.length, input.value.length);
  }

  function setCaretToBegin(input) {
    setSelectionRange(input, 0, 0);
  }

  function setCaretToPos(input, pos) {
    setSelectionRange(input, pos, pos);
  }

  function selectString(input, string) {
    if (input == "") return;
    var match = new RegExp(string, "i").exec(input.value);
    if (match) {
      setSelectionRange(input, match.index, match.index + match[0].length);
    }
  } // ENDS selectString

  function replaceSelection(input, replaceString) {
    if (document.selection) {
      var range = document.selection.createRange();
      if (range.parentElement() == input) {
        var isCollapsed = range.text == '';
        range.text = replaceString;
        if (!isCollapsed)  { // reselect the replaced selection
          range.moveStart('character', -replaceString.length);
          range.select();
        }
      }
    }
  //  else { // NOT YET IN NS6
  //    if (input.setSelectionRange) {
  //      var selectionStart = input.selectionStart;
  //      var selectionEnd = input.selectionEnd;
  //      input.value = input.value.substring(0, selectionStart)
  //                    + replaceString
  //                    + input.value.substring(selectionEnd);
  //      if (selectionStart != selectionEnd) // has there been a selection
  //        setSelectionRange(input, selectionStart, selectionStart + replaceString.length);
  //      else // set caret
  //        setCaretToPos(input, selectionStart + replaceString.length);
  //    }
  //  }
  } // ENDS replaceSelection

  // need to check & enforce limit here in case user pastes data into a fields
  function enforceLimit(fieldObj) {
    var charLimit = 500; // default
    if (arguments[1] == null) {
      try {
        charLimit = fieldObj.maxlength;
        if (charLimit==null) {
          charLimit = fieldObj.maxLength;
        if (charLimit==null) {
          charLimit = fieldObj.MAXLENGTH;
        if (charLimit==null) {
          charLimit = fieldObj.rows * fieldObj.cols
        if (charLimit==null) {
          charLimit = 500; // everything else failed
        }}}}
      }
      catch(e5) {
        charLimit = 500; // default
      }
    }
    else {
      charLimit = arguments[1];
    }

    // special check for multibyte characters in Oracle
    var fieldText = fieldObj.value;
    var truncFieldText = "";
    var maxSafeOracleChars = 1333;
    // now check the byte length
    if ((UTILSFRAME != null) && (UTILSFRAME.DBInUSE == "ORACLE") && (charLimit >= maxSafeOracleChars) && (fieldText.length >= maxSafeOracleChars)) {
      truncFieldText = UTILSFRAME.UtilitiesApplet.truncateDBFieldText(fieldText, UTILSFRAME.DBInUSE);

      if (fieldText.length > truncFieldText.length) charLimit = truncFieldText.length;
    }

    //window.status="(enforce) fieldText.length => "+ fieldText.length + "       truncFieldLength => "+truncFieldText.length+"     charLimit => "+charLimit;

    if (fieldText.length > charLimit) {
      setFormDirty(); // force the dirty flag

      var excess = fieldObj.value.length - charLimit;
      fieldObj.value = fieldObj.value.substring(0, charLimit);
      if (inserting) {
        inserting = false;
        try { uiAlert = false; } catch(a) { /* do nothing */ }
        return;
      }

      var alertMsg = "";
      var arr = new Array();
      arr[0] = charLimit;
      arr[1] = excess;
      try { alertMsg = UTILSFRAME.enforceTextAreaLimitExceededMsg; } catch(uf) { alertMsg = "The pasted text has exceeded the ~ character limit of this field. We have trimmed the excess ~ characters."; }
      alertMsg = populateMessage(alertMsg, arr);

      //if (!uiAlert) expAlert(alertMsg);
      expAlert(alertMsg);

      try { uiAlert = true; } catch(a) { /* do nothing */ }
    }
    else {
      try { uiAlert = false; } catch(a) { /* do nothing */ }
    }
  } // ENDS enforceLimit

  var insertMode = false; // master switch variable
  var inserting = false; // functional variable

  // limit typing of text into a field
  function limitText(fieldObj, sysEvent) {
    var charLimit = 500; // default
    if (arguments[2] == null) {
      try {
        charLimit = fieldObj.maxlength;
        if (charLimit==null) {
          charLimit = fieldObj.maxLength;
        if (charLimit==null) {
          charLimit = fieldObj.MAXLENGTH;
        if (charLimit==null) {
          charLimit = fieldObj.rows * fieldObj.cols
        if (charLimit==null) {
          charLimit = 500; // everything else failed
        }}}}
      }
      catch(e5) {
        charLimit = 500; // default
      }
    }
    else {
      charLimit = arguments[2];
    }

    var result = true;

    allowKey = false;
    var keyCode = sysEvent.keyCode;
    var controlKey = sysEvent.ctrlKey ? true : false;

    // the insert key was pressed
    if (keyCode == 45) {
      insertMode = !insertMode;
      inserting = insertMode;
    }

    // if inserting has been turned off, use of the left or up arrow key turns inserting back on
    if ((keyCode == 37 || keyCode == 38) && insertMode) {
      inserting = true;
    }

    // keyCode less then "0" and not "enter" and not "space" or control key down and not paste
    if ((keyCode < 48 && keyCode != 13 && keyCode != 32) || (controlKey && keyCode != 86) || inserting) {
      allowKey = true;
    }

    // we are pasting while in insertMode - we want the enforceLimit message to display if we go over
    if (insertMode && controlKey && keyCode == 86) {
      inserting = false;
    }

    // special check for multibyte characters in Oracle
    var fieldText = fieldObj.value;
    var truncFieldText = "";
    var maxSafeOracleChars = 1333;

    // now check the byte length
    if ((UTILSFRAME != null) && (UTILSFRAME.DBInUSE == "ORACLE") && (charLimit >= maxSafeOracleChars) && (fieldText.length >= maxSafeOracleChars)) {
      truncFieldText = UTILSFRAME.UtilitiesApplet.truncateDBFieldText(fieldText+"~", UTILSFRAME.DBInUSE, "reachLimit");

      if (truncFieldText == "~limitReached~") result = false;
    }

    //window.status="(limit) fieldText.length => "+fieldText.length+"       truncFieldLength => "+truncFieldText.length+"     charLimit => "+charLimit;

    if (allowKey) result = true;

    sysEvent.returnValue = result;

    if (!result) setFormDirty(); // force the dirty flag

    return result;
  } // ENDS limitText

  // if inserting has been turned off, a click will change the cursor position - so, turn inserting back on
  function newCursorPos() {
    if (insertMode) {
      inserting = true;
    }
  }

// -- TextArea and Input Field Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Date Utilities
// ---------------------------

  // Set Calendar localized date format -- this will be moved to the Edit JSP when we localize
  var calendarCodeLoaded;

  try {
    calendarCodeLoaded = calendarCodeInUse;
  }
  catch(calendarcodenotloaded) {
    calendarCodeLoaded = false;
  }

  if (calendarCodeLoaded) {
    gLocalizedReturnDateFormat = "DD-MON-YY";
    setCalendarDefaults(); // set the gLocalized Calendar variables
  }

  var datePickerHover = false;

  function checkDate(dateFld) {
    // param: dateFld : the id of the date field.
    // param: blind: display the invalid date error
    // param: required: display error when date is empty
    // param: p_format: return date format

    if (!isDate(dateFld, arguments[2], arguments[3])) {
      var display = true;
      var required = false;

      if (arguments[1] != null) {
        display = !eval(arguments[1] == "blind");
      }

      if (arguments[2] != null) {
        required = eval(arguments[2] == "required");
      }

      if (display || (required && display)) {
        document.getElementById(dateFld).select();

        var requiredMsg = "";
        if (required) {
          try { requiredMsg = UTILSFRAME.datePickerRequiredMsg; } catch(uf) { requiredMsg = "\n\nThe date is required."; }
        }

        var alertMsg = "";
        try { alertMsg = UTILSFRAME.getDatePickerReviewMsg(); } catch(uf) { alertMsg = "Please review this date. ~ \n\nDates should be entered in one of the following formats:\n\n\xB0 dd-Mmm-yy    (Example: 4-Apr-02)\n\xB0 dd-Mmm-yyyy    (Example: 4-Apr-2002)\n\xB0 mm/dd/yy    (Example: 4/7/02)\n\xB0 mm/dd/yyyy    (Example: 4/7/2002)"; }
        alertMsg = replaceStringWithString(alertMsg, "~", requiredMsg);

        //if (!uiAlert) expAlert(alertMsg);
        expAlert(alertMsg);

        try { uiAlert = true; } catch(a) { /* do nothing */ }

        return false; // kill thread
      }
      else {
        try { uiAlert = false; } catch(a) { /* do nothing */ }

        document.getElementById("save_"+dateFld).value = "";
        document.getElementById(dateFld).value = "";
      }

      // returns cursor control to the text field object
      try { document.getElementById(dateFld).focus(); } catch(nofocus) { /* do nothing */ }
    }
    else {
      try { uiAlert = false; } catch(a) { /* do nothing */ }

      return true;
    }
  } // ENDS checkDate

  // Populate a Custom Field Date
  function populateCFDate() {
    setFormDirty();

    if (arguments.length==3) {
      document.getElementById("save_"+arguments[2]).value=arguments[0];
      document.getElementById(arguments[2]).value=arguments[1];
    }
    else if (arguments.length==4) {
      document.getElementById("save_"+arguments[3]).value=arguments[0];
      document.getElementById(arguments[3]).value=arguments[1];

      // possible future alternate custom date field
      //document.getElementById("alt_"+arguments[3]).value=arguments[2];
    }
  }

  function popUpCalendar() {
    // parameter format - dateFormElementId,dateFormat,altFormat,cfItem
    // !!! NOTE: it is assumed that if the "cfItem" (optional date field for Custom data section) is populated,
    // !!!       then the "alt..." parameters ARE NOT populated. This is because there is only one date field
    // !!!       in the custom data section.

    var dateValue = document.getElementById("save_"+arguments[0]).value;

    show_calendar(arguments[1], dateValue, arguments[2], arguments[3], arguments[4]);
  } // ENDS popUpCalendar

// -- End Date Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Header Utilities
// ---------------------------

  function setProjectTitle(projectName) {
    if (arguments[1] == null || (arguments[1] != null && (arguments[1] == "" || arguments[1] == "clear"))) {
      // clear the progress indicator
      clearProgressIndicator();
    }

    try {
      var breakout = top.headerframe;
      top.headerframe.document.getElementById('projecttitle').innerHTML=projectName;
    } catch(e) { if (breakout!=null) displayError("utilities:setProjectTitle.",e,DEBUGMODERATE); }
  }

  function unsetProjectTitle() {
    if ((arguments[1] == null) || ((arguments[1] != null) && ((arguments[1] == "") || (arguments[1] == "clear")))) {
      // clear the progress indicator
      clearProgressIndicator();
    }

    try {
      var breakout = top.headerframe;
      top.headerframe.document.getElementById('projecttitle').innerHTML=top.headerframe.welcome;
    } catch(e) { if (breakout!=null) displayError("utilities:unsetProjectTitle.",e,DEBUGWARNING); }
  }

  function showTransQueue() {
    try {
      var breakout = top.headerframe;
      top.headerframe.showTransQueue();
    } catch(e) { if (breakout!=null) displayError("utilities:showTransQueue.",e,DEBUGMODERATE); }
  }

  function showChangeGroup() {
    try {
      var breakout = top.headerframe;
      top.headerframe.showChangeGroup();
    } catch(e) { if (breakout!=null) displayError("utilities:showChangeGroup.",e,DEBUGMODERATE); }
  }

  // hides both trans queue and change group
  function clearHeaderActions() {
    try {
      var breakout = top.headerframe;
      top.headerframe.clearHeaderActions();
    } catch(e) { if (breakout!=null) displayError("utilities:clearHeaderActions.",e,DEBUGWARNING); }
  }

  function showHelp(aHelpUrl) {
    if (aHelpUrl == null || aHelpUrl == "") aHelpUrl = "expwin.htm";
    strFeatures = "scrollbars=yes,resizable=yes,width=740,height=460," + positionWindow(740, 460, "topleft");
    aHelpUrl = "help/" + aHelpUrl;
    window.open(aHelpUrl, 'HELP', strFeatures);
  }

  function setHelpUrl(aHelpUrl) {
    try {
      var breakout = top.headerframe;
      top.headerframe.helpUrl = aHelpUrl;
    } catch(e) { if (breakout!=null) displayError("utilities:setHelpUrl.",e,DEBUGMODERATE); }
  }

  function setSysItemType(aSysItemType) {
    try {
      var breakout = top.headerframe;
      top.headerframe.strSysItemType = aSysItemType;
      top.headerframe.bDocumentFrameChanged = true;
    } catch(e) { if (breakout!=null) displayError("utilities:setSysItemType.",e,DEBUGMODERATE); }
  }

  function unsetSysItemType() {
    try {
      var breakout = top.headerframe;
      top.headerframe.strSysItemType = '';
      top.headerframe.bDocumentFrameChanged = true;
    } catch(e) { if (breakout!=null) displayError("utilities:unsetSysItemType.",e,DEBUGWARNING); }
  }

  function getSysItemType() {
    try {
      var breakout = top.headerframe;
      return top.headerframe.strSysItemType;
    } catch(e) { if (breakout!=null) displayError("utilities:getSysItemType.",e,DEBUGWARNING); }
  }

  function setTransmittalQueueCount(count) {
    try {
      var breakout = top.headerframe;
      top.headerframe.setTransmittalQueueCount(count);
    } catch(e) { if (breakout!=null) displayError("utilities:setTransmittalQueueCount.",e,DEBUGWARNING); }
  }

// -- End Header Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Anchor Utilities
// ---------------------------

  function debugHiddenFrame() {
    try {
      rows = (top.document.getElementById('layoutframeset').rows).split(",");
      rows[3] = 50;
      top.document.getElementById('layoutframeset').rows = rows;
    } catch(e) { alert("error calling debug on debugHiddenFrame"); } // developer tool needs to be alert
  }

  function debugUtilitiesFrame() {
    try {
      rows = (top.document.getElementById('layoutframeset').rows).split(",");
      rows[4] = 20;
      top.document.getElementById('layoutframeset').rows = rows;
    } catch(e) { alert("error calling debug on debugUtilitiesFrame"); } // developer tool needs to be alert
  }

  function debugSpellcheckerFrame() {
    try {
      rows = (top.document.getElementById('layoutframeset').rows).split(",");
      rows[5] = 20;
      top.document.getElementById('layoutframeset').rows = rows;
    } catch(e) { alert("error calling debug on debugSpellcheckerFrame"); } // developer tool needs to be alert
  }

  function debugPreferencesFrame() {
    try {
      rows = (top.document.getElementById('layoutframeset').rows).split(",");
      rows[6] = 180;
      top.document.getElementById('layoutframeset').rows = rows;
    } catch(e) { alert("error calling debug on debugPreferencesFrame"); } // developer tool needs to be alert
  }

  //layoutframeset -
  //  headerframe
  //  anchorframe
  //  bodyframeset
  //  hiddenframe
  //  utilitiesframe
  //  spellcheckerframe
  //  preferencesframe

  function showAnchorFrame() {
    try {
      var breakout = top.document.getElementById('layoutframeset');
      top.document.getElementById('layoutframeset').rows = '66,64,*,0,0,0,0';
      top.treeframe.closeFindFrame();
    } catch(e) { if (breakout!=null) displayError("utilities:showAnchorFrame.",e,DEBUGMODERATE); }
  }

  function hideAnchorFrame() {
    try {
      var breakout = top.document.getElementById('layoutframeset');
      top.document.getElementById('layoutframeset').rows = '66,0,*,0,0,0,0';
    } catch(e) { if (breakout!=null) displayError("utilities:hideAnchorFrame.",e,DEBUGMODERATE); }
  }

  function setModuleName(moduleName) {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('modulename').innerHTML=moduleName;
    } catch(e) { if (breakout!=null) displayError("utilities:setModuleName.",e,DEBUGMODERATE); }
  }

  function setModuleNameSuffix(moduleNameSuffix) {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('modulenamesuffix').innerHTML=moduleNameSuffix;
    } catch(e) { if (breakout!=null) displayError("utilities:setModuleNameSuffix.",e,DEBUGMODERATE); }
  }

  function getModuleName() {
    try {
      var breakout = top.anchorframe;
      return top.anchorframe.document.getElementById('modulename').innerHTML;
    } catch(e) { if (breakout!=null) displayError("utilities:getModuleName.",e,DEBUGMODERATE); }
  }

  function unsetModuleName() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('modulename').innerHTML="";
    } catch(e) { if (breakout!=null) displayError("utilities:unsetModuleName.",e,DEBUGWARNING); }
  }

  function unsetModuleNameSuffix() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('modulenamesuffix').innerHTML="";
    } catch(e) { if (breakout!=null) displayError("utilities:unsetModuleNameSuffix.",e,DEBUGWARNING); }
  }

  function pushBreadCrumb(crumb, crumbLink) {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.setBreadCrumb(crumb, crumbLink);
    } catch(e) { if (breakout!=null) displayError("utilities:pushBreadCrumb.",e,DEBUGMODERATE); }
  }

  function clearBreadCrumb() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.clearBreadCrumb();
    } catch(e) { if (breakout!=null) displayError("utilities:clearBreadCrumb.",e,DEBUGWARNING); }
  }

  function setJumpBack(jumpBackTitle, jumpBackLink) {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.setJumpBack(jumpBackTitle, jumpBackLink);
    } catch(e) { if (breakout!=null) displayError("utilities:setJumpBack.",e,DEBUGWARNING); }
  }

  // This will set/substitute the master key in the jumpback link
  function setJumpBackMasterKey(jumpBackMasterKey) {
    try {
      var breakout = top.anchorframe;
      var jumpBackLink = top.anchorframe.getJumpBackLink();

      var strHrefPre = jumpBackLink.substring(0,jumpBackLink.indexOf("masterkey=")+10);
      jumpBackLink = jumpBackLink.substring(jumpBackLink.indexOf("masterkey=")+10);
      var strHrefPost = "";
      if (jumpBackLink.indexOf("&") != -1) {
        strHrefPost = jumpBackLink.substring(jumpBackLink.indexOf("&"));
      }
      top.anchorframe.setJumpBackLink(strHrefPre+jumpBackMasterKey+strHrefPost);
    } catch(e) { if (breakout!=null) displayError("utilities:setJumpBackMasterKey.",e,DEBUGWARNING); }
  }

  //New function for clearing CM Jumpbacks.
  function clearCMJumpBack() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.clearCMJumpBack();
    } catch(e) { if (breakout!=null) displayError("utilities:clearCMJumpBack.",e,DEBUGWARNING); }
  }

  function clearJumpBack() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.clearJumpBack();
    } catch(e) { if (breakout!=null) displayError("utilities:clearJumpBack.",e,DEBUGWARNING); }
  }

  function showExpansion() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('expansion').style.visibility = ""; // visible is implied
    } catch(e) { if (breakout!=null) displayError("utilities:showExpansion.",e,DEBUGMODERATE); }

    resumeActions("expandall", "collapseall");
  }

  function hideExpansion() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('expansion').style.visibility = "hidden";
    } catch(e) { if (breakout!=null) displayError("utilities:hideExpansion.",e,DEBUGWARNING); }
  }

  function showSelection() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('selection').style.visibility = ""; // visible is implied
    } catch(e) { if (breakout!=null) displayError("utilities:showSelection.",e,DEBUGMODERATE); }

    resumeActions("selectall", "unselectall");
  }

  function hideSelection() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.document.getElementById('selection').style.visibility = "hidden";
    } catch(e) { if (breakout!=null) displayError("utilities:hideSelection.",e,DEBUGWARNING); }
  }

  function setAnchorActions() {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.setAnchorActions(arguments); // this will pass the arguments array as 1 object
    } catch(e) { if (breakout!=null) displayError("utilities:setAnchorActions.",e,DEBUGMODERATE); }
  } // ENDS setAnchorActions

  function setAnchorButtonStates(astrButtonNames, astrButtonStates) {
    try {
      var breakout = top.anchorframe;
      top.anchorframe.setAnchorButtonStates(astrButtonNames, astrButtonStates);
    } catch(e) { if (breakout!=null) displayError("utilities:setAnchorButtonStates.",e,DEBUGMODERATE); }
  }

  var anchorLinks="";
  var anchorImages="";
  var anchorNames="";

  // clicking the anchor link will blind expand the related section before going to the section
  var anchorTwistieState="";
  var anchorTwistieUpdateFunctionName="";

  function addAnchor(type) {
    if (type=="custom") {
      anchorLinks+="anchor_custom~";
      anchorImages+="img/anchor_custom.gif~";
      try { anchorNames+=UTILSFRAME.customFieldsAnchorName+"~"; } catch(uf) { anchorNames+="custom fields~"; }

      anchorTwistieState+="customExpanded~";
      anchorTwistieUpdateFunctionName+="updateCustom()~";
    }
    else if (type=="costing") {
      anchorLinks+="anchor_costing~";
      anchorImages+="img/anchor_costing.gif~";
      try { anchorNames+=UTILSFRAME.costingAnchorName+"~"; } catch(uf) { anchorNames+="costing~"; }

      anchorTwistieState+="costingExpanded~";
      anchorTwistieUpdateFunctionName+="updateCosting()~";
    }
    else if (type=="issue") {
      anchorLinks+="anchor_issue~";
      anchorImages+="img/anchor_issue.gif~";
      try { anchorNames+=UTILSFRAME.issuesAnchorName+"~"; } catch(uf) { anchorNames+="issues~"; }

      anchorTwistieState+="issueExpanded~";
      anchorTwistieUpdateFunctionName+="updateIssue()~";
    }
    else if (type=="attachment") {
      anchorLinks+="anchor_attachment~";
      anchorImages+="img/anchor_attachment.gif~";
      try { anchorNames+=UTILSFRAME.attachmentsAnchorName+"~"; } catch(uf) { anchorNames+="attachments~"; }

      anchorTwistieState+="attachmentExpanded~";
      anchorTwistieUpdateFunctionName+="updateAttachment()~";
    }
    else if (type=="activity") {
      anchorLinks+="anchor_activity~";
      anchorImages+="img/anchor_activity.gif~";
      try { anchorNames+=UTILSFRAME.scheduleAnchorName+"~"; } catch(uf) { anchorNames+="schedule~"; }

      anchorTwistieState+="scheduleExpanded~";
      anchorTwistieUpdateFunctionName+="updateSchedule()~";
    }
    else if (type=="contractsummary") {
      anchorLinks+="anchor_contractsummary~";
      anchorImages+="img/anchor_contractsummary.gif~";
      try { anchorNames+=UTILSFRAME.contractSummaryAnchorName+"~"; } catch(uf) { anchorNames+="contract summary~"; }

      anchorTwistieState+="contractsummaryExpanded~";
      anchorTwistieUpdateFunctionName+="updateContractSummary()~";
    }
    else if (type=="lineitems") {
      anchorLinks+="anchor_lineitems~";
      anchorImages+="img/anchor_lineitems.gif~";
      try { anchorNames+=UTILSFRAME.lineItemsAnchorName+"~"; } catch(uf) { anchorNames+="line items~"; }

      anchorTwistieState+="lineitemsExpanded~";
      anchorTwistieUpdateFunctionName+="updateLineItems()~";
    }
    else if (type=="details") {
      anchorLinks+="anchor_details~";
      anchorImages+="img/anchor_details.gif~";
      try { anchorNames+=UTILSFRAME.detailsAnchorName+"~"; } catch(uf) { anchorNames+="details~"; }

      anchorTwistieState+="detailsExpanded~";
      anchorTwistieUpdateFunctionName+="updateDetails()~";
    }
  } // ENDS addAnchor

  function addSpecialAnchor(link, image, anchorName, twistStateName, twistUpdFuncName) {
    anchorLinks+=link+"~";
    anchorImages+=image+"~";
    anchorNames+=anchorName+"~";

    anchorTwistieState+=twistStateName+"~";
    anchorTwistieUpdateFunctionName+=twistUpdFuncName+"~";
  }

  function setAnchors() {
    // only set the anchors if some were added
    if (anchorLinks != "") {
      // remove the trailing ~ from each of the arrays
      anchorLinks = anchorLinks.substring(0,anchorLinks.length-1);
      anchorImages = anchorImages.substring(0,anchorImages.length-1);
      anchorNames = anchorNames.substring(0,anchorNames.length-1);

      // clicking the anchor link will blind expand the related section before going to the section
      anchorTwistieState = anchorTwistieState.substring(0, anchorTwistieState.length-1);
      anchorTwistieUpdateFunctionName = anchorTwistieUpdateFunctionName.substring(0, anchorTwistieUpdateFunctionName.length-1);

      if ((arguments != null) && (arguments[0] == "child")) {
        setDetailAnchors(anchorLinks, anchorImages, anchorNames, anchorTwistieState, anchorTwistieUpdateFunctionName);
      }
      else {
        setAnchorActions(anchorLinks, anchorImages, anchorNames, anchorTwistieState, anchorTwistieUpdateFunctionName);
      }
    }
    else {
      // if we are here then lets to a clean up
      unsetAnchors();
    }
  } // ENDS setAnchors

  function unsetAnchors() {
    anchorLinks="";
    anchorImages="";
    anchorNames="";

    // clicking the anchor link will blind expand the related section before going to the section
    anchorTwistieState="";
    anchorTwistieUpdateFunctionName="";

    try {
      var breakout = top.anchorframe;
      top.anchorframe.clearAnchorActions();
    } catch(e) { if (breakout!=null) displayError("utilities:unsetAnchors.",e,DEBUGWARNING); }
  } // ENDS unsetAnchors

  function setDetailAnchors(astrAnchorLinks, astrAnchorIcons, astrAnchorDescriptions, astrAnchorTwistieState, astrAnchorTwistieUpdateFunctionName) {
    var anchorLinks = astrAnchorLinks.split("~");
    var anchorIcons = astrAnchorIcons.split("~");
    var anchorDescriptions = astrAnchorDescriptions.split("~");

    var anchorTextPosition = null;
    var frameLocation = "";

    frameLocation = top.logframe;
    if ((frameLocation == null) || (frameLocation == "undefined") || (frameLocation == "")) {
      frameLocation = ""; // child window
    }
    else {
      frameLocation = "top.logframe."; // detail window
    }

    // try to get a pointer to preferencesframe
    if (frameLocation == "top.logframe.") anchorTextPosition = top.preferencesframe.getAnchorTextPosition();
    if (anchorTextPosition == null) try { anchorTextPosition = window.opener.top.preferencesframe.getAnchorTextPosition(); } catch(e) { /* do nothing */ }
    if (anchorTextPosition == null) try { anchorTextPosition = window.opener.opener.top.preferencesframe.getAnchorTextPosition(); } catch(e) { /* do nothing */ }
    if (anchorTextPosition == null) anchorTextPosition = "none";

    // clicking the anchor link will blind expand the related section before going to the section
    var anchorTwistieState = astrAnchorTwistieState.split("~");
    var anchorTwistieUpdateFunctionName = astrAnchorTwistieUpdateFunctionName.split("~");

    var anchors = "<table border=0 cellspacing=0 cellpadding=0 height=100% width="+((anchorTextPosition == "beside") ? "80%" : "1%")+">\n\t<tr>\n";

    // if text is beside icon then all the anchors are run together in 1 cell for wrapping
    if (anchorTextPosition == "beside") {
      anchors += "\t\t<td align=right width=100%>";
    }

    for (i=0; i<anchorLinks.length; i++) {
      if ((anchorTextPosition == "none") || (anchorTextPosition == "below")) {
        anchors += "\t\t<td align=center width=1% nowrap>";
      }

      // icon
      anchors += "<a href=\"javascript:void 0;\" title=\""+anchorDescriptions[i]+"\" onclick=\""+frameLocation+anchorTwistieState[i]+"=true;"+frameLocation+anchorTwistieUpdateFunctionName[i]+";"+frameLocation+"dynamicResize();"+frameLocation+"gotoAnchor('"+anchorLinks[i]+"');"+((frameLocation == "") ? "document." : frameLocation)+"focus();"+((frameLocation == "") ? "" : frameLocation)+"selectFirstElement('"+anchorLinks[i]+"');return false;\""+((frameLocation == "") ? "" : " target=\"logframe\"")+">";
      anchors += "<img src='"+anchorIcons[i]+"' border=0 hspace="+((anchorTextPosition == "beside") ? "2" : "4")+">";

      // anchor text beside icon
      if (anchorTextPosition == "beside") {
        anchors += "<span class=small>"+replaceStringWithString(anchorDescriptions[i], " ", "&nbsp;")+"</span>";
      }

      anchors += "</a>";

      // anchor text below
      if (anchorTextPosition == "below") {
        anchors += "<br>";
        anchors += "<a href=\"javascript:void 0;\" title=\""+anchorDescriptions[i]+"\" onclick=\""+frameLocation+anchorTwistieState[i]+"=true;"+frameLocation+anchorTwistieUpdateFunctionName[i]+";"+frameLocation+"dynamicResize();"+frameLocation+"gotoAnchor('"+anchorLinks[i]+"');"+((frameLocation == "") ? "document." : frameLocation)+"focus();"+((frameLocation == "") ? "" : frameLocation)+"selectFirstElement('"+anchorLinks[i]+"');return false;\""+((frameLocation == "document.") ? "" : " target=\"logframe\"")+">";
        anchors += "<span class=small>"+anchorDescriptions[i]+"</span>";
        anchors += "</a>";
      }

      if ((anchorTextPosition == "none") || (anchorTextPosition == "below")) {
        anchors += "</td>";
      }

      // spacer
      if (anchorTextPosition == "below") {
        anchors += "<td width=8><img src='img/pix.gif' width=8 height=1 border=0></td>\n";
      }
      else if (anchorTextPosition == "beside") {
        anchors += "<img src='img/pix.gif' width=8 height=1 border=0>" + " "; // important space for wrapping
      }
    } // ENDS for (i=0; i<anchorLinks.length; i++)

    // if text is beside icon then all the anchors are run together in 1 cell for wrapping
    if (anchorTextPosition == "beside") {
      anchors += "</td>";
    }

    // side spacing if not showing text
    if (anchorTextPosition == "none") anchors += "\n\t\t<td width=10><img src='img/pix.gif' width=10 height=1 border=0></td>";

    anchors += "\n\t</tr>\n</table>";

    document.getElementById('anchoractions').innerHTML = anchors;
  } // ENDS setDetailAnchors

  function gotoAnchor(anchor) {
    try {
      var override = (arguments[1] == null) ? "true" : arguments[1];
      if (window.location.hash != "" && !override) return;

      // refresh the current hash
      if ((anchor == null || anchor == "") && window.location.hash != "") anchor=window.location.hash;

      if (!(anchor == null || anchor == "")) window.location.hash=anchor;
    } catch(e) { displayError("utilities:gotoAnchor.",e,DEBUGMODERATE); }
  } // ENDS gotoAnchor

// -- End Anchor Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Action Utilities
// ---------------------------

  // global hide/show action images
  var hideActions = new Image; hideActions.src = "img/hide_actionframe.gif";
  var showActions = new Image; showActions.src = "img/show_actionframe.gif";

  function showActionFrame() {
    // -----------------------------
    // see showTreeFrame for unsetting the action frame toggle ui
    // -----------------------------

    try {
      var breakout = top.document.getElementById('bodyframeset');
      var isLog = (getWhatIsLogFrame() == "log");

      var showActionFrame = top.preferencesframe.getShowDetailActionFrame();
      if (isLog) {
        //showActionFrame = top.anchorframe.logActionFrameVisible; // -- action toggle code
        //if (showActionFrame == null) { // -- action toggle code
          showActionFrame = top.preferencesframe.getShowLogActionFrame();
        //} // -- action toggle code
      }
      else {
        top.anchorframe.logActionFrameVisible = null;
      }

	if (showActionFrame == "show") 
	{
		if (top.preferencesframe.locale_in_use=='fr_FR' || top.preferencesframe.locale_in_use=='de_DE')
		{
			top.lognavigationframe.document.getElementById('fixactionwidth').style.width = 300 - 265; 	
		}
		else
		{
			top.lognavigationframe.document.getElementById('fixactionwidth').style.width = 300 - 180; // 180 is the treeframe width
		}
		top.anchorframe.document.getElementById('actionlist').innerHTML = "";

		//top.anchorframe.document.getElementById('toggleactionframeimage').src = hideActions.src; // -- action toggle code
		if (top.preferencesframe.locale_in_use=='fr_FR' || top.preferencesframe.locale_in_use=='de_DE')
		{
			top.document.getElementById('bodyframeset').cols = '0,265,*';
		}
		else
		{
			top.document.getElementById('bodyframeset').cols = '0,180,*';
		}
	}
      else {
        top.lognavigationframe.document.getElementById('fixactionwidth').style.width = 300;
        top.anchorframe.document.getElementById('actionlist').innerHTML = top.actionframe.document.getElementById('actionlist').innerHTML;

        //top.anchorframe.document.getElementById('toggleactionframeimage').src = showActions.src; // -- action toggle code

        top.document.getElementById('bodyframeset').cols = '0,0,*';
      }

      //top.anchorframe.document.getElementById('toggleactionframeimage').style.visibility = ""; // visible is implied -- action toggle code
    } catch(e) { if (breakout!=null) displayError("utilities:showActionFrame.",e,DEBUGMODERATE); }
  } // ENDS showActionFrame

  function toggleActionFrame() {
    // -----------------------------
    // see showTreeFrame for unsetting the action frame toggle ui
    // -----------------------------

    try {
      var breakout = top.document.getElementById('bodyframeset');
      var isLog = (getWhatIsLogFrame() == "log");
      var toggle = top.anchorframe.document.getElementById('toggleactionframeimage');

      // we do not update these prefs - yet - so do not set from them
//      var showActionFrame = top.preferencesframe.getShowDetailActionFrame();
//      if (isLog) {
//        showActionFrame = top.preferencesframe.getShowLogActionFrame();
//      }

      var showActionFrame = ((toggle.src.indexOf("show") != -1) ? "hide" : "show");

      // show the action frame
      if (showActionFrame == "hide") {
        showActionFrame = "show";
        if (document.styleSheets[2] && document.styleSheets[2].href.indexOf("fr_FR.css")!=-1)
        {
        	top.lognavigationframe.document.getElementById('fixactionwidth').style.width = 300 - 200; 
        }
        else
        {
        	top.lognavigationframe.document.getElementById('fixactionwidth').style.width = 300 - 180; // 180 is the treeframe width
        }

        toggle.src = hideActions.src;
        toggle.alt = toggle.hidealt;

        top.anchorframe.document.getElementById('actionlist').innerHTML = "";
	if (document.styleSheets[2] && document.styleSheets[2].href.indexOf("fr_FR.css")!=-1)
	{
	        top.document.getElementById('bodyframeset').cols = '0,200,*';
	}
	else
	{
		top.document.getElementById('bodyframeset').cols = '0,180,*';
	}
      }

      // hide the action frame
      else {
        showActionFrame = "hide";
        top.lognavigationframe.document.getElementById('fixactionwidth').style.width = 300;
        top.anchorframe.document.getElementById('actionlist').innerHTML = top.actionframe.document.getElementById('actionlist').innerHTML;

        toggle.src = showActions.src;
        toggle.alt = toggle.showalt;

        try { top.anchorframe.document.getElementById('selectactions').style.width = getStyleClass('width_e', 'width'); } catch(badtiming) {}

        top.document.getElementById('bodyframeset').cols = '0,0,*';
      }

      if (isLog) {
        top.anchorframe.logActionFrameVisible = showActionFrame;
      }
      else {
        top.anchorframe.logActionFrameVisible = null;
      }

      top.anchorframe.document.getElementById('toggleactionframeimage').style.visibility = ""; // visible is implied

      // do not set because the preferenceFrame does not update these prefs - yet
//      if (isLog) {
//        top.preferencesframe.setShowLogActionFrame(showActionFrame);
//      }
//      else {
//        top.preferencesframe.setShowDetailActionFrame(showActionFrame)
//      }

    } catch(e) { if (breakout!=null) displayError("utilities:showActionFrame.",e,DEBUGMODERATE); }
  } // ENDS toggleActionFrame

  function showTreeFrame() {
    try {
      var breakout = top.document.getElementById('bodyframeset');

      // clear the action toggle ui
      top.anchorframe.document.getElementById('actionlist').innerHTML = "";
      top.anchorframe.document.getElementById('toggleactionframeimage').style.visibility = "hidden";
      top.anchorframe.logActionFrameVisible = null;
    } catch(e) { if (breakout!=null) displayError("utilities:showTreeFrame:clearactiontoggleui.",e,DEBUGMODERATE); }

    try {
      var breakout = top.document.getElementById('bodyframeset');
      top.document.getElementById('bodyframeset').cols = '25%,0,*';
      top.treeframe.repaintTree(); // so ugly - jra to fix certain redraw problems
    } catch(e) { if (breakout!=null) displayError("utilities:showTreeFrame.",e,DEBUGMODERATE); }
  }

  var logIsSplit = false;
  var logIsTotaled = false;
  var showMiniSplitLog = false; // for devlopers only

  function showSplitLogFrame() {
    try {
      var breakout = top.document.getElementById('splitloglayoutframeset');

      // if this noResize worked.. then this is where it would go
      //top.logframe.noResize = false;
      //top.splitlogframe.noResize = false;

      top.document.getElementById('splitloglayoutframeset').frameBorder = 10;
      top.document.getElementById('splitloglayoutframeset').border = 5;
      top.document.getElementById('splitloglayoutframeset').frameSpacing = 4;

      top.logframe.document.body.style.overflowX = "auto";
      top.logframe.document.body.style.overflowY = "auto";

      top.splitlogframe.document.body.style.overflowX = "auto";
      top.splitlogframe.document.body.style.overflowY = "hidden";

      top.logframe.logIsSplit = true;
    } catch(e) { if (breakout!=null) displayError("utilities:showSplitLogFrame.",e,DEBUGMODERATE); }
  } // ENDS showSplitLogFrame

  function showTotalsLogFrame() {
    try {
      var breakout = top.document.getElementById('splitloglayoutframeset');

      var rowHeight = top.logframe.document.getElementById('headerrow').offsetHeight + 17; // 1 (the table cellspacing) + 16 (the horizontal scroll bar height)

      top.document.getElementById('logframesets').rows = '*,'+rowHeight;

      top.logframe.document.body.style.overflowX = "hidden";

      if (top.logframe.logIsSplit) {
        top.document.getElementById('splitlogframeset').rows = '*,'+rowHeight;
        top.splitlogframe.document.body.style.overflowX = "hidden";
      }

      top.logframe.logIsTotaled = true;
    } catch(e) { if (breakout!=null) displayError("utilities:showTotalsLogFrame.",e,DEBUGMODERATE); }
  } // ENDS showTotalsLogFrame

  // hide split log
  function resetLogFrame() {
    try {
      var breakout = top.document.getElementById('splitloglayoutframeset');

      top.document.getElementById('splitlogframeset').rows = '*,0';
      top.document.getElementById('logframesets').rows = '*,0';

      var currentSplitLogSet = ((""+top.document.getElementById('splitloglayoutframeset').cols).split(","));

      if (showMiniSplitLog && (currentSplitLogSet[0] != "*")) {
        top.document.getElementById('splitloglayoutframeset').cols = '200,*';
      }
      else {
        top.document.getElementById('splitloglayoutframeset').cols = '0,*';

        top.document.getElementById('splitloglayoutframeset').frameBorder = 0;
        top.document.getElementById('splitloglayoutframeset').border = 0;
        top.document.getElementById('splitloglayoutframeset').frameSpacing = 0;
      }

      // if this noResize worked.. then this is where it would go
      //top.logframe.noResize = true;
      //top.splitlogframe.noResize = true;

      try {
        if (is_ie) top.splitlogframe.document.body.scrollLeft = 0;
        else top.splitlogframe.window.pageYOffset = 0;
      } catch(frame_already_unloaded) { /* do nothing */ }

      try {
        if (is_ie) top.logframe.document.body.scrollLeft = 0;
        else top.logframe.window.pageYOffset = 0;
      } catch(frame_already_unloaded) { /* do nothing */ }

      try { top.logframe.logIsSplit = false; } catch(nos) { /* do nothing - don't really have to reset this as it gets reset when the page reloads */ }
    } catch(e) { if (breakout!=null) displayError("utilities:resetLogFrame.",e,DEBUGMODERATE); }
  } // ENDS resetLogFrame

  function showLogNavigationFrame() {
    try {
      var breakout = top.document.getElementById('loglayoutframeset');
      top.document.getElementById('loglayoutframeset').rows = '*,20';
    } catch(e) { if (breakout!=null) displayError("utilities:showLogNavigationFrame.",e,DEBUGMODERATE); }
  }

  function hideLogNavigationFrame() {
    try {
      var breakout = top.document.getElementById('loglayoutframeset');
      top.document.getElementById('loglayoutframeset').rows = '*,0';
    } catch(e) { if (breakout!=null) displayError("utilities:hideLogNavigationFrame.",e,DEBUGMODERATE); }
  }

  function setLogHref(toSysItemType, returnToLogPage, findText) {
    try {
      var breakout = top.actionframe;
      top.actionframe.setLogHref(toSysItemType, returnToLogPage, findText);
    } catch(e) { if (breakout!=null) displayError("utilities:setLogHref.",e,DEBUGMODERATE); }
  }

  function setDocHref(strHref) {
    try {
      var breakout = top.actionframe;
      top.actionframe.setDocHref(strHref);
    } catch(e) { if (breakout!=null) displayError("utilities:setDocHref.",e,DEBUGMODERATE); }
  }

  function setActions(displayNames, pictures, links, permittedFlags) {
    try {
      var breakout = top.actionframe;
      if (displayNames=="show none") pictures=links=permittedFlags="";
      top.actionframe.setValues(displayNames, pictures, links, permittedFlags);
    } catch(e) { if (breakout!=null) displayError("utilities:setActions.",e,DEBUGMODERATE); }
  }

  function setActionsForButtons(displayNames, pictures, links, permittedFlags) {
    try {
      var breakout = top.actionframe;
      if (displayNames=="show none") pictures=links=permittedFlags="";
      top.actionframe.setValuesForButtons(displayNames, pictures, links, permittedFlags);
    } catch(e) { if (breakout!=null) displayError("utilities:setActions.",e,DEBUGMODERATE); }
  }

  function setWhatIsLogFrame(str) {
    try {
      var breakout = top.actionframe;
      top.actionframe.setWhatIsLogFrame(str);
    } catch(e) { if (breakout!=null) displayError("utilities:setWhatIsLogFrame."+str,e,DEBUGWARNING); }
  }

  function getWhatIsLogFrame() {
    try {
      var breakout = top.actionframe;
      return top.actionframe.getWhatIsLogFrame();
    } catch(e) { if (breakout!=null) displayError("utilities:getWhatIsLogFrame.",e,DEBUGWARNING); }
  }

  function makeLogLinkInvisible() {
    try {
      var breakout = top.actionframe;
      top.actionframe.makeLogLinkInvisible();
    } catch(e) { if (breakout!=null) displayError("utilities:makeLogLinkInvisible.",e,DEBUGWARNING); }
  }

// -- End Action Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Preferences Utilities
// ---------------------------

  // master twistie switch
  var twistiesEnabled = false;

  function enableTwisties() { twistiesEnabled = true; }
  function disableTwisties() { twistiesEnabled = false; }

  // global twistie images
  twistieExpand = new Image; twistieExpand.src = "img/expand.gif";
  twistieCollapse = new Image; twistieCollapse.src = "img/collapse.gif";

  function setTwistieIndicator(imageId, state) {
    // imageId can be either an object or the id for an object
    // note: if given an id.. it must be within the current document
    try {
      if (imageId.charAt) imageId = document.getElementById(imageId);

      if (state) setTwistieExpand(imageId);
      else setTwistieCollapse(imageId);
    } catch(e) { displayError("utilities:setTwistieIndicator.",e,DEBUGWARNING); }
  }

  function setTwistieExpand(imageId) {
    // imageId can be either an object or the id for an object
    // note: if given an id.. it must be within the current document
    try {
      if (imageId.charAt) imageId = document.getElementById(imageId);

      imageId.src = twistieExpand.src;
    } catch(e) { displayError("utilities:setTwistieExpand.",e,DEBUGWARNING); }
  }

  function setTwistieCollapse(imageId) {
    // imageId can be either an object or the id for an object
    // note: if given an id.. it must be within the current document
    try {
      if (imageId.charAt) imageId = document.getElementById(imageId);

      imageId.src = twistieCollapse.src;
    } catch(e) { displayError("utilities:setTwistieCollapse.",e,DEBUGWARNING); }
  }

  function getTwistieState(module, number) {
    try {
      var breakout = top.preferencesframe;

      // we might be in a child window
      if (breakout==null) {
        return window.opener.top.preferencesframe.getTwistieState(module, number);
      }
      else {
        return top.preferencesframe.getTwistieState(module, number);
      }
    } catch(e) { if (breakout!=null) refreshPreferences(); displayError("utilities:getTwistieState.",e,DEBUGMODERATE); }
  } // ENDS getTwistieState

  function setTwistieState(module, number, value) {
    try {
      var breakout = top.preferencesframe;

      // we might be in a child window
      if (breakout==null) {
        window.opener.top.preferencesframe.setTwistieState(module, number, value);
      }
      else {
        top.preferencesframe.setTwistieState(module, number, value);
      }
    } catch(e) { if (breakout!=null) refreshPreferences(); displayError("utilities:setTwistieState.",e,DEBUGMODERATE); }
  } // ENDS setTwistieState

  function setTwistieSectionVisible(section, expanded) {
    // section can be either an object or the id for an object
    // note: if given an id.. it must be within the current document
    if (section.charAt) section = document.getElementById(section);

    if (expanded) {
//      try {
        if (section.style.display != "") {
          section.style.display = "";
        }
//      }
//      catch(e) {
//        if (section.tagName == "TABLE" && section.style.visibility != "") {
//          // ----------------------------------------
//          // IMPORTANT: do not change order of events
//          // ----------------------------------------
//          section.style.top = "";
//          section.style.clip = "rect(0px 0px 0px 0px)";
//          section.style.visibility = "";
//          section.style.position = "relative"; // IMPORTANT: this must be set after the visibility when expanding
//        }
//      }
    }
    else {
//      try {
        if (section.style.display != "none") {
          section.style.display = "none";
        }
//      }
//      catch(e) {
//        if (section.tagName == "TABLE" && section.style.visibility != "hidden") {
//          // ----------------------------------------
//          // IMPORTANT: do not change order of events
//          // ----------------------------------------
//          section.style.visibility = "hidden";
//          section.style.position = "absolute";
//          section.style.clip = "rect(0px 0px 0px 0px)";
//          section.style.top = "0px";
//        }
//      }
    }
  }

  function getLogSplitScrollModule(module) {
    try {
      var breakout = top.preferencesframe;
      return top.preferencesframe.getLogSplitScrollModule(module);
    } catch(e) { if (breakout!=null) refreshPreferences(); displayError("utilities:getLogSplitScrollModule.",e,DEBUGMODERATE); }
  }

  function setLogSplitScrollModule(module, splitScrollData) {
    try {
      var breakout = top.preferencesframe;
      top.preferencesframe.setLogSplitScrollModule(module, splitScrollData);
    } catch(e) { if (breakout!=null) refreshPreferences(); displayError("utilities:setLogSplitScrollModule.",e,DEBUGMODERATE); }
  }

  function savePreferences() {
    try {
      var breakout = top.preferencesframe;
      top.preferencesframe.submitForm();
    } catch(e) { if (breakout!=null) refreshPreferences(); displayError("utilities:savePreferences.",e,DEBUGMODERATE); }
  }

  function refreshPreferences() {
    top.preferencesframe.location.replace("preferences.do?action=show");
    //displayError("utilities:refreshPreferences.",e,DEBUGALL);
  }

// -- End Preferences Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Image Utilities
// ---------------------------

  function changeImage(imageId, newImage) {
    // imageId can be either an object or the id for an object
    // note: if given an id.. it must be within the current document
    try {
      if (imageId.charAt) imageId = document.getElementById(imageId);

      imageId.src = newImage.src;
    } catch(e) { displayError("utilities:changeImage.",e,DEBUGMODERATE); }
  }

  function ImageAnimator(imgName, imgURLs, spd) {
    this.id = ImageAnimator.cnt;
    ImageAnimator.elements[ImageAnimator.cnt++] = this;
    this.imgName = imgName;
    this.imgURLs = imgURLs;
    this.spd = spd ? spd : 500;
    this.images = new Array(this.imgURLs.length);
    for (var i = 0; i < this.imgURLs.length; i++) {
      this.images[i] = new Image();
      this.images[i].src = this.imgURLs[i];
    }
    this.direction = 'forward';
  } // ENDS ImageAnimator

  ImageAnimator.prototype.play = ImageAnimator_play;

  function ImageAnimator_play(play) {
    // play: cycle, loop, forward, backward
    if (play == "" || play == null) play = 'loop';
    if (this.tid) {
      clearTimeout(this.tid);
    }
    if (play == 'loop') {
      this.direction = 'forward';
      this.cnt = 0;
      if (!this.image) {
        this.image = document.getElementById(this.imgName);
      }
      if (this.image) {
        this.animateLoop();
      }
    }
    else if (play == 'cycle') {
      this.direction = 'forward';
      this.cnt = 0;
      if (!this.image) {
        this.image = document.getElementById(this.imgName);
      }
      if (this.image) {
        this.animateCycle();
      }
    }
    else {
      this.direction = play;
      if (this.direction == 'forward') {
        this.cnt = 0;
      }
      else {
        this.cnt = ((this.cnt == 0) ? 0 : this.cnt--);
      }
      if (!this.image) {
        this.image = document.getElementById(this.imgName);
      }
      if (this.image) {
        this.animate();
      }
    }
  } // ENDS ImageAnimator_play

  ImageAnimator.prototype.animateLoop = ImageAnimator_animateLoop;

  function ImageAnimator_animateLoop() {
    this.image.src = this.images[this.cnt].src;
    this.cnt++;
    if (this.cnt >= this.imgURLs.length) {
      this.cnt=0;
    }
    this.tid = setTimeout('ImageAnimator.elements[' + this.id + '].animateLoop()', this.spd);
  } // ENDS ImageAnimator_animateLoop

  ImageAnimator.prototype.animateCycle = ImageAnimator_animateCycle;

  function ImageAnimator_animateCycle() {
    this.image.src = this.images[this.cnt].src;
    if (this.cnt >= this.imgURLs.length-1) {
      this.direction = 'backward';
    }
    if (this.cnt == 0) {
      this.direction = 'forward';
    }
    if (this.direction == 'forward') this.cnt++;
    else this.cnt--;
    this.tid = setTimeout('ImageAnimator.elements[' + this.id + '].animateCycle()', this.spd);
  } // ENDS ImageAnimator_animateCycle

  ImageAnimator.prototype.animate = ImageAnimator_animate;

  function ImageAnimator_animate() {
    this.image.src = this.images[this.cnt].src;
    if (this.direction == 'forward') {
      this.cnt++;
      if (this.cnt < this.imgURLs.length) {
        this.tid = setTimeout('ImageAnimator.elements[' + this.id + '].animate()', this.spd);
      }
      else {
        this.cnt--;
      }
    }
    else {
      this.cnt--;
      if (this.cnt >= 0 && this.cnt < this.imgURLs.length) {
        this.tid = setTimeout('ImageAnimator.elements[' + this.id + '].animate()', this.spd);
      }
      else {
        this.cnt = 0;
      }
    }
  } // ENDS ImageAnimator_animate

  ImageAnimator.cnt = 0;
  ImageAnimator.elements = new Array();

  var processingIndicator = new ImageAnimator(
    'processing',
    new Array('img/process_meter_1.gif',
              'img/process_meter_2.gif',
              'img/process_meter_3.gif',
              'img/process_meter_4.gif',
              'img/process_meter_5.gif',
              'img/process_meter_6.gif'),
    200
 );

// -- End Image Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Struts Form Element Handler Utilities
// ---------------------------

  function returnElementIndex(theForm, elementName) {
    // return the form element index for the given element name because we
    // can't directly call struts form elements via their name with javascript
    // due to struts using "." in their form element names

    for(i=0;i<theForm.elements.length;i++) {
      if (theForm.elements[i].name == elementName) {
        return i;
      }
    }
    return -1;
  } // ENDS returnElementIndex

  function setInputFromThisSelect(theFormName, inputElement, thisElement) {
    var theForm=window.document.forms(theFormName);
    var setElement=theForm.elements(inputElement);

    setElement.value=thisElement.options[thisElement.selectedIndex].value;
    thisElement.selectedIndex = 0; // first option in select is expected to be blank
  } // ENDS setInputFromThisSelect

  function updateHiddenTextArea(theFormName, hiddenElement, thisElement) {
    var theForm=window.document.forms(theFormName);
    var setElement=theForm.elements(hiddenElement);

    setElement.value=thisElement.value;
  } // ENDS updateHiddenTextArea

// -- End Struts Form Element Handler Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Popup Utilities
// ---------------------------

  function centerWindow(width, height, aWindow) {
    if (aWindow == null) {
      aWindow = window;
    }
    return positionWindow(width, height, "center", aWindow);
  } // ENDS centerWindow

  // can optionally pass in a fifth param of 'coordinates' which will instruct
  // the function to return the left and top numeric positions only
  function positionWindow(width, height, position, aWindow) {
    if (aWindow == null) {
      aWindow = window;
    }
    // NOTE: window height is the broswer content window height. It does not include the header bars
    // (buttons, location field, tool bar, favorites) width and height are the the new windows desired
    // width and height and are used as offset values acceptable positions are any combination of the
    // following key words:
    //   center, left, right, top, bottom

    var left = l = 50;
    var top = t = 50;
    var hpadding = 50;
    var vpadding = 50;
    var w = width;
    var h = height;

    var win = aWindow;
    var resolution = 0;
    try {
      resolution = win.screen.width*win.screen.height;
    }
    catch(resolution800600bug) {
      resolution = 800*600;
    }

    // if the resolution is smaller than 800*600 then the window
    // may be one of our popup windows and not the main window.
    // we want to be sure to be positioning in relation to the main
    // window, which typically will be maximized to full screen demensions.
    if (resolution-1 < 800*600) {
      win = aWindow.opener;
      try {
        resolution = win.screen.width*win.screen.height;
      }
      catch(resolution800600bug) {
        resolution = 800*600;
      }
    }

    if (resolution > 1280*1024) vpadding = 250;
    if (resolution <= 1280*1024) vpadding = 200;
    if (resolution <= 1152*864) vpadding = 150;
    if (resolution <= 1024*768) vpadding = 100;
    if (resolution <= 800*600) vpadding = 0;

    if ((height>490) && (vpadding>0)) height=490;

    try {
      if (is_ie) {
        l = win.top.screenLeft;
        t = ((position == "center") ? win.top.screenTop : 0);
        w = win.top.document.body.offsetWidth;
        h = win.top.document.body.offsetHeight;
      }
      else if (is_nav) {
        l = win.top.screenX;
        t = ((position == "center") ? win.top.screenY : 0);
        w = win.top.outerWidth;
        h = win.top.outerHeight;
      }
      else {
        // default
        l=0;
        t=0;
        w = win.screen.width; // this should be valid JS in any browser
        h = win.screen.height; // this should be valid JS in any browser
      }
    }
    catch(resolution800600bug) { // IE 5.5 sp2 complains about not knowing what "window.top.screentop" is when resolution is 600x800 or less
      l=0;
      t=0;
      try {
        w = win.screen.width; // this should be valid JS in any browser
        h = win.screen.height; // this should be valid JS in any browser
      }
      catch(resolution800600bug) { // IE 6 complains about not knowing what "window.screen.height" is when resolution is 600x800 or less
        w = 800;
        h = 600;
      }
    }

    if (position.indexOf("center") != -1) {
      left = l+Math.round((w - width)/2);
      top = t+Math.round((h - height)/2);
    }
    if (position.indexOf("left") != -1) {
      left = l+hpadding;
    }
    if (position.indexOf("right") != -1) {
      left = l+w-width-hpadding;
    }
    if (position.indexOf("top") != -1) {
      top = t+vpadding;
    }
    if (position.indexOf("bottom") != -1) {
      top = t+h-height-vpadding;
    }

    // w & h is the amount of web page space the browser is displaying - it doesn't include toolbars and menus
    // if the width or height of the window is greater than the width or height of the IE page then adjust the left & top so the
    // left & bottom doesn't drop off the screen. 5 is a little extra padding to bring the window fully into view.
    if (width>w) left = left-(width-w)-5;
    if (height>h) top = top-(height-h)-5;

    // ensure that we are attempting to position the window on screen
    // reuse the w and h variables for this final quick test
    // we need to test against the screen dimensions not the current window
    try {
      w = win.screen.width; // this should be valid JS in any browser
      h = win.screen.height; // this should be valid JS in any browser
    }
    catch(resolution800600bug) { // IE 6 complains about not knowing what "window.screen.height" is when resolution is 600x800 or less
      w = 800;
      h = 600;
    }
    if (left>w) left = Math.round((w-width)/2);
    if (top>h) top = Math.round((h-height)/2);

    if (arguments[4] != null && arguments[4] == 'coordinates') return (left+","+top);
    else return ("left="+left+",top="+top);
  } // ENDS positionWindow

  function autoResizeWindow() {
    //if (is_nav) {
    //  window.sizeToContent();
    //  return;
    //}

    // -------------------------------------
    // resize the window to fit the content
    // get these values after the document has been fully populated
    var displayWidth = window.top.document.body.offsetWidth;
    var displayHeight = window.top.document.body.offsetHeight;

    var actualWidth = document.body.scrollWidth;
    var actualHeight = document.body.scrollHeight;

    //original = "\n"+"displayWidth => "+displayWidth+
    //"\n"+"actualWidth => "+actualWidth+
    //"\n"+"displayHeight => "+displayHeight+
    //"\n"+"actualHeight => "+actualHeight;

    var resize = false;

    if (actualWidth > displayWidth) {
      resize = true;
      displayWidth = actualWidth;
    }
    if (actualHeight > displayHeight) {
      resize = true;
      displayHeight = actualHeight + 50; // +25 for the title bar
    }

    var widthOffset = 6;
    var heightOffset = 6;

    // make sure we do not resize bigger than the screen resolution
    if (displayWidth+widthOffset > window.screen.width) displayWidth = window.screen.width;
    if (displayHeight+heightOffset > window.screen.height) displayHeight = window.screen.height;

    //resized = "\n"+"displayWidth => "+(displayWidth+widthOffset)+"\n"+"displayHeight => "+(displayHeight+heightOffset);

    if (resize) {
      resizeTo(displayWidth+widthOffset, displayHeight+heightOffset);

      //displayWidthDblcheck = window.top.document.body.offsetWidth;
      //actualWidth = document.body.scrollWidth;
      //displayHeightDblcheck = window.top.document.body.offsetHeight;
      //actualHeight = document.body.scrollHeight;
      //alert(original+"\n"+resized+"\n"+
      //"\n"+"displayWidth => "+displayWidthDblcheck+
      //"\n"+"actualWidth => "+actualWidth+
      //"\n"+"displayHeight => "+displayHeightDblcheck+
      //"\n"+"actualHeight => "+actualHeight);

      // reposition the window
      var topPosition = eval(((""+((""+centerWindow(displayWidth, displayHeight)).split(","))[1]).split("="))[1]);
      var leftPosition = eval(((""+((""+centerWindow(displayWidth, displayHeight)).split(","))[0]).split("="))[1]);

      // make sure we do not go off the screen
      if (topPosition+displayHeight > window.screen.width) topPosition = 0;
      if (leftPosition+displayWidth > window.screen.width) leftPosition = 0;

      moveTo(leftPosition, topPosition);
    }

    // ENDS resize
    // -------------------------------------
  } // ENDS autoResizeWindow

  var mChildWindow = null;

  function popupChildWindow(strHref, windowName, strFeatures) {
    // --------------
    // special case for issues and attachments
    if (windowName == "PRINT!") {
      top.actionframe.openIndicator(strHref);
      top.hiddenframe.location.replace(strHref+'&printreport=true');
      return;
    }
    else if (windowName == "ADVANCEDPRINT!") {
      top.headerframe.popAdvancedPrint('actionframe', strHref);
      return;
    }
    else if (windowName == "PRINTPREVIEW!") {
      top.headerframe.popPrintPreview('actionframe', strHref);
      return;
    }
    else if (windowName == "SEARCH") {
      top.headerframe.processGoToBuildIssue(strHref);
      return;
    }
    else if (windowName == "COSTCODEPICKER" || windowName == "GETMARKUP" || windowName == "UPDATEPERCENTCOMPLETE" || windowName == "IMPORTREPORT") {
      eval(strHref);
      return;
    }
    else if (windowName == "WORDOPEN") {
      var argarray = strHref.split(',');
      var sWordUrl = "";
	  sWordUrl = top.utilitiesframe.UtilitiesApplet.getMSWordDocumentUrl(argarray[0], argarray[1], argarray[2], argarray[3], argarray[4]);
	  var sDataSource = top.utilitiesframe.UtilitiesApplet.getDataSourceFileName();
      launchWord(sWordUrl,sDataSource);
	  return;
    }
    else if (strHref.indexOf("issuepicker.do") != -1) {
      if (strHref.indexOf("action=delete") != -1) {
        processUnlink(strHref, windowName);
      }
      else {
        popupPickerWindow(strHref, windowName, strFeatures);
      }
      return;
    }
    else if (strHref.indexOf("attachments.do") != -1) {
      if (strHref.indexOf("action=delete") != -1) {
        processDetachment(strHref, windowName);
      }
      else {
        popupPickerWindow(strHref, windowName, strFeatures);
      }
      return;
    }
    else if (strHref.indexOf("action=delete") != -1) {
      // special case for delete LUW
      processDelete(strHref, windowName);
      return;
    }
    else if (strHref.indexOf("action=clearphase") != -1) {
      //special case for CM Clearphase LUW
      processDelete(strHref, windowName);
      return;
    }
    else if (strHref.indexOf("action=removedistribution") != -1 || strHref.indexOf("action=removedrawing") != -1) {
      //special case for drawing set remove
      processDelete(strHref, windowName);
      return;
    }
    else if (windowName == "ADDINPLACE") {
      top.logframe.location.replace(strHref);
      return;
    }
    else if ((strHref.indexOf("documentation.do") != -1) || (strHref.indexOf("documentlinkrequest.do") != -1)) {
      windowName = "FORM";
    }
    // ENDS special case for issues and attachments
    // --------------

    windowFeatures = "scrollbars=yes,resizable=no,top=50,left=50";

    if ((strFeatures.split(",")).length>2) {
      windowFeatures = strFeatures;
    }
    else {
      windowFeatures += ","+strFeatures;
    }

    windowName = makeAlphaNumeric(windowName, "preservewhitespace");

    if ((!mChildWindow) || (mChildWindow.closed)) {
      mChildWindow = window.open(strHref, windowName, windowFeatures);
      if (mChildWindow.opener == null) mChildWindow.opener = self;
    }
    else {
      //don't open a new window if one already exsists
      mChildWindow.focus();
    }
  } // ENDS popupChildWindow

  var mPickerWindow = null;

  function popupPickerWindow(strHref, windowName) {

    buildPopupPickerWindow(strHref, windowName, ((arguments[2] == null) ? "" : arguments[2]), ((arguments[3] == null) ? "" : arguments[3]));

//    // optional 3rd or 4th parameters
//    // if there is only a 3rd parameter then it is a string list of window features
//    // if there is a 3rd and 4th then the 3rd parameter is the window width and the 4th is the window height
//    if (arguments.length == 3) {
//      strFeatures = arguments[2];
//    }
//    else if (arguments.length == 4) {
//      strFeatures = "scrollbars=yes,resizable=no,width="+arguments[2]+",height="+arguments[3]+","+positionWindow(arguments[2], arguments[3], "topright");
//    }
//
//    windowFeatures = "scrollbars=yes,resizable=no,top=1,left=1";
//
//    if ((strFeatures.split(",")).length>2) windowFeatures = strFeatures;
//    else windowFeatures = windowFeatures+","+strFeatures;
//
//    windowName = makeAlphaNumeric(windowName, "preservewhitespace");
//
//    if ((!mPickerWindow) || (mPickerWindow.closed)) {
//      mPickerWindow = window.open(strHref, windowName, windowFeatures);
//      if (mPickerWindow.opener == null) mPickerWindow.opener = self;
//    }
//    else {
//      //don't open a new window if one already exsists
//      mPickerWindow.focus();
//    }
  } // ENDS popupPickerWindow

  function buildPopupPickerWindow(actionDotDo, windowName, optWinFeatureOne, optWinFeatureTwo, formElements, formValues, formValueReferenceType) {
    // formValueReferenceType can either be:  vals, ids or vars
    //     vals => are actual values
    //     ids  => identified (by id) form element on the document in the callee window (window.opener)
    //     vars => variables declared on the document in the callee window (window.opener)

    if (optWinFeatureTwo == "" || optWinFeatureTwo == null) {
      strFeatures = optWinFeatureOne;
    }
    else {
      strFeatures = "scrollbars=yes,resizable=no,width="+optWinFeatureOne+",height="+optWinFeatureTwo+","+positionWindow(optWinFeatureOne, optWinFeatureTwo, "topright");
    }

    windowFeatures = "scrollbars=yes,resizable=no,top=1,left=1";

    if ((strFeatures.split(",")).length>2) windowFeatures = strFeatures;
    else windowFeatures = windowFeatures+","+strFeatures;

    windowName = makeAlphaNumeric(windowName, "preservewhitespace");

    if ((!mPickerWindow) || (mPickerWindow.closed)) {

      mPickerWindow = window.open("blank.html", windowName, windowFeatures);

      var newDocumentHTML = "<html><head><link href=css/exponline.css rel=stylesheet type=text/css charset=ISO-8859-1></head><body><form id='buildform' method='post'";

      if (formValueReferenceType == null) formValueReferenceType = "vals";
      if (formElements == null) formElements = new Array();
      if (formValues == null) formValues = new Array();

      // check to see if the actionDotDo is a full url
      if (actionDotDo.indexOf("?") != -1) {
        actionDotDo = replaceStringWithString(actionDotDo, "&amp;", "&");

        // note: we are not going to support nested paramters within quotes
        var urlParams = getURLParams('', actionDotDo);

        for (var property in urlParams) {
          var propertyValue = "urlParams."+property;
   
          try {
            propertyValue = eval(propertyValue);
          }
          catch(e) {
            propertyValue = "";
          }

          formElements[formElements.length] = property;
          formValues[formValues.length] = filter(propertyValue);
        }

        actionDotDo = actionDotDo.substring(0, actionDotDo.indexOf("?"));
      }
      
      newDocumentHTML = newDocumentHTML + " action='"+actionDotDo+"'";
      newDocumentHTML = newDocumentHTML + ">";

      // btw... we are not currently handling multi select boxes
      var newFormElement = null;
      for (var i=0; i < formElements.length; i++) {
        // set the formElements
        newDocumentHTML = newDocumentHTML + "<input type='hidden' id='" + formElements[i] + "' name='" + formElements[i] + "' value='";

        // set the formValues
//        if (formValueReferenceType == "ids") {
//          newDocumentHTML = newDocumentHTML + window.opener.document.getElementById(formValues[i]).value;
//        }
//        else if (formValueReferenceType == "vars") {
//          newDocumentHTML = newDocumentHTML + eval("window.opener.document."+formValues[i]+".value");
//        }
//        else { // default to vals
          newDocumentHTML = newDocumentHTML + formValues[i];
//        }

        newDocumentHTML = newDocumentHTML + "'>"
      }

      if (mPickerWindow.opener == null) mPickerWindow.opener = self;

      newDocumentHTML = newDocumentHTML + "</form></body></html>";

      mPickerWindow.document.open();
      mPickerWindow.document.write(newDocumentHTML);
      mPickerWindow.document.close();

      mPickerWindow.document.getElementById('buildform').submit();
    }
    else {
      //don't open a new window if one already exsists
      mPickerWindow.focus();
    }
  } // ENDS popupPickerWindow

  function popupDocumentWindow(strHref) {
    strFeatures = "scrollbars=yes,resizable=yes,width=700,height=650,top=50,left=200";
    popupChildWindow(strHref, "DOCUMENT", strFeatures);
  }

  function popupActivityInfo(strTaskCode) {
    strHref = "activitypopup.do?action=show&taskcode=" + strTaskCode;
    strFeatures = "width=400,height=340";
    popupChildWindow(strHref, "ACTIVITY_INFO", strFeatures);
  }

  function popupUserInfo(strHref) {
    // not really a picker, but is a third level window
    strFeatures = "scrollbars=yes,resizable=no,width=400,height=270,top=100,left=375";
    popupPickerWindow(strHref, "USER_INFO", strFeatures);
  }

  function popupContactInfo(strHref) {
    // not really a picker, but is a third level window
    strFeatures = "scrollbars=yes,resizable=no,width=400,height=400,top=100,left=375";
    popupPickerWindow(strHref, "CONTACT_INFO", strFeatures);
  }

  function popupCostDistribution(strAnchor, strHref) {
    strFeatures = "width=370,height=270,"+centerWindow(370, 270);
    processPopupRequest(strAnchor, strHref, "POPUPDIST", strFeatures);
  }

  // Company Contact Picker
  function contactPickerPopUp(pickerType, isAddressNeeded, isMultiSelect, organiseBy, sortBy, selectedVendorCode, selectedInitials, selectedCompany, isJobTitleNeeded, isTelephoneNeeded, isEnterpriseTypeNeeded, isEmailNeeded) {
    if (pickerType != "companycontact" &&
        pickerType != "companycontactrole" &&
        pickerType != "company" &&
        pickerType != "contact" &&
        pickerType != "companyonly") {
      return;
    }

    if ((isEnterpriseTypeNeeded != "true" && isEnterpriseTypeNeeded != true)) { isEnterpriseTypeNeeded="false"; } else { isEnterpriseTypeNeeded="true"; }

    if ((isEmailNeeded != "true" && isEmailNeeded != true)) { isEmailNeeded="false"; } else { isEmailNeeded="true"; }

    if ((isAddressNeeded != "true" && isAddressNeeded != true)) { isAddressNeeded="false"; } else { isAddressNeeded="true"; }

    if ((isJobTitleNeeded != "true" && isJobTitleNeeded != true)) { isJobTitleNeeded="false"; } else { isJobTitleNeeded="true"; }

    if ((isTelephoneNeeded != "true" && isTelephoneNeeded != true)) { isTelephoneNeeded="false"; } else { isTelephoneNeeded="true"; }

    if (isMultiSelect != "true" && isMultiSelect != true) { isMultiSelect="false"; } else { isMultiSelect="true"; }

    if(pickerType == 'contact'){
      if (organiseBy != 'company') { organiseBy = 'contact'; }
    }
    else{
      if (organiseBy != 'contact') { organiseBy = 'company'; }
    }

    if (sortBy != 'lastname') { sortBy = 'firstname'; }

    if (selectedVendorCode == null) { selectedVendorCode = ''; }

    if (selectedInitials == null) { selectedInitials = ''; }

    if (selectedCompany == null) { selectedCompany = ''; }

    var strHref = "contactpicker.do?action=show";

    if (pickerType == "companyonly") { // all company pickers can have the "Add Company" button except the company picker from "Add Contact"
      pickerType = "company&amp;canaddcompanyonfly=false";
    }

    strHref = strHref + "&amp;contactpickertype="+pickerType ;
    strHref = strHref + "&amp;multiselect="+ isMultiSelect;
    strHref = strHref + "&amp;organiseby="+organiseBy;
    strHref = strHref + "&amp;sortby="+sortBy;
    strHref = strHref + "&amp;isaddressneeded="+isAddressNeeded;
    strHref = strHref + "&amp;prevselectedvendorcode="+expEncode(selectedVendorCode);
    strHref = strHref + "&amp;prevselectedvendorini="+expEncode(selectedInitials);
    strHref = strHref + "&amp;prevselectedcompany="+expEncode(selectedCompany);
    strHref = strHref + "&amp;isjobtitleneeded="+isJobTitleNeeded;
    strHref = strHref + "&amp;istelephoneneeded="+isTelephoneNeeded;
    strHref = strHref + "&amp;isenterprisetypeneeded="+isEnterpriseTypeNeeded;
    strHref = strHref + "&amp;isemailneeded="+isEmailNeeded;

    if (isMultiSelect == "true") {
      popupPickerWindow(strHref, "PICKER", "680", "550");
    }
    else {
      popupPickerWindow(strHref, "PICKER", "680", "490");
    }
  } // ENDS contactPickerPopUp

  // Submittal Picker
  function submittalPickerPopUp(organiseBy, sortBy, selectedMasterKeys, selectedParentKeys, selectedTitles, selectedSubmittalNos, selectedPackageNumbers) {
    if (organiseBy != 'submittalpackage') { organiseBy = 'submittal'; }
    if (sortBy != 'number') { sortBy = 'title'; }
    if (selectedMasterKeys == null) {
      selectedMasterKeys = '';
    }
    if (selectedParentKeys == null) {
      selectedParentKeys = '';
    }
    if (selectedTitles == null) {
      selectedTitles = '';
    }
    if (selectedSubmittalNos == null) {
      selectedSubmittalNos = '';
    }
    if (selectedPackageNumbers == null) {
      selectedPackageNumbers = '';
    }
    var strHref = "submittalpicker.do?action=show";
    strHref = strHref + "&amp;multiselect=true";
    strHref = strHref + "&amp;organiseby="+organiseBy;
    strHref = strHref + "&amp;sortby="+sortBy;
    strHref = strHref + "&amp;selectedmasterkeys="+selectedMasterKeys;
    strHref = strHref + "&amp;selectedparentkeys="+selectedParentKeys;
    strHref = strHref + "&amp;selectedtitles="+selectedTitles;
    strHref = strHref + "&amp;selectedsubmittalnos="+selectedSubmittalNos;
    strHref = strHref + "&amp;selectedpackagenumbers="+selectedPackageNumbers;
    popupPickerWindow(strHref, "PICKER", "680", "540");
  } // ENDS submittalPickerPopUp

  function changeDocPickerPopUp() {
    var changeDocUrl = 'changedocpicker.do?action=show';
    var tmp = ((arguments[0] != null) ? arguments[0] : "");
    tmp = expEncode(tmp);
    if (tmp != "") changeDocUrl += "&docmasterkey="+tmp;

    popupPickerWindow(changeDocUrl, "PICKER", "680", "540") ;
  } // ENDS changeDocPickerPopUp

  function contractPickerPopUp() {
    var contractUrl = 'contractpicker.do?action=show';
    var tmp = ((arguments[0] != null) ? arguments[0] : "");
    tmp = expEncode(tmp);
    if (tmp != "") contractUrl += "&docmasterkey="+tmp;

    //see if a second param was supplied
    if (arguments[1] != null && arguments[1] != "") {
      //if the second param is == tofromvendorsupplied
      //then there should be 4 more params after it in the following order
      //arguments[2] = tovendor , arguments[3] = tovendorini
      //arguments[4] = fromvendor , arguments[5] = fromvendorini
      if (arguments[1] == "BUDGET" || arguments[1] == "COMMITMENT") {
        contractUrl += "&costingside=" + arguments[1];
        if (arguments[2] == "changeorderinfo=yes") {
          contractUrl += "&changeorderinfo=yes";
        }
        else if (arguments[2].indexOf("proposalinfo") != -1) {
          contractUrl += "&" + arguments[2];
        }
      }
      else if (arguments[2].indexOf("changeorderinfo") != -1) {
        contractUrl = contractUrl + "&" + arguments[2];
      }
      else if (arguments[2].indexOf("proposalinfo") != -1) {
        contractUrl = contractUrl + "&" + arguments[2];
      }
      else if (arguments[2].indexOf("requisitioninfo") != -1) {
        contractUrl = contractUrl + "&" + arguments[2];
      }
      else if (arguments[2].indexOf("materialinfo") != -1) {
        contractUrl = contractUrl + "&" + arguments[2];
      }
      else if (arguments[1] == "tofromvendorsupplied") {
        contractUrl += "&tofromvendorsupplied=yes";

        tmp = ((arguments[2] != null) ? arguments[2] : "");
        tmp = expEncode(tmp);
        contractUrl += "&tovendor="+tmp;

        tmp = ((arguments[3] != null) ? arguments[3] : "");
        tmp = expEncode(tmp);
        contractUrl += "&tovendorini="+tmp;

        tmp = ((arguments[4] != null) ? arguments[4] : "");
        tmp = expEncode(tmp);
        contractUrl += "&fromvendor="+tmp;

        tmp = ((arguments[5] != null) ? arguments[5] : "");
        tmp = expEncode(tmp);
        contractUrl += "&fromvendorini="+tmp;
      }
    }

    popupPickerWindow(contractUrl, "PICKER", "680", "540") ;
  } // ENDS contractPickerPopUp

  function activityPickerPopUp() {
    var activityUrl = 'activitypicker.do?action=show';
    var tmp = ((arguments[0] != null) ? arguments[0] : "");
    tmp = expEncode(tmp);
    if (tmp != "") activityUrl += "&taskcode="+tmp;

    popupPickerWindow(activityUrl, "PICKER", "680", "540") ;
  } // ENDS activityPickerPopUp

  function projectPickerPopUp() {
    var projectUrl = 'projectpicker.do?action=';
    if (arguments[0] == null) {
      projectUrl = projectUrl + 'show';
    }
    else {
      projectUrl = projectUrl + arguments[0];
    }
    if (arguments[1] != null) {
      projectUrl = projectUrl + '&' + arguments[1];
    }

    popupPickerWindow(projectUrl, "PICKER", "680", "540") ;
  } // ENDS projectPickerPopUp

  function packagePickerPopup() {
    var packageUrl = 'packagepicker.do?action=show';
    popupPickerWindow(packageUrl, "PICKER", "680", "540") ;
  } // ENDS packagePickerPopup

  function materialPickerPopUp() {
    // 1st argument tells the picker if it is a multi select or single select picker
    // 2nd argument is the master key of the item (is available)
    var materialUrl = 'materialpicker.do?action=show';
    var multi = false;
    var tmp = "";
    if ((arguments[0] == "true") || (arguments[0] == "false") || (arguments[0] == "multi")) {
      multi = ((arguments[0]=="multi") ? "true" : arguments[0]);
      tmp = ((arguments[1] != null) ? arguments[1] : "");
    }
    else {
      tmp = ((arguments[0] != null) ? arguments[0] : "");
    }
    tmp = expEncode(tmp);

    materialUrl += "&multiselect="+multi;
    if (tmp != "") materialUrl += "&prevmaterialmasterkey="+tmp;

    popupPickerWindow(materialUrl, "PICKER", "680", "540") ;
  } // ENDS materialPickerPopUp

  function safetyViolationPickerPopUp() {
    var safetyViolationUrl = 'safetyviolationpicker.do?action=show';
    var tmp = ((arguments[0] != null) ? arguments[0] : "");
    tmp = expEncode(tmp);
    safetyViolationUrl += "&selectedcodes="+tmp;

    popupPickerWindow(safetyViolationUrl, "PICKER", "680", "540") ;
  } // ENDS safetyViolationPickerPopUp

// -- End Popup Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Cookie Utilities
// ---------------------------

  // http://www.webreference.com/js/column8/index.html

  /*
    If you provide a date in the past, the cookie is instantly deleted. JavaScript's
    built-in toGMTString() method converts an instance of the Date object to the
    required date format. If the expires attribute isn't specified, the cookie expires
    when the user's session ends.

    When searching for valid cookies, the browser compares the domain attribute of each
    cookie to the current server's domain name. The browser looks for a tail match. For
    example, a domain name of ".internet.com" would tail match "www.internet.com" as
    well as "search.internet.com". A domain name must consist of at least two periods in
    a top-level domain (e.g., com, edu, net, org, gov, mil, int), and at least three in
    any other one (e.g., co.il, ac.il). The default value of the domain attribute is the
    host name of the server that set the cookie. Setting the domain of the cookie allows
    pages on a domain made up of more than one server (cross sub-domains) to share
    cookie information. A cookie will not be read by search.site.com when its domain is
    www.site.com. When setting the domain to site.com, the search sub-domain may also
    read the cookie. A cookie cannot have its domain set to a domain which the page is
    not in, basically you cannot make the domain www.microsoft.com.

    The path attribute specifies a subset of URLs in a domain for which a cookie is
    valid. After the domain is matched, the pathname component of the URL is compared
    with pathname (the value of the path attribute), and, if successful, the cookie is
    considered valid and is sent along with the HTTP request. The path "/foo" would
    match "/foobar" and "/foo/bar/html". "/" is the most general path. If a path is not
    specified, it defaults to the path of the document or script that set the cookie.

    If you specify the word secure in the Set-Cookie field, the cookie will only be
    transmitted across a secured communication channel between the client and the
    server. If this attribute is not specified, the cookie will be sent over any
    channel, including an unsecured one.
  */

  function setCookie(cookieName, cookieValue, expires, path, domain, secure) {
    // expires date is calculated by 1000 * 60 * 60 * 24 * 1 = today
    // 1000 milliseconds
    // 60 seconds
    // 60 minutes
    // 24 hours
    // 1 day

    // ---------------------------
    // [expires] - expiration date of the cookie (defaults to end of current session)
    // [path] - path for which the cookie is valid (defaults to path of calling document)
    // [domain] - domain for which the cookie is valid (defaults to domain of calling document)
    // ---------------------------

    if (cookieName != null || cookieName != '') {
      document.cookie =
        expEncode(cookieName) + '=' + (cookieValue ? expEncode(cookieValue) : '')
        + (expires ? '; EXPIRES=' + (expires == 'DELETE' ? 'Thu, 01-Jan-70 00:00:01 GMT' : expires.toGMTString()) : '')
        + (path ? '; PATH=' + path : '')
        + (domain ? '; DOMAIN=' + domain : '')
        + (secure ? '; SECURE' : ''); // needed for HTTPS cookies
    }
  } // ENDS setCookie

  function getCookie(cookieName) {
    var cookieValue = null;

    var posName = document.cookie.indexOf(expEncode(cookieName) + '=');
    if (posName != -1) {
      var posValue = posName + (expEncode(cookieName) + '=').length;
      var endPos = document.cookie.indexOf(';', posValue);
      if (endPos != -1) {
        cookieValue = expDecode(document.cookie.substring(posValue, endPos));
      }
      else {
        cookieValue = expDecode(document.cookie.substring(posValue));
      }
    }

    // cookie value is a string... so return a boolean if applicable
    if ((cookieValue == 'true') || (cookieValue == 'TRUE')) return true;
    if ((cookieValue == 'false') || (cookieValue == 'FALSE')) return false;

    return cookieValue;
  } // ENDS getCookie

  function deleteCookie(cookieName, path, domain) {
    // ---------------------------
    // [path] - path of the cookie (must be same as path used to create cookie)
    // [domain] - domain of the cookie (must be same as domain used to create cookie)
    // path and domain default if assigned null or omitted if no explicit argument proceeds
    // ---------------------------
    if (getCookie(cookieName)) {
      setCookie(cookieName, 'DELETED', 'DELETE', path, domain);
    }
  }

  function setSessionCookie(cookieName, cookieValue, path, domain) {
    setCookie(cookieName, cookieValue, null, path, domain);
  }

  function setPersistentCookie(cookieName, cookieValue, path, domain) {
    setTemporaryCookie(cookieName, cookieValue, 365, path, domain); // expire in 365 days
  }

  function setTemporaryCookie(cookieName, cookieValue, days, path, domain) {
    var now = new Date();
    var when = new Date(now.getTime() + 1000 * 60 * 60 * 24 * days);
    setCookie(cookieName, cookieValue, when, path, domain);
  }

// -- End Cookie Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Form Verification Utilities
// ---------------------------

  // return true/false if content of element is a valid email address. If not, warning that name is not a valid email address
  function isValidEmail(element, emailID) {
    var email = element.value;

    // ----------------------------------------------
    // pattern test - not verified yet
    // emailPattern = /^(\w+\.)*(\w+)@(\w+\.)+([a-zA-Z]{2,4})$/
    // return (emailPattern.test(email));
    // ----------------------------------------------

    var sign=email.indexOf("@");
    var before=email.substring(0,sign);
    var after=email.substring(sign+1,email.length);
    var lower=after.toLowerCase();
    var coma=before.indexOf(",");
    var period=after.indexOf(".");
    var spc=email.indexOf(" ");

    var isValid=false;
    if (sign == 0) {
      warning("EMAIL: User id is missing before the @.");
      isValid=true;
    } else if (sign == -1) {
      warning("EMAIL: You need an @ somewhere in the address.");
      isValid=true;
    } else if (sign == (email.length-1)) {
      warning("EMAIL: Missing host name after the @.");
      isValid=true;
    } else if (email.indexOf("@",sign+1) != -1) {
      warning("EMAIL: Only one @ for valid email address.");
      isValid=true;
    } else if (email.indexOf("@.") != -1) {
      warning("EMAIL: Invalid email address format, @.");
      isValid=true;
    } else if (email.indexOf("..") != -1) {
      warning("EMAIL: Invalid email address format, ..");
      isValid=true;
    } else if (after.indexOf(",") != -1) {
      warning("EMAIL: Invalid email address format");
      isValid=true;
    } else if (after.indexOf("/") != -1) {
      warning("EMAIL: Invalid email address format");
      isValid=true;
    } else if (after.lastIndexOf(".") == after.length-1) {
      warning("EMAIL: Address can't end in dot");
      isValid=true;
    } else if (coma >= 0) {
      warning("EMAIL: You must change the comma to a period in the first part of the address.")
      isValid=true;
    } else if (period == -1) {
      warning("EMAIL: You need a period in the second part of the address");
      isValid=true;
    } else if (spc != -1) {
      warning("EMAIL: Please Remove any spaces from your email address");
      isValid=true;
    }
    if (isValid) warning(emailID + " is not a valid email address.");

    return !isValid;
  } // ENDS isValidEmail

  // return true/false if form element is not null. Handles form element types of text,password,hidden,textarea,select and radio
  function isElementNotNull(formElement, errorMsg) {
    var formElementIsNotNull = true;

    if ((formElement.type == "text") || (formElement.type == "password") || (formElement.type == "hidden") || (formElement.type == "textarea")) {
      if (formElement.value == "") {
        warning(errorMsg);
        formElement.select();
        formElementIsNotNull = false;
      }
    } else if ((formElement.type == "select-one") || (formElement.type == "select-multiple")) {
      if (formElement.options[formElement.options.selectedIndex].value == "") {
        warning(errorMsg);
        formElement.select();
        formElementIsNotNull = false;
      }
    } else if (formElement[0].type == "radio") {
      var radioSelected = false;
      var x=0;
      while(formElement[x]) {
        if (formElement[x].type == "radio") {
          if (formElement[x].status) radioSelected = true;
        }
        x++;
      }
      if (!radioSelected) {
        warning(errorMsg);
        formElement[0].select();
        formElementIsNotNull = false;
      }
    }

    return formElementIsNotNull;
  } // ENDS isElementNotNull

  function convertFormCase(formElement, changeCase) {
    if (formElement.type == "text") {
      formElement.value = convertCase(formElement.value, changeCase);
    }
  }

// -- End Form Verification Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// String Utilities
// ---------------------------

  function replaceStringWithString(theStr, replaceStr, withStr) {
    if ((theStr == "") || (replaceStr == "")) return theStr;

    var listOfNonRegExpChars = "~*~+~^~|~$~(~)~[~]~<~>~.~:~?~\\~";

    var nonregexp = false;

    if (listOfNonRegExpChars.indexOf("~"+replaceStr+"~") != -1) {
      nonregexp = true;
    }
    else {
      try {
        var pattern = new RegExp (replaceStr,'ig'); // i = case-insensitive; g = global

        theStr = theStr.replace(pattern, withStr);

        if ((arguments[3] != null) && (eval(arguments[3]))) {
          while (theStr.indexOf(replaceStr) != -1) {
            theStr = theStr.replace(pattern, withStr);
          }
        }
      }
      catch(e) {
        nonregexp = true;
      }
    }

    // slower method which does not use a regular expresion replace
    if (nonregexp) {
      while (theStr.indexOf(replaceStr) != -1) {
        theStr = theStr.substring(0, theStr.indexOf(replaceStr)) + withStr + theStr.substring(theStr.indexOf(replaceStr)+1);
      }

      if ((arguments[3] != null) && (eval(arguments[3]))) {
        while (theStr.indexOf(replaceStr) != -1) {
          theStr = theStr.substring(0, theStr.indexOf(replaceStr)) + withStr + theStr.substring(theStr.indexOf(replaceStr)+1);
        }
      }
    }

    return theStr;
  } // ENDS replaceStringWithString

  // trim the passed string (remove leading and trailing spaces)
  String.prototype.trim = function() {
    try {
      // optimal
      return this.replace(/^\s*(\b.*\b|)\s*$/, "$1");
    }
    catch(e) {
      var trimText = this;

      while(''+trimText.charAt(0) == ' ') {
        trimText = trimText.substring(1,trimText.length);
      }

      while(''+trimText.charAt(trimText.length-1) == ' ') {
        trimText = trimText.substring(0,trimText.length-1);
      }

      return trimText;
    }
  }

  // trim the passed value (remove leading and trailing spaces)
  function trim(trimText) {
    // if the trimText is not a string type then we make it a string
    return (''+trimText).trim();
  } // ENDS trim

  function replaceEscapeChars(value) {
    if (value == null) {
      return (null);
    }

    len = value.length;
    result = "";

    for (var i = 0; i < len; i++) {
      result = result + value.charAt(i);
      if (value.charAt(i)=="\\") {
        result = result + "\\";
      }
    }

    return result;
  } // ENDS replaceEscapeChars

  function replaceQuotes(value) {
    if (value == null) {
      return (null);
    }

    var result = value;

    var quotpattern = new RegExp ("\"",'ig'); // i = case-insensitive; g = global
    var singlequotepattern = new RegExp ("'",'ig'); // i = case-insensitive; g = global
    // amp needs to be done first, otherwise the inserted amps get replaced again
    result = result.replace(quotpattern, "\\\"");
    result = result.replace(singlequotepattern, "\\\'");

    return result;
  } // ENDS replaceQuotes

  function filter(value) {
    if (value == null) {
      return (null);
    }

    var result = value;

    var amppattern = new RegExp ("&",'ig'); // i = case-insensitive; g = global
    var ltpattern = new RegExp ("<",'ig'); // i = case-insensitive; g = global
    var gtpattern = new RegExp (">",'ig'); // i = case-insensitive; g = global
    var quotpattern = new RegExp ("\"",'ig'); // i = case-insensitive; g = global
    var singlequotepattern = new RegExp ("'",'ig'); // i = case-insensitive; g = global

    // amp needs to be done first, otherwise the inserted amps get replaced again
    result = result.replace(amppattern, "&amp;");
    result = result.replace(ltpattern, "&lt;");
    result = result.replace(gtpattern, "&gt;");
    result = result.replace(quotpattern, "&quot;");
    result = result.replace(singlequotepattern, "&#39;");

    // DO NOT FILTER SPACE or MINUS
    // filter minus with <strike>&nbsp;</strike> at the point where it is needed

    if ((arguments[1] != null) && (arguments[1] == "special")) {
      var brpattern = new RegExp ("&lt;br&gt;",'ig'); // i = case-insensitive; g = global
      result = result.replace(brpattern, "<br>");
    }

    return result;
  } // ENDS filter

  function reverseFilter(value) {
    if (value == null) {
      return (null);
    }

    var result = value;

    var amppattern = new RegExp ("&amp;",'ig'); // i = case-insensitive; g = global
    var ltpattern = new RegExp ("&lt;",'ig'); // i = case-insensitive; g = global
    var gtpattern = new RegExp ("&gt;",'ig'); // i = case-insensitive; g = global
    var quotpattern = new RegExp ("&quot;",'ig'); // i = case-insensitive; g = global
    var singlequotpattern = new RegExp ("&#39;",'ig'); // i = case-insensitive; g = global
    var singlequotpatternalt = new RegExp ("&amp;#39;",'ig'); // i = case-insensitive; g = global

    result = result.replace(ltpattern, "<");
    result = result.replace(gtpattern, ">");
    result = result.replace(quotpattern, "\"");
    result = result.replace(singlequotpattern, "'");
    result = result.replace(singlequotpatternalt, "'");

    // amp needs to be done last, otherwise the inserted amps get replaced again
    result = result.replace(amppattern, "&");

    return result;
  } // ENDS reverseFilter

  // set value to case (upper, lower, capital)
  function convertCase(value, changeCase) {
    if (changeCase == "upper") {
      value = value.toUpperCase();
    }
    else {
      value = value.toLowerCase();
    }
    if (changeCase == "capital") {
      value = value.substring(0, 1).toUpperCase()+value.substring(1, value.length);
    }

    return value;
  } // ENDS convertCase

  function populateMessage(msg, arr){
    // populates the ~ in the argument message with values from the argument array.
    if(arr.length == 0) return msg;

    for(i=0; i<arr.length; i++){
      idx = msg.indexOf('~');
      if(idx == -1){
        break;
      }
      else{
        msg = msg.substring(0, idx) + arr[i] + msg.substring(idx + 1);
      }
    }

    return msg;
  } // ENDS populateMessage

  function expEncode(value) {
    var encodeURIComponentAvailable = null;
    try { encodeURIComponentAvailable = encodeURIComponent; } catch(e) {}

    var rtnValue;
    if (encodeURIComponentAvailable != null) {
      rtnValue = encodeURIComponent(value);
    }
    else {
      rtnValue = escape(value); // only for developers
    }

    return rtnValue;
  } // ENDS expEncode

  function expDecode(value) {
    var decodeURIComponentAvailable = null;
    try { decodeURIComponentAvailable = decodeURIComponent; } catch(e) {}

    var rtnValue;
    if (decodeURIComponentAvailable != null) {
      rtnValue = decodeURIComponent(value);
    }
    else {
      rtnValue = unescape(value); // only for developers
    }

    return rtnValue;
  } // ENDS expDecode

  // check that a string contains only letters and numbers
  function isAlphaNumeric(value) {
    theStr = value+""; // normalize the value

    // not a valid value
    if (theStr == "undefined" || theStr == "null" || theStr == "") return false;

    var ignoreWhiteSpace = false;
    if ((arguments[1] != null) && (arguments[1] == "ignorewhitespace")) ignoreWhiteSpace = true;

    try {
      if (UTILSFRAME.UtilitiesApplet.isAlphaNumeric(theStr, (ignoreWhiteSpace ? "true" : "false")) == "false") return false;
    }
    catch(uf) {
      if (theStr.search) {
        if ((ignoreWhiteSpace && theStr.search(/[^\w\s]/) != -1) || (!ignoreWhiteSpace && theStr.search(/\W/) != -1)) return false;
      }
    }

    return true;
  }

  // check that a string contains only letters and numbers
  function makeAlphaNumeric(value) {
    theStr = value+""; // normalize the value

    // not a valid value
    if (theStr == "undefined" || theStr == "null" || theStr == "") return "";

    var preserveWhiteSpace = false;
    if ((arguments[1] != null) && (arguments[1] == "preservewhitespace")) preserveWhiteSpace = true;

    try {
      theStr = UTILSFRAME.UtilitiesApplet.makeAlphaNumeric(theStr, (preserveWhiteSpace ? "true" : "false"));
    } catch(uf) { /* do nothing */ }

    return theStr;
  }

// -- End String Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Currency Utilties
// ---------------------------

  // ------------------------------------------------------------------------------
  // the .toFixed(x) function will round a number to the X number of decimal places
  // This prototype function is for browsers older than NS6 and IE5.5 which do not
  // support the .toFixed(x) function. With this the .toFixed(x) function can be
  // generically used anywhere.
  if ((typeof(Number) != 'undefined') && (typeof(Number.prototype) != 'undefined')) {
    if (typeof(Number.prototype.toFixed) == 'undefined') {

      function Number_toFixed(d) {
        var n = this;
        d = d || 2;
        var f = Math.pow(10, d);
        n = Math.round(n * f) / f;
        n += Math.pow(10, - (d + 1));
        n += '';
        return d == 0 ? n.substring(0, n.indexOf('.')) : n.substring(0, n.indexOf('.') + d + 1);
      }

      Number.prototype.toFixed = Number_toFixed;
    }
  } // ENDS Number.prototype
  // ------------------------------------------------------------------------------

  function isValidNumber(value) {
    var retVal = "true"; // just allow the value - the backend will catch the mistake
    try { retVal = UTILSFRAME.UtilitiesApplet.isValidNumber(""+value); } catch(uf) { retVal = "true" }
    return (retVal == "true");
  }

  function validateNumber(value) {
    var validFlag = true;
    var alertMsg = "";
    var decimalSymbol = ".";
    try { decimalSymbol = UTILSFRAME.UtilitiesApplet.getDecimalSeparator(); } catch(uf) { decimalSymbol = "."; }

    if (arguments[1] != null && arguments[1] == "int") {
      if (((""+value).indexOf(decimalSymbol) != -1) || ((""+value).indexOf("/") != -1)) {
        try { alertMsg = UTILSFRAME.invalidWholeNumberMsg; } catch(uf) { alertMsg = "This number must be a whole value."; }

        validFlag = false;
      }
    }
    var iLength = null;
    var iDecimal = null;

    if (arguments[2]!=null) {
      iLength = eval(arguments[2]);
    }
    if (arguments[3]!=null) {
      iDecimal = eval(arguments[3]);
    }
    if (isValidNumber(value) != true) {
      try {
        if(arguments[1] !=null && arguments[1]=="intbutnomessage"){
          alertMsg += UTILSFRAME.getInvalidNumberMsg(iLength, iDecimal,"intbutnomessage");
        }
        else{
          alertMsg += UTILSFRAME.getInvalidNumberMsg(iLength, iDecimal);
        }
      }
      catch(uf) {
        alertMsg += "Please review this number.\n\nIt should not have letters, spaces, or other characters.\n\n\xB0 Use a period (.) for a decimal symbol.\n\xB0 Use a minus sign (-) for negative numbers.";
      }

      validFlag = false;
    }

    if (!validFlag) {
      //if (!uiAlert) expAlert(alertMsg); else return;
      expAlert(alertMsg);
    }

    if (validFlag) try { uiAlert = false; } catch(a) { /* do nothing */ }
    else try { uiAlert = true; } catch(a) { /* do nothing */ }

    return validFlag;
  } // ENDS validateNumber

  function validatePositiveNumber(value, allowThousSeparator) {
    var validFlag = true;
    var alertMsg = "";

    if (allowThousSeparator) {
      value = removeCommas(value);
    }
    else {
      try { value = UTILSFRAME.UtilitiesApplet.fixDecimalSymbol(value); } catch(uf) { value = removeCommas(value); }
    }

    if (isNaN(value) == true || (isNaN(value) == false && eval(value) < 0)) {
      try { alertMsg = UTILSFRAME.invalidPositiveNumberMsg; } catch(uf) { alertMsg = "Please review this number.\n\n\xB0 It should not have letters, spaces, or other characters.\n\xB0 It should not be negative."; }

      if (allowThousSeparator) {
        try { alertMsg += UTILSFRAME.getInvalidPositiveNumberThousMsg(); } catch(uf) { alertMsg += "\n\xB0 Use a comma (,) for a thousands separator."; }
      }

      validFlag = false;
    }

    if (!validFlag) {
      //if (!uiAlert) expAlert(alertMsg); else return;
      expAlert(alertMsg);
    }

    if (validFlag) try { uiAlert = false; } catch(a) { /* do nothing */ }
    else try { uiAlert = true; } catch(a) { /* do nothing */ }

    return validFlag;
  } // ENDS validateNumber

  function validRange(value, min, max) {
    value = removeCommas(value);

    var validFlag = true;

    if (value < min) {
      var warningMsg = "";
      try { warningMsg = UTILSFRAME.invalidRangeMsg; } catch(uf) { warningMsg = "invalid number"; }
      warning(warningMsg);
      validFlag = false;
    }
    else if (value > max) {
      validFlag = false;
    }

    return validFlag;
  } // ENDS validRange

  function decimalFormatter(value, decimal) {
    var ret = value;
    try { ret = UTILSFRAME.UtilitiesApplet.getFormattedNumber(value, decimal); } catch(uf) { /* do nothing */ }
    return ret;
  } // ENDS decimalFormatter

  function currencyFormatter(value, decimal) {
    var ret = value;
    try { ret = UTILSFRAME.UtilitiesApplet.getFormattedCurrency(value, decimal); } catch(uf) { /* do nothing */ }
    return ret;
  } // ENDS currencyFormatter

  function toFixed(value, decimal) {
    var longValue = Number("1e"+decimal);
    var fixedValue = new String(Math.round(value*longValue)/longValue);
    if (fixedValue.indexOf('e') == -1) {
      while ((longValue = fixedValue.indexOf('.')) == -1) {
        fixedValue += '.';
      }
      while (fixedValue.length <= longValue+decimal) {
        fixedValue += '0';
      }
    }
    return fixedValue
  } // ENDS toFixed

  function setThousandSeparator(value) {
    var returnVal = '';
    var count = 0;
    var decimalPart = '';
    var preceedingSign = '';
    value = removeCommas(value);
    if (value.indexOf(".")>0) {
      decimalPart = value.substring(value.indexOf("."));
      if (value.charAt(0) == '-') {
        preceedingSign = value.charAt(0);
        value = value.substring(1,value.indexOf("."));
      }
      else {
        value = value.substring(0,value.indexOf("."));
      }
    }
    if (value.length > 3) {
      var iDigits = value.length % 3;
      var insertComma = false;
      for (var k = 0; k < iDigits; k++) {
        returnVal = returnVal + value.charAt(count);
        count++;
        insertComma = true;
      }
      for (;;) {
        if (count > value.length-1) {
          break;
        }
        // To avoid a comma, if number of digits are a multiple of 3.
        if (insertComma) {
          returnVal = returnVal + ',';
        }
        insertComma = true;
        returnVal = returnVal + value.charAt(count);
        count++;
        returnVal = returnVal + value.charAt(count);
        count++;
        returnVal = returnVal + value.charAt(count);
        count++;
      }
    }
    else {
      returnVal = value;
    }
    if (decimalPart != '') {
      returnVal = preceedingSign + returnVal + decimalPart;
    }

    return returnVal;
  } // ENDS setThousandSeparator

  function validateCurrency(value) {
    var validFlag = true;
    var alertMsg = "";

    if (arguments[1] != null && arguments[1] == "int") {
      if (((""+value).indexOf(".") != -1) || ((""+value).indexOf("/") != -1)) {
        try { alertMsg = UTILSFRAME.invalidWholeNumberMsg; } catch(uf) { alertMsg = "This number must be a whole value."; }

        validFlag = false;
      }
    }

    if (isNaN(value) == true) {
      try { alertMsg += UTILSFRAME.getInvalidCurrencyMsg(); } catch(uf) { alertMsg += "Please review this number.\n\nIt should not have letters, spaces, or other characters.\n\n\xB0 Use a period (.) for a decimal symbol.\n\xB0 Use a comma (,) for a thousands separator.\n\xB0 Use a minus sign (-) for negative numbers.\n\nExample: -99,999.99"; }

      validFlag = false;
    }

    if (!validFlag) {
      //if (!uiAlert) expAlert(alertMsg); else return;
      expAlert(alertMsg);
    }

    if (validFlag) try { uiAlert = false; } catch(a) { /* do nothing */ }
    else try { uiAlert = true; } catch(a) { /* do nothing */ }

    return validFlag;
  } // ENDS validateCurrency

  function validateMaxLength(value, maxLength) {
    var validFlag = true;
    var alertMsg = "";
    var decimalSymbol = '.';
    var minusSymbol = '-';

    value = removeCommas(value);

    try { alertMsg = UTILSFRAME.invalidMaxLengthMsg; } catch(uf) { alertMsg = "This number cannot contain more than ~ digits before the decimal point."; }
    alertMsg = replaceStringWithString(alertMsg, "~", maxLength);

    if (value.indexOf(decimalSymbol) > 0) value = value.substring(0,value.indexOf(decimalSymbol));
    if (value.charAt(0) == minusSymbol) value = value.substring(1);
    if (value.length > maxLength) {
      validFlag = false;
    }

    if (!validFlag) {
      //if (!uiAlert) expAlert(alertMsg); else return;
      expAlert(alertMsg);
    }

    if (validFlag) try { uiAlert = false; } catch(a) { /* do nothing */ }
    else try { uiAlert = true; } catch(a) { /* do nothing */ }

    return validFlag;
  } // ENDS validateMaxLength

  function removeCommas(value) {
    if (trim(value) == ''){
      value = 0;
    }
    var ret = value;
    try { ret = UTILSFRAME.UtilitiesApplet.removeFormatting(value); } catch(uf) { /* do nothing */ }
    return ret;
  } // ENDS removeCommas

// -- End Currency Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// LUW Utilities
// ---------------------------

  var formDirty = false;

  // set the current form clean (used by the main detail form and child forms)
  function setFormClean() { formDirty = ((arguments[0] == null || arguments[0] == "") ? false : arguments[0]); }

  // set the current form dirty (used by the main detail form and child forms)
  function setFormDirty() { formDirty = ((arguments[0] == null || arguments[0] == "") ? true : arguments[0]); }

  // return (true/false) if the current form is dirty (used by the main detail form and child forms)
  function isFormDirty() { return formDirty; }

  // set all children clean for the current form (clears the dirty children list and sets the dirty child flag)
  function cleanDirtyChildren() {
    try {
      var isPresent = top.logframe.document.forms[0].dirtyChildren;
      top.logframe.document.forms[0].dirtyChildren.value = "";
      setChildClean();
    } catch(e) { if (isPresent!=null) displayError("utilities:cleanDirtyChildren.",e,DEBUGWARNING); }
  } // ENDS cleanDirtyChildren

  // add a dirty child to the list on the current form and set the dirty child flag
  function addDirtyChildren(childSection) {
    try {
      var isPresent = top.logframe.document.forms[0].dirtyChildren;
      dirtyChildren = (top.logframe.document.forms[0].dirtyChildren.value).split("<br>");
      alreadyDirty = false;

      for (var i = 0; i < dirtyChildren.length; i++) if (dirtyChildren[i] == childSection) { alreadyDirty = true; break; }

      if (!alreadyDirty) {
        if (top.logframe.document.forms[0].dirtyChildren.value != "") childSection = "<br>" + childSection
        top.logframe.document.forms[0].dirtyChildren.value = getDirtyChildren() + childSection;
      }
      setChildDirty();
    } catch(e) { if (isPresent!=null) displayError("utilities:addDirtyChildren.",e,DEBUGMODERATE); }
  } // ENDS addDirtyChildren

  // return (true/false) if any children are dirty within the current form
  function isChildDirty() {
    return eval((top.logframe.document.forms[0].childDirty.value == null || top.logframe.document.forms[0].childDirty.value == "") ? "false" : top.logframe.document.forms[0].childDirty.value);
  }

  // return the list of dirty children for the current form
  function getDirtyChildren() {
    return ((top.logframe.document.forms[0].dirtyChildren.value == null || top.logframe.document.forms[0].dirtyChildren.value == "") ? "" : top.logframe.document.forms[0].dirtyChildren.value);
  }

  // set all child flag to clean within the current form
  // typically this will only get called from the cleanDirtyChildren function
  // but was seperated for possible blind UI tasks
  function setChildClean() {
    try {
      var isPresent = top.logframe.document.forms[0].childDirty;
      top.logframe.document.forms[0].childDirty.value = ((arguments[0] == null || arguments[0] == "") ? "false" : arguments[0]);
    } catch(e) { if (isPresent!=null) displayError("utilities:setChildClean.",e,DEBUGWARNING); }
  }

  // set that a child is dirty within the current form
  // typically this will only get called from the addDirtyChildren function
  // but was seperated for possible blind UI tasks
  function setChildDirty() {
    try {
      var isPresent = top.logframe.document.forms[0].childDirty;
      top.logframe.document.forms[0].childDirty.value = ((arguments[0] == null || arguments[0] == "") ? "true" : arguments[0]);
    } catch(e) { if (isPresent!=null) displayError("utilities:setChildDirty.",e,DEBUGWARNING); }
  }

  // our modal window tracker
  var mModalWindow = null;

  function triggerDirty(theDocument) {
    //make sure the onchange is triggered by changing focus of the form elements
    var firstElement, nextElement = 0;
    try {
      for (firstElement = 0; firstElement < theDocument.forms[0].elements.length; firstElement++) {
        try {
          theDocument.forms[0].elements[firstElement].focus();
          break;
        } catch(not_able_to_focus) { /* do nothing */ }
      }
      for (nextElement = firstElement+1; nextElement < theDocument.forms[0].elements.length; nextElement++) {
        try {
          theDocument.forms[0].elements[nextElement].focus();
          break;
        } catch(not_able_to_focus) { /* do nothing */ }
      }

      if (firstElement > 0) theDocument.forms[0].elements[firstElement].focus();
    } catch(no_element) { /* do nothing */ }
  } // ENDS triggerDirty

  function openConfirmWindow(type) {
    if ((!mModalWindow) || (mModalWindow.closed)) {

      // override width and height as appropriate
      width=350; height=200;

      if (type=="SAVE") {
        windowName = "CONFIRMSAVE";
        height=210;
        strHref = "confirmsave.jsp";
      } else if (type=="LEAVE") {
        windowName = "CONFIRMLEAVE";
        height = 120;
        strHref = "confirmleave.jsp";
      } else if (type=="BREADCRUMBLEAVE") {
        windowName = "CONFIRMBREADCRUMBLEAVE";
        height = 120;
        strHref = "confirmbreadcrumbleave.jsp";
      } else if (type=="LOGOUTLEAVE") {
        windowName = "CONFIRMLOGOUTLEAVE";
        height = 120;
        strHref = "confirmlogout.jsp";
      } else if (type=="CHILDSAVE") {
        windowName = "CONFIRMCHILDSAVE";
        height = 130;
        strHref = "confirmchildsave.jsp";
      } else if (type=="CHILDSAVETOLINK") {
        windowName = "CONFIRMCHILDSAVETOLINK";
        height = 210;
        strHref = "confirmchildsavetolink.jsp";
      } else if (type=="CANCELPARENT") {
        windowName = "CONFIRMCANCEL";
        height = 120;
        strHref = "cancelparent.jsp";
      } else if (type=="CANCELCHILD") {
        windowName = "CONFIRMCANCEL";
        height = 320;
        strHref = "cancelchild.jsp";
      } else if (type=="CANCELPARENTCHILD") {
        windowName = "CONFIRMCANCEL";
        height = 250;
        strHref = "cancelparentchild.jsp";
      } else if (type=="DELETEFROMINBOX") {
        windowName = "CONFIRMDELETEFROMINBOX";
        height = 120;
        strHref = "confirmdeletefrominbox.jsp";
      } else if (type=="FORWARD") {
        windowName = "CONFIRMFORWARD";
        height = 120;
        strHref = "confirmforward.jsp";
      } else if (type=="CANCELPRINT") {
        windowName = "CONFIRMCANCELPRINT";
        height = 120;
        strHref = "cancelprint.jsp";
      } else if (type=="SPELLINGCOMPLETE") {
        windowName = "SPELLINGCOMPLETE";
        height = 120;
        strHref = "confirmspellingcomplete.jsp";
      } else if (type=="CONFIRMQUEUEREMOVE") {
        windowName = "CONFIRMQUEUEREMOVE";
        height = 120;
        strHref = "confirmremove.jsp?action=remove";
      } else if (type=="CONFIRMQUEUEREMOVEALL") {
        windowName = "CONFIRMQUEUEREMOVEALL";
        height = 120;
        strHref = "confirmremove.jsp?action=removeall&totalrows="+arguments[1];
      } else if (type=="CONFIRMMESSAGE") {
        windowName = "CONFIRMMESSAGE";
        height = 200;
        if (arguments[3] != null) {
          height = eval(arguments[3]);
        }
        var textAlign = "center";
        if (arguments[4] != null) {
          textAlign = arguments[4];
        }
        strHref = "confirmmessage.jsp?custommessage=" + expEncode(arguments[1]) + "&buttontypes="+arguments[2] + "&align=" + textAlign;
      } else if (type=="RETURN") {
        windowName = "CONFIRMRETURN";
        height = 160;
        strHref = "confirmreturn.jsp";
      } else if (type=="RETURNLETTERTEMPLATE") {
        windowName = "CONFIRMRETURN";
        height = 120;
        strHref = "confirmreturnletter.jsp";
      } else if (type=="RETURNDISTRIBUTION") {
        windowName = "CONFIRMRETURN";
        height = 120;
        strHref = "confirmreturndistribution.jsp";
      } else if (type=="SWITCHTOADVANCED") {
        windowName = "SWITCHTOADVANCED";
        height = 160;
        strHref = "confirmadvanced.jsp";
      } else if (type=="SAVEASMYLAYOUT") {
        windowName = "SAVEASMYLAYOUT";
        height = 160;
        strHref = "confirmsaveasmylayout.jsp?custommessage=" + expEncode(arguments[1]);
      } else if (type=="SEARCHLEAVE") {
        windowName = "CONFIRMSEARCHLEAVE";
        height = 120;
        strHref = "confirmsearchleave.jsp";
      } else if (type=="CMPHASELEAVE") {
        windowName = "CMPHASELEAVE";
        height = 120;
        strHref = "cmphaseleave.jsp";
      } else if (type=="CONFIRMRECALC") {
        windowName = "CONFIRMRECALC";
        height = 120;
        strHref = "confirmrecalc.jsp?href="+expEncode(arguments[1]);
      }

      strFeatures = "scrollbars=no,resizable=no,width="+width+",height="+height+","+centerWindow(width, height);

      mModalWindow = window.open(strHref, 'ALERT', strFeatures);
      if (mModalWindow.opener == null) mModalWindow.opener = self;
    }
    else {
      //don't open a new window if one already exsists
      mModalWindow.focus();
    }
  } // ENDS openConfirmWindow

  function cancelProcessRequest() {
    var theForm=document.forms[0];

    if (theForm.elements("action") != null) theForm.elements("action").value="save";
    if (theForm.elements("href") != null) theForm.elements("href").value="";
    if (theForm.elements("windowName") != null) theForm.elements("windowName").value="";
    if (theForm.elements("features") != null) theForm.elements("features").value="";
    if (theForm.elements("gotoId") != null) theForm.elements("gotoId").value="";
    if (theForm.elements("pageAnchor") != null) theForm.elements("pageAnchor").value="";
    clearJumpBack();
  } // ENDS cancelProcessRequest

  // when the main window has focus confirm leaving the current form via opening a child window (add or edit)
  function processPopupRequest(strPageAnchor, strHref, windowName, strFeatures) {
    var theForm=document.forms[0];

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;
    if (!fromView) {

      // don't have to force onchange here, since clicking on the screen will trigger the onchange.

      if (isFormDirty()) {
        theForm.elements("href").value=strHref;
        theForm.elements("windowName").value=windowName;
        theForm.elements("features").value=strFeatures;
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value=strPageAnchor;
        theForm.elements("action").value="saveedit";

        var prefFrame = top.preferencesframe;

        // we might be in a child window
        if (prefFrame==null) {
          prefFrame = window.opener.top.preferencesframe;
        }

        if ((prefFrame!=null) && prefFrame.getHideDirtySave()) {
          validate();
        }
        else {
          openConfirmWindow("SAVE");
        }
      }
      else {
        theForm.elements("gotoId").value="";
        if (theForm.elements("pageAnchor") != null) {
          theForm.elements("pageAnchor").value=strPageAnchor;
        }
        popupChildWindow(strHref, windowName, strFeatures);
      }
    }
    else {
      if (theForm.elements("pageAnchor") != null) {
        theForm.elements("pageAnchor").value=strPageAnchor;
      }
      popupChildWindow(strHref, windowName, strFeatures);
    }
  } // ENDS processPopupRequest

  // when the main window has focus confirm leaving the current form via opening a child picker window (add or edit)
  // which behaves more like a child window (ie. issues picker)
  function processPickerRequest(strPageAnchor, strHref, windowName, strFeatures) {
    var theForm=document.forms[0];

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;
    if (!fromView) {

      // don't have to force onchange here, since clicking on the screen will trigger the onchange.

      if (isFormDirty()) {
        theForm.elements("href").value=strHref;
        theForm.elements("windowName").value=windowName;
        theForm.elements("features").value=strFeatures;
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value=strPageAnchor;
        theForm.elements("action").value="saveedit";

        var prefFrame = top.preferencesframe;

        // we might be in a child window
        if (prefFrame==null) {
          prefFrame = window.opener.top.preferencesframe;
        }

        if ((prefFrame!=null) && prefFrame.getHideDirtySave()) {
          validate();
        }
        else {
          openConfirmWindow("SAVE");
        }
      }
      else {
        theForm.elements("gotoId").value="";
        if (theForm.elements("pageAnchor") != null) {
          theForm.elements("pageAnchor").value=strPageAnchor;
        }
        if (strHref == "") {
          openPickerWindow(windowName, strFeatures);
        }
        else {
          popupPickerWindow(strHref, windowName, strFeatures);
        }
      }
    }
    else {
      if (theForm.elements("pageAnchor") != null) {
        theForm.elements("pageAnchor").value=strPageAnchor;
      }
      if (strHref == "") {
        openPickerWindow(windowName, strFeatures);
      }
      else {
        popupPickerWindow(strHref, windowName, strFeatures);
      }
    }
  } // ENDS processPickerRequest

  // when the main window has focus confirm cancel of the current form
  function confirmCancel() {

    // don't have to force onchange here, since clicking on the screen will trigger the onchange.

    if (isFormDirty() && isChildDirty()) {
      openConfirmWindow("CANCELPARENTCHILD");
    }
    else if (isFormDirty()) {
      openConfirmWindow("CANCELPARENT");
    }
    else if (isChildDirty() && !top.preferencesframe.getHideDirtyCancel()) {
      // this is when we cancel the parent (not dirty) edit after changing some child data
      // this is the only time we have the checkbox (do not show again) option during a cancel
      openConfirmWindow("CANCELCHILD");
    }
    else {
      processCancel();
    }
  } // ENDS confirmCancel

  // when the child window has focus confirm cancel of a dirty child
  function confirmChildCancel() {

    // don't have to force onchange here, since clicking on the screen will trigger the onchange.

    if (isFormDirty()) {
      // we want the same cancel confirm window for the child as we do for the parent (poor naming choice)
      openConfirmWindow("CANCELPARENT");
    }
    else {
      window.close();
    }
  } // ENDS confirmChildCancel

  // when the child window has focus confirm saving a dirty child (used by the next/prev actions within the child forms)
  function confirmChildSave(strHref) {
    window.document.forms[0].gotoId.value = strHref;

    // don't have to force onchange here, since clicking on the screen will trigger the onchange.

    if (isFormDirty()) {
      if (window.opener.top.preferencesframe.getHideDirtySave()) {
        validate();
        //window.opener.top.logframe.reloadPage(); // rrl 6/23/04 - seems that this is a double reload
      }
      else {
        openConfirmWindow("CHILDSAVE");
      }
    }
    else {
      window.location.replace(strHref);
    }
  } // ENDS confirmChildSave

  // when the main window has focus confirm leaving the current form via a direct link
  // currently handling the 'return to log' and 'return to project center' links in the action frame
  function confirmLeave(strHref) {
    try {
      var doc = top.logframe.document;
      doc.forms[0].gotoId.value = strHref;

      triggerDirty(doc);

      if (top.logframe.isFormDirty()) {
        try {
          //Check for CM doc cases. As we might need to delete the phase document
          //if the user clicks NO for save. This will be used for Change Orders and
          //Proposals. : Puneet : 11/29/2002.
          var showingnewPhase = "false";
          var showingNewPhaseField = null;
          showingNewPhaseField = doc.forms[0].showingNewPhase;

          if (showingNewPhaseField == null) {
            showingnewPhase = "false";
          }
          else {
            showingnewPhase = showingNewPhaseField.value;
          }
        } catch(e) { /* do nothing */ }

        if (showingnewPhase == "true") {
          top.logframe.openConfirmWindow("CMPHASELEAVE");
        }
        else {
          top.logframe.openConfirmWindow("LEAVE");
        }
      }
      else {
        clearJumpBack();
        clearBreadCrumb();

        top.logframe.location.replace(strHref);
      }
    }
    catch(veryleast) {
      clearJumpBack();
      clearBreadCrumb();

      window.location.replace(strHref);
    }
  } // ENDS confirmLeave

  // when the main window has focus confirm leaving the current form via breadcrumb
  function confirmBreadCrumbLeave(strHref) {
    try {
      var doc = top.logframe.document;
      doc.forms[0].gotoId.value = strHref;

      triggerDirty(doc);

      if (top.logframe.isFormDirty()) {
        top.logframe.openConfirmWindow("BREADCRUMBLEAVE");
      }
      else {
        top.anchorframe.processBreadCrumbLeave(strHref);
      }
    }
    catch(veryleast) {
      top.anchorframe.processBreadCrumbLeave(strHref);
    }
  } // ENDS confirmBreadCrumbLeave

  // when the main window has focus confirm leaving the current form via breadcrumb
  function confirmSearchLeave() {
    var doc = top.logframe.document;
    var theForm = doc.forms[0];

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;
    if (!fromView) {

      // don't have to force onchange here, since clicking on the screen will trigger the onchange.

      if (top.logframe.isFormDirty()) {
        var strHref = arguments[0];
        if (strHref != null) {
          if (strHref.indexOf("action=create") != -1) {
            strHref = replaceStringWithString(strHref, "action=create", "masterkey=&action=show");
          }
          else {
            if ((theForm.elements("action").value == "save") ||
              // need to include the special case for letters
              (theForm.elements("action").value == "createletter"))
            {
              if (strHref.indexOf("?") == -1) strHref = strHref + "?masterkey=&action=show"
            }
          }
        }
        else {
          strHref = "";
        }

        theForm.elements("href").value=strHref;
        theForm.elements("windowName").value="SEARCH";
        theForm.elements("features").value="";
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value="";

        // DO NOT reset the form action to "saveedit" for confirmSearchLeave
        // theForm.elements("action").value = "saveedit";

        top.logframe.openConfirmWindow("SEARCHLEAVE");
      }
      else {
        theForm.elements("gotoId").value="";
        popupChildWindow("", "SEARCH", "");
      }
    }
    else {
      popupChildWindow("", "SEARCH", "");
    }
  } // ENDS confirmSearchLeave

  // when the main window has focus confirm leaving the current form via logging out
  function confirmLogout() {
    try {
      var doc = top.logframe.document;
      doc.forms[0].gotoId.value = "LOGOUT!";

      // DO NOT reset the form action to "saveedit" for confirmLogout
      // theForm.elements("action").value = "saveedit";

      triggerDirty(doc);

      if (top.logframe.isFormDirty()) {
        top.logframe.openConfirmWindow("LOGOUTLEAVE");
      }
      else {
        top.headerframe.processLogout();
      }
    }
    catch(veryleast) {
      top.headerframe.processLogout();
    }
  } // ENDS confirmLogout

  function saveAndEditNextChild(strHref) {
    window.document.forms[0].gotoId.value = strHref;
    validate();
  }

  function saveAndAddAnotherChild(strHref) {
    saveAndEditNextChild(strHref); // if there ever comes a time when they need to be different
  }

  // -------------------------------------------------------
  // special IE5 function map to the all collections
  // DO NOT CALL DIRECTLY
  function ie5_getElementsByTagName(str) {
    if (str == "*") return document.all
    else return document.all.tags(str)
  }

  if (document.all && is_ie5) document.getElementsByTagName = ie5_getElementsByTagName;
  // END special IE5 function map to the all collections
  // -------------------------------------------------------

  var selectEventLoop = 0; // event loop counter
  var setObj = null;
  function selectFirstElement() {

    // do not allow us to get into an event loop
    if (selectEventLoop >= 1) {
      selectEventLoop = 0;
      return;
    }
    selectEventLoop = selectEventLoop+1;

    // arguments[0] = number of elements to skip before selecting
    //                or select first element after named element
    var skipElements = null;
    var skipToElement = null;
    var skipped = 0;
    if (arguments[0] != null) {
      if (isNaN(arguments[0])) {
        skipToElement = arguments[0];
        if (skipToElement == "") skipToElement = null;
      }
      else {
        try {
          skipElements = parseInt(arguments[0]);
        }
        catch(notint) {
          skipElements = null;
        }
      }
    }

    var obj = document.getElementsByTagName("*");

    // set focus to the calling object - more than likely a document such as logframe
    try {
      // developer tool needs to be alert
      //alert("selectFirstElement (callee) => name = "+this.name+"\n"+"tagName = "+this.tagName+"\n"+"href = "+this.href+"\n"+"id = "+this.id+"\n"+"type = "+this.type+"\n"+"innerHTML = "+this.innerHTML)+"";
      this.focus();
    } catch(nofocus) { /* do nothing */ }

    // tagName is uppercase
    var tagList = "A~SELECT~INPUT~TEXTAREA~BUTTON~"

    var s=0;

    // skip to element
    if (skipToElement != null) {
      for (s=0; s<obj.length; s++) {
        if (tagList.indexOf(obj[s].tagName+"~") != -1) {
          if (obj[s].name == skipToElement) {
            break;
          }
        }
      }
      if (s >= obj.lenght) s=0;
    }

    for (var i=s; i<obj.length; i++) {
      if (tagList.indexOf(obj[i].tagName+"~") != -1) {

        try {
          // developer tool needs to be alert
          //alert("next select: "+i+"\n"+"tagName = "+obj[i].tagName+"\n"+"name = "+obj[i].name+"\n"+"href = "+obj[i].href+"\n"+"id = "+obj[i].id+"\n"+"type = "+obj[i].type+"\n"+"innerHTML = "+obj[i].innerHTML)+"";

          // tagName is uppercase
          // type is lowercase

          // can not select - obj is an anchor tag <a name=....
          if ((obj[i].tagName == "A") && (obj[i].type == "") && (obj[i].href == "")) {
            continue;
          }

          // can not select - obj is a hidden input
          if ((obj[i].tagName == "INPUT") && (obj[i].type == "hidden")) {
            continue;
          }

          // skip some number of elements
          if ((skipElements != null) && (skipElements > skipped)) {
            skipped = skipped + 1;
            continue;
          }

          obj[i].focus();

          try {
            if (((obj[i].tagName == "INPUT") && ((obj[i].type == "text") || (obj[i].type == "password"))) || (obj[i].tagName == "TEXTAREA")) {
              setCaretToBegin(obj[i]);
              setObj = obj[i];
              setTimeout("try{if(setObj!=null)setCaretToBegin(setObj);setObj=null;}catch(e){}",100);
            }
          } catch(not_able_to_set_caret) { /* do nothing */ }

          break;
        } catch(not_able_to_focus) { /* do nothing */ }
      } // ENDS if (tagList.indexOf(obj[i].tagName+";") != -1)
    } // ENDS for (var i=0; i<obj.length; i++)
  } // ENDS selectFirstElement()

// -- End LUW Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Spell Checker Utilities
// ---------------------------

  function checkSpelling() {
    try {
      var breakout = top.spellcheckerframe;
      isParent = (top.spellcheckerframe!=null);
      if (isParent) {
        top.spellcheckerframe.checkSpelling();
      }
      else {
        breakout = window.opener;
        isChild = (window.opener.top.spellcheckerframe!=null);
        if (isChild) {
          window.opener.top.spellcheckerframe.checkSpelling(window);
        }
        else {
          breakout = window.opener.opener;
          window.opener.opener.top.spellcheckerframe.checkSpelling(window);
        }
      }
    } catch(e) { if (breakout!=null) displayError("utilities:checkSpelling.",e,DEBUGMODERATE); }
  }  // ENDS checkSpelling

  function closeSpellChecker() {
    try {
      var breakout = top.spellcheckerframe;
      isParent = (top.spellcheckerframe!=null);
      if (isParent) {
        top.spellcheckerframe.closeSpellChecker();
      }
      else {
        breakout = window.opener;
        isChild = (window.opener.top.spellcheckerframe!=null);
        if (isChild) {
          window.opener.top.spellcheckerframe.closeSpellChecker();
        }
        else {
          breakout = window.opener.opener;
          window.opener.opener.top.spellcheckerframe.closeSpellChecker();
        }
      }
    } catch(e) { if (breakout!=null) displayError("utilities:closeSpellChecker.",e,DEBUGWARNING); }
  } // ENDS closeSpellChecker

  function popUpSpellCheckCompleteMessage() {
    openConfirmWindow('SPELLINGCOMPLETE');
  }

// -- End Spell Checker Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Edit Utilities
// ---------------------------

  function processEdit() {
    if ((!mModalWindow) || (mModalWindow.closed)) {
      width=350; height=200;
      strFeatures   = "scrollbars=no,resizable=no,width="+width+",height="+height+","+centerWindow(width, height);
      windowName    = "CONFIRMEDIT";

      customMessageKey = "";
      href = arguments[0];
      if (arguments[0].substring(0, 17) == "custommessagekey=") {
        customMessageKey = arguments[0].substring(0, arguments[0].indexOf("^"));
        href = arguments[0].substring(arguments[0].indexOf("^") + 1, href.length);
        strHref = "confirmedit.jsp?" + customMessageKey  + "&edithref=" + expEncode(href);
      }
      else {
        strHref = "confirmedit.jsp?edithref=" + expEncode(href);
      }

      mModalWindow = window.open(strHref, 'ALERT', strFeatures);
      if (mModalWindow.opener == null) mModalWindow.opener = self;
    }
    else {
      //don't open a new window if one already exsists
      mModalWindow.focus();
    }
  } // ENDS processEdit

// ------------------------------------------------------------
// ------------------------------------------------------------
// Delete Utilities
// ---------------------------

  function processDelete() {
    // I have not been able to confirm the need for setting the gotoId in the query string
    // for next release - double check and remove
    // see also:
    //    submittaldetailform.jsp
    //    submittaldetailformedit.jsp
    //    ACTION_MASTER_POP_S.SQL
    //    confirmdelete.jsp

    if ((!mModalWindow) || (mModalWindow.closed)) {
      if (arguments[2] != null) {
        width=350; height=arguments[2];
      }
      else if (arguments[0].substring(0,6) == "height") {
        arguments[0] = arguments[0].substring(6);
        width=350;
        height = arguments[0].substring(1,arguments[0].indexOf("^"));
        arguments[0] = arguments[0].substring(arguments[0].indexOf("^")+1);
      }
      else {
        width=350;
        height=150;
      }

      customMessageText = "";
      href = arguments[0];

      var jspName = "confirmdelete";

      if (href.indexOf("companydetail") != -1) {
        jspName = "confirmdeletecompany";
        height=175;
      }
      else if (href.indexOf("contactname") != -1) {
        jspName = "confirmdeletecontact";
        height=175;
      }

      strFeatures = "scrollbars=no,resizable=no,width="+width+",height="+height+","+centerWindow(width, height);
      windowName  = "CONFIRMDELETE";

      if (arguments[0].substring(0, 14) == "custommessage=") {
        customMessageText = arguments[0].substring(0,arguments[0].indexOf("^"));
        // We remove all the & from the customMessage because this text will be retrieved
        // through getUrlParams in confirmdelete.jsp which will NOT work if they are there - RM
        if (customMessageText.indexOf("&") > 0) {
          customMessageText = replaceStringWithString(customMessageText,"& "," ");
        }
        href = arguments[0].substring(arguments[0].indexOf("^")+1,href.length);
        strHref = jspName + ".jsp?" + customMessageText  + "&deletehref=" + expEncode(href) + "&gotoid=" + arguments[1];
      }
      else {
        strHref = jspName + ".jsp?deletehref=" + expEncode(href) + "&gotoid=" + arguments[1];
      }

      mModalWindow = window.open(strHref, 'ALERT', strFeatures);
      if (mModalWindow.opener == null) mModalWindow.opener = self;
    }
    else {
      //don't open a new window if one already exsists
      mModalWindow.focus();
    }
  } // ENDS processDelete

  // when the main window has focus confirm leaving the current form via opening a child window (add or edit)
  function processChildGridDelete(strPageAnchor, strHref, strGotoId) {

    // I have not been able to confirm the need for setting the gotoId in the query string
    // for next release - double check and remove
    // see also:
    //    submittaldetailform.jsp
    //    submittaldetailformedit.jsp
    //    ACTION_MASTER_POP_S.SQL
    //    confirmdelete.jsp

    var theForm=document.forms[0];

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;
    if (!fromView) {

      // don't have to force onchange here, since clicking on the screen will trigger the onchange.

      if (isFormDirty()) {
        theForm.elements("href").value=strHref;
        theForm.elements("windowName").value=strGotoId;
        theForm.elements("features").value="";
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value=strPageAnchor;
        theForm.elements("action").value="saveedit";

        var prefFrame = top.preferencesframe;
        // we might be in a child window
        if (prefFrame==null) {
          prefFrame = window.opener.top.preferencesframe;
        }

        if ((prefFrame!=null) && prefFrame.getHideDirtySave()) {
          validate();
        }
        else {
          openConfirmWindow("SAVE");
        }
      }
      else {
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value=strPageAnchor;
        processDelete(strHref, strGotoId);
      }
    }
    else {
      theForm.elements("pageAnchor").value=strPageAnchor;
      processDelete(strHref, strGotoId);
    }
  } // ENDS processChildGridDelete

// -- End Delete Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Link Processing Utilities
// ---------------------------

  // This methods does the actual navigation
  function navigateLink(strHref, newWindow) {
    // arguments[2] is window features or jumpBackTitle
    // arguments[3] is jumpBackLink

    if (newWindow == 1) {
      popupChildWindow(strHref, "POPUP", arguments[2]);
    }
    else {
      if (newWindow == 'closeWindow') {
        window.opener.location.replace(strHref);
        window.close();
      }
      else {

        // set the jump back
        if ((arguments[2] != null) && (arguments[3] != null) && (arguments[2] != "") && (arguments[3] != "")) {
          try {
            //Check case of CEJUMPBACK.
            if (arguments[3].indexOf("CEJUMPBACK") != -1) {
              if (relativeHREF(arguments[3]).indexOf("CEJUMPBACK") != -1) {
                setJumpBack(arguments[2], relativeHREF(arguments[3]));
              }
              else {
                setJumpBack(arguments[2], "CEJUMPBACK" + relativeHREF(arguments[3]));
              }
            }
            else {
              setJumpBack(arguments[2], relativeHREF(arguments[3]));
            }
          } catch(e) { displayError("utilities:navigateLink - setJumpBack.",e,DEBUGMODERATE); }
        }

        // clear and the following module will reset the twistie module
        top.preferencesframe.currentModule = null;

        // goto to location strHref
        if (strHref.indexOf('buildissue.do') != -1) {
          top.logframe.location.replace(strHref);
        }
        else {
          window.location.replace(strHref);
        }
      }
    }
  } // ENDS navigateLink

  // This method should be called, for navigating to linked Documents.
  function processLinkRequest(strHref, jumpBackTitle, jumpBackLink) {
    var prefFrame;
    var windowToChange;

    // we might be in a child window
    childWindow = false;

    if (top.logframe == null) {
      prefFrame = window.opener.top.preferencesframe;
      windowToChange = window.opener.top.logframe;

      windowToChange.document.isChild = true;
      childWindow = true;
    }
    else {
      prefFrame = top.preferencesframe;
      windowToChange = top.logframe;
    }

    var theForm = document.forms[0];

    document.newHref = strHref;

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;

    documentImplemented = ((arguments[3] != null) ? arguments[3] : -1);
    if (documentImplemented == 0) {
      if (strHref != "") navigateLink("unsupporteddocumentframe.jsp?url=" + expEncode(strHref), 1, "resizable=yes,width=780,height=540,left=10,top=0");
      if (childWindow) window.close();
    }
    else {
      if (!fromView) {
        triggerDirty(document);

        windowToChange.clearJumpBack();
        windowToChange.clearBreadCrumb();

        if (isFormDirty()) {
          theForm.elements("action").value="saveedit";

          windowToChange.document.forms[0].elements("gotoId").value = strHref;
          setJumpBack(jumpBackTitle, relativeHREF(jumpBackLink));
          if (prefFrame.getHideDirtySave()) {
            validate();
          }
          else {
            if (childWindow) {
              openConfirmWindow("CHILDSAVETOLINK");
            }
            else {
              openConfirmWindow("SAVE");
            }
          }
        }
        else {
          if (window != windowToChange) {
            window.close();
          }
          if (strHref != "") {
            windowToChange.navigateLink(strHref, 0, jumpBackTitle, jumpBackLink);
          }
        }
      }
      else {
        windowToChange.clearJumpBack();
        windowToChange.clearBreadCrumb();

        if (window != windowToChange) {
          window.close();
        }
        if (strHref != "") {
          windowToChange.navigateLink(strHref, 0, jumpBackTitle, jumpBackLink);
        }
      }
    }
  } // ENDS processLinkRequest

  function confirmUnlink(strHref) {
    if ((!mModalWindow) || (mModalWindow.closed)) {
      width=350; height=120;
      strFeatures = "scrollbars=no,resizable=no,width="+width+",height="+height+","+centerWindow(width, height);
      windowName  = "CONFIRMUNLINK";
      strHref     = "confirmunlink.jsp?unlinkHref=" + expEncode(strHref);

      mModalWindow = window.open(strHref, 'ALERT', strFeatures);
      if (mModalWindow.opener == null) mModalWindow.opener = self;
    }
    else {
      //don't open a new window if one already exsists
      mModalWindow.focus();
    }
  } // ENDS confirmUnlink

  function processUnlink(strHref) {
    var theForm = document.forms[0];

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;
    if (!fromView) {

      // don't have to force onchange here, since the only way to get to unlink is in the drop down.

      if (isFormDirty()) {
        theForm.elements("href").value=strHref;
        theForm.elements("features").value="";
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value="anchor_issue";
        theForm.elements("action").value="saveedit";

        var prefFrame = top.preferencesframe;
        // we might be in a child window
        if (prefFrame==null) {
          prefFrame = window.opener.top.preferencesframe;
        }

        if (prefFrame.getHideDirtySave()) {
          validate();
        }
        else {
          openConfirmWindow("SAVE");
        }
      }
      else {
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value="anchor_issue";
        confirmUnlink(strHref);
      }
    }
    else {
      theForm.elements("pageAnchor").value="anchor_issue";
      confirmUnlink(strHref);
    }
  } // ENDS processUnlink

  // return the relative href (relative to struts actions) by parsing out to the action.do?
  function relativeHREF(strHref) {
    var doIndex = strHref.indexOf(".do?");
    var reffile = strHref.substring(0, doIndex);
    reffile = reffile.substring((reffile.lastIndexOf("/") + 1), reffile.length);

    strHref = reffile + strHref.substring(doIndex, strHref.length);

    return strHref;
  } // ENDS relativeHREF

  // return the normalizedHREF href
  // -- currently we check that any #anchors are not mistakenly included as a parameter value
  function normalizeHREF(strHref) {
    var hashIndex = strHref.lastIndexOf("#");
    var ampIndex = strHref.lastIndexOf("&");

    if ((hashIndex != -1) && (ampIndex != -1) && (hashIndex > ampIndex)) {
      strHref = strHref.substring(0, hashIndex) + '&' + strHref.substring(hashIndex);
    }

    return strHref;
  } // ENDS normalizeHREF

// -- End Link Processing Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Attachment Processing Utilities
// ---------------------------

  function confirmDetachment(strHref) {
    if ((!mModalWindow) || (mModalWindow.closed)) {
      width=350; height=120;
      strFeatures = "scrollbars=no,resizable=no,width="+width+",height="+height+","+centerWindow(width, height);
      windowName  = "CONFIRMDETACHMENT";
      strHref     = "confirmdetachment.jsp?detachHref=" + expEncode(strHref);

      mModalWindow = window.open(strHref, 'ALERT', strFeatures);
      if (mModalWindow.opener == null) mModalWindow.opener = self;
    }
    else {
      //don't open a new window if one already exsists
      mModalWindow.focus();
    }
  } // ENDS confirmDetachment

  function processDetachment(strHref) {
    var theForm = document.forms[0];

    // determine if we are called from the view or edit detail
    var fromView = true;
    if (theForm.elements("action")) fromView = false;
    if (!fromView) {

      // don't have to force onchange here, since the only way to get to unlink is in the drop down.

      if (isFormDirty()) {
        theForm.elements("href").value=strHref;
        theForm.elements("features").value="";
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value="anchor_attachment";
        theForm.elements("action").value="saveedit";

        var prefFrame = top.preferencesframe;
        // we might be in a child window
        if (prefFrame==null) {
          prefFrame = window.opener.top.preferencesframe;
        }

        if (prefFrame.getHideDirtySave()) {
          validate();
        }
        else {
          openConfirmWindow("SAVE");
        }
      }
      else {
        theForm.elements("gotoId").value="";
        theForm.elements("pageAnchor").value="anchor_attachment";
        confirmDetachment(strHref);
      }
    }
    else {
      theForm.elements("pageAnchor").value="anchor_attachment";
      confirmDetachment(strHref);
    }
  } // ENDS processDetachment

// -- End Attachment Processing Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Table Sorting Utilities
// ---------------------------

  // ---------------------------
  // Sort Globals
  // ---------------------------
  var lastColumnSorted = 0;
  var lastTableSorted = 0;
  var sortAsc = true;

  // preload order images
  sort_order_asc = new Image; sort_order_asc.src = "img/sort_order_asc.gif";
  sort_order_desc = new Image; sort_order_desc.src = "img/sort_order_desc.gif";
  sort_order_none = new Image; sort_order_none.src = "img/sort_order_none.gif";

  // ---------------------------
  // Table Access
  // ---------------------------
  function createRowsArray(table) {
    var rows = new Array();
    var r = 0;
    if ((table.tHead == null) && (table.tFoot == null)) {
      for (var r1 = 0; r1 < table.rows.length; r1++, r++) {
        rows[r] = table.rows[r1];
      }
    }
    else {
      for (var t = 0; t < table.tBodies.length; t++) {
        for (var r1 = 0; r1 < table.tBodies[t].rows.length; r1++, r++) {
          rows[r] = table.tBodies[t].rows[r1];
        }
      }
    }

    return rows;
  } // ENDS createRowsArray

  function insertSortedRows(table, sortRows) {
    var tableSection;
    if ((table.tHead == null) && (table.tFoot == null)) tableSection = table;
    else tableSection = table.tBodies[table.tBodies.length - 1];

    for (var r = tableSection.rows.length-1; r >= 0; r--) {
      tableSection.deleteRow(r);
    }
    for (var r = 0; r < sortRows.length; r++) {
      tableSection.appendChild(sortRows[r]);
    }
  } // ENDS insertSortedRows

  function insertReversedOrderRows(table, sortRows) {
    var tableSection;
    if ((table.tHead == null) && (table.tFoot == null)) tableSection = table;
    else tableSection = table.tBodies[table.tBodies.length - 1];

    for (var r = tableSection.rows.length-1; r >= 0 ; r--) {
      tableSection.deleteRow(r);
    }
    for (var r = sortRows.length-1; r >= 0; r--) {
      tableSection.appendChild(sortRows[r]);
    }
  } // ENDS insertReversedOrderRows

  function sortTable(table, sortFun, preSortFun) {
    var statusMsg = "";
    try { statusMsg = UTILSFRAME.sortStatusInitMsg; } catch(uf) { statusMsg = "initializing sort..."; }
    window.status = statusMsg;
    tableId = table.id;

    reverseit = false;
    // if we are the same table as the last sort and the same column
    if (((lastTableSorted != null) && (tableId == lastTableSorted)) && ((lastColumnSorted != null) && (sortFun.col == lastColumnSorted))) { reverseit = true; }
    // if we are a different table than the last sort and sorting the last sorted column
    if ((lastTableSorted != null) && (tableId != lastTableSorted)) {
      for (var c = 0; c < table.rows[0].cells.length; c++) {
        try {
          if (document.getElementById(tableId+"_col"+c)) {
            if (document.getElementById(tableId+"_col"+c).src.indexOf(sort_order_none.src) == -1) {
              if (sortFun.col == c) {
                if (document.getElementById(tableId+"_col"+c).src.indexOf(sort_order_asc.src) != -1) { sortAsc = true; }
                else { sortAsc = false; }

                reverseit = true;
                break;
              }
            }
          } // ENDS if (document.getElementById(tableId+"_col"+c))
        }
        catch(e) { displayError("utilities:lastTableSorted.",e,DEBUGALL); }
      } // ENDS for (var c = 0; c < table.rows[0].cells.length; c++)
    } // ENDS if ((lastTableSorted != null) && (tableId != lastTableSorted))

    var sortRows = createRowsArray(table.cloneNode(true)); // deep clone to includes child nodes

    try { statusMsg = UTILSFRAME.sortStatusMsg; } catch(uf) { statusMsg = "sorting..."; }
    window.status = statusMsg;

    if (reverseit) {
      if (sortRows.length > 0) {
        insertReversedOrderRows(table, sortRows);
        sortAsc = !sortAsc;
      }
    }
    else {
      if (sortRows.length > 0) {
        if (preSortFun != null) sortRows.sort(preSortFun);

        sortRows.sort(sortFun);
        insertSortedRows(table, sortRows);
      }
    }

    try {
      if (table.rows.length > 1) {
        if ((lastTableSorted != null) && (tableId != lastTableSorted)) {
          for (var c = 0; c < table.rows[0].cells.length; c++) {
            try {
              if (document.getElementById(tableId+"_col"+c)) document.getElementById(tableId+"_col"+c).src = sort_order_none.src;
            }
            catch(e) { displayError("utilities:sortTable:"+tableId+"_col.indicator"+c+".",e,DEBUGALL); }
          }
        } // ENDS if ((lastTableSorted != null) && (tableId != lastTableSorted))
        if (((lastTableSorted != null) && (tableId == lastTableSorted)) && ((lastColumnSorted != null) && (sortFun.col != lastColumnSorted))) {
          document.getElementById(tableId+"_col"+lastColumnSorted).src = sort_order_none.src;
        }

        document.getElementById(tableId+"_col"+sortFun.col).src = ((sortAsc) ? sort_order_asc.src : sort_order_desc.src);
      } // ENDS if (table.rows.length > 1)
    }
    catch(e) { displayError("utilities:sortTable.",e,DEBUGALL); }

    refreshSortedTable(table);

    lastColumnSorted = sortFun.col;
    lastTableSorted = tableId;

    window.status = "";

    if (MASTERDEBUGLEVEL >= DEBUGWARNING) {
      window.status = "lastTableSorted = "+lastTableSorted+"        lastColumnSorted = "+lastColumnSorted+"        sorted "+sortRows.length+" rows "+((sortAsc) ? "ascending" : "descending");
    }
  } // ENDS sortTable

  function idThisSortColumn(node) {
    tableId = findTableParent(node).id;
    imgNode = findFirstLinkChild(node).firstChild;

    while (imgNode != null) {
      if ((imgNode.tagName == "IMG") && (imgNode.src.indexOf("sort_order_") != -1)) {
        imgNode.id = tableId+"_col"+node.cellIndex;
        break;
      }
      else {
        imgNode = imgNode.nextSibling;
      }
    } // ENDS while (imgNode != null)

    return findTableParent(node);
  } // ENDS idThisSortColumn

  function refreshSortedTable(table) {
    // DO NOT declare this as VAR - this variable is referenced in the refreshSortedTableRow function
    // this is the only option which can be set
    ignoreResetSelects = false;

    // special test for only resetting the selects dropdown for a row which was
    // just inserted. note: passing in -1 will result in not resetting any selects
    if ((arguments[1] != null) && (r != arguments[1])) ignoreResetSelects = true;
    else ignoreResetSelects = false;

    // DO NOT declare these as VAR - these variables are referenced in the refreshSortedTableRow function
    ignoreResetCheckboxes = false;
    ignoreResetRadiodials = false;
    refreshWhiteBgColor = getStyleClass("whitebanding", 'backgroundColor');
    refreshGrayBgColor = getStyleClass("graybanding", 'backgroundColor');
    // ENDS - DO NOT declare these as VAR

    if ((table.tHead == null) && (table.tFoot == null)) {
      for (var r = 0; r < table.rows.length; r++) {
        refreshSortedTableRow(table.rows[r], r);
      }
    }
    else {
      for (var t = 0; t < table.tBodies.length; t++) {
        var r = 0;
        var i = 0;
        while( i < table.tBodies[t].rows.length) {
          if( table.tBodies[t].rows[i].style.display != "none") {
            refreshSortedTableRow(table.tBodies[t].rows[i], r);
            r++;
          }
          i++;
        }
      }
    }
  } // ENDS refreshSortedTable

  function refreshSortedTableRow(row, r) {
    // reset row-cell colors
    bgColor = (((r % 2) == 0) ? refreshWhiteBgColor : refreshGrayBgColor);

    // refresh special child grids -- be sure that the grid table ID is unique to the system
    // CM Grid has cells set to class other than the banding
    if (findTableParent(row).id == "commitmentstable") {
      if (row.cells[0].style.backgroundColor != bgColor) {
        for (var c = 0; c < row.cells.length; c++) {

          // If the original style of the cell is neither graybanding or whitebanding then
          // do not reset the cell color
          if (row.cells[c].className == "whitebanding" || row.cells[c].className == "graybanding") {
            row.cells[c].style.backgroundColor = bgColor;
          }
        }
      }
    }

    // refresh all normal child grids
    else {
      if (row.cells[0].style.backgroundColor != bgColor) {
        for (var c = 0; c < row.cells.length; c++) {
          row.cells[c].style.backgroundColor = bgColor;
        }
      }
    }

    // checkbox elements do not keep their checked setting when sorting
    // therefore each checkbox needs to have a hidden text field associated with it, with id 'tracksort_' and the id of the checkbox
    // reset any number of checkbox in any cell within the row
    if (!ignoreResetCheckboxes) {
      var foundCheckboxToReset = false;
      for (var c = 0; c < row.cells.length; c++) {
        node = row.cells[c].firstChild;

        while (node != null) {
          if ((node.tagName == "INPUT") && (node.type == "checkbox")) {
            if (document.getElementById("tracksort_"+node.id) != null) {
              foundCheckboxToReset = true;
              node.checked = (document.getElementById("tracksort_"+node.id).value==1?true:false);
            }
            else {
              // table is not setup properly for sorting checkbox elements
              ignoreResetCheckboxes = true;
              break;
            }
          }
          node = node.nextSibling;
        }
      }
      // if we did not find a checkbox to resest in the first row
      // then do not bother checking the remaining rows - optimizing for speed
      if (!foundCheckboxToReset && r==0) ignoreResetCheckboxes = true;
    }

    // radio dial elements do not keep their selected setting when sorting
    // therefore each radio dial needs to have a hidden text field associated with it, with id 'tracksort_' and the id of the radio dial
    // reset any number of radio dial in any cell within the row
    if (!ignoreResetRadiodials) {
      var foundRadiodialToReset = false;
      for (var c = 0; c < row.cells.length; c++) {
        node = row.cells[c].firstChild;

        while (node != null) {
          if ((node.tagName == "INPUT") && (node.type == "radio")) {
            if (document.getElementById("tracksort_"+node.id) != null) {
              foundRadiodialToReset = true;
              node.checked = (document.getElementById("tracksort_"+node.id).value==1?true:false);
            }
            else {
              // table is not setup properly for sorting radio dial elements
              ignoreResetRadiodials = true;
              break;
            }
          }
          node = node.nextSibling;
        }
      }
      // if we did not find a radio dial to resest in the first row
      // then do not bother checking the remaining rows - optimizing for speed
      if (!foundRadiodialToReset && r==0) ignoreResetRadiodials = true;
    }

    // reset any number of selects (dropdowns) in any cell within the row
    // this will set the selection to the first item in the list
    // the current selection will not remain selected -- check with Russ if this needs to change
    if (!ignoreResetSelects) {
      var foundSelectToReset = false;
      for (var c = 0; c < row.cells.length; c++) {
        node = row.cells[c].firstChild;
        while (node != null) {
          if (node.tagName == "SELECT") {
            foundSelectToReset = true;
            node.selectedIndex = 0;
          }
          node = node.nextSibling;
        }
      }
      // if we did not find a select to resest in the first row
      // then do not bother checking the remaining rows - optimizing for speed
      if (!foundSelectToReset && r==0) ignoreResetSelects = true;
    }

  } // ENDS refreshSortedTableRow

  // ---------------------------
  // Sort Data Types
  // ---------------------------

  // sort by the displayed value ascending
  function sortTableASC(table, col) {
    sortRowsAlphaASC.col = col;
    sortRowsAlphaCaseDESC.col = col;
    sortTable(table, sortRowsAlphaASC, sortRowsAlphaCaseDESC);
  }

  // sort by the displayed value descending
  function sortTableDESC(table, col) {
    sortRowsAlphaDESC.col = col;
    sortRowsAlphaCaseASC.col = col;
    sortTable(table, sortRowsAlphaDESC, sortRowsAlphaCaseASC);
  }

  // sort by the hidden value ascending
  function sortTableASCHidden(table, col) {
    sortRowsHiddenAlphaASC.col = col;
    sortRowsHiddenAlphaCaseDESC.col = col;
    sortTable(table, sortRowsHiddenAlphaASC, sortRowsHiddenAlphaCaseDESC);
  }

  // sort by the hidden value descending
  function sortTableDESCHidden(table, col) {
    sortRowsHiddenAlphaDESC.col = col;
    sortRowsHiddenAlphaCaseASC.col = col;
    sortTable(table, sortRowsHiddenAlphaDESC, sortRowsHiddenAlphaCaseASC);
  }

  // sort by the displayed numerical value ascending
  function sortTableASCNumerical(table, col) {
    sortRowsNumberASC.col = col;
    sortTable(table, sortRowsNumberASC);
  }

  // sort by the displayed numerical value descending
  function sortTableDESCNumerical(table, col) {
    sortRowsNumberDESC.col = col;
    sortTable(table, sortRowsNumberDESC);
  }

  // sort by the hidden numerical value ascending
  function sortTableASCHiddenNumerical(table, col) {
    sortRowsHiddenNumberASC.col = col;
    sortTable(table, sortRowsHiddenNumberASC);
  }

  // sort by the hidden numerical value descending
  function sortTableDESCHiddenNumerical(table, col) {
    sortRowsHiddenNumberDESC.col = col;
    sortTable(table, sortRowsHiddenNumberDESC);
  }

  // sort by the links href value ascending
  function sortTableASCLinkHref(table, col) {
    sortRowsLinkASC.sortby = "href";
    sortRowsLinkCaseDESC.sortby = "href";
    sortRowsLinkASC.col = col;
    sortRowsLinkCaseDESC.col = col;
    sortTable(table, sortRowsLinkASC, sortRowsLinkCaseDESC);
  }

  // sort by the links href value descending
  function sortTableDESCLinkHref(table, col) {
    sortRowsLinkDESC.sortby = "href";
    sortRowsLinkCaseASC.sortby = "href";
    sortRowsLinkDESC.col = col;
    sortRowsLinkCaseASC.col = col;
    sortTable(table, sortRowsLinkDESC, sortRowsLinkCaseASC);
  }

  // sort by the links text ascending
  function sortTableASCLinkText(table, col) {
    // this will return all text for the cell - not just the text which is the link
    sortRowsLinkASC.sortby = "text";
    sortRowsLinkCaseDESC.sortby = "text";
    sortRowsLinkASC.col = col;
    sortRowsLinkCaseDESC.col = col;
    sortTable(table, sortRowsLinkASC, sortRowsLinkCaseDESC);
  }

  // sort by the links text descending
  function sortTableDESCLinkText(table, col) {
    // this will return all text for the cell - not just the text which is the link
    sortRowsLinkDESC.sortby = "text";
    sortRowsLinkCaseASC.sortby = "text";
    sortRowsLinkDESC.col = col;
    sortRowsLinkCaseASC.col = col;
    sortTable(table, sortRowsLinkDESC, sortRowsLinkCaseASC);
  }

  // ---------------------------
  // Row Sorting Schemes - DO NOT EDIT - NOT INTENDED TO BE CALLED FROM ANT FUNCTION OTHER THAN THE SORT DATA TYPES
  // ---------------------------
  function sortRowsAlphaASC(row1, row2) {
    column = sortRowsAlphaASC.col;
    try { cell1 = (row1.cells[column].firstChild.nodeValue).toLowerCase(); } catch(c) { try { cell1 = (getTextNodes(row1.cells[column])).toLowerCase(); } catch(cx) { cell1 = ""; }}
    try { cell2 = (row2.cells[column].firstChild.nodeValue).toLowerCase(); } catch(c) { try { cell2 = (getTextNodes(row2.cells[column])).toLowerCase(); } catch(cx) { cell2 = ""; }}

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsAlphaCaseASC(row1, row2) {
    column = sortRowsAlphaCaseASC.col;
    try { cell1 = row1.cells[column].firstChild.nodeValue; } catch(c) { try { cell1 = getTextNodes(row1.cells[column]); } catch(cx) { cell1 = ""; }}
    try { cell2 = row2.cells[column].firstChild.nodeValue; } catch(c) { try { cell2 = getTextNodes(row2.cells[column]); } catch(cx) { cell2 = ""; }}

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsAlphaDESC(row1, row2) {
    column = sortRowsAlphaDESC.col;
    try { cell1 = (row1.cells[column].firstChild.nodeValue).toLowerCase(); } catch(c) { try { cell1 = (getTextNodes(row1.cells[column])).toLowerCase(); } catch(cx) { cell1 = ""; }}
    try { cell2 = (row2.cells[column].firstChild.nodeValue).toLowerCase(); } catch(c) { try { cell2 = (getTextNodes(row2.cells[column])).toLowerCase(); } catch(cx) { cell2 = ""; }}

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsAlphaCaseDESC(row1, row2) {
    column = sortRowsAlphaCaseDESC.col;
    try { cell1 = row1.cells[column].firstChild.nodeValue; } catch(c) { try { cell1 = getTextNodes(row1.cells[column]); } catch(cx) { cell1 = ""; }}
    try { cell2 = row2.cells[column].firstChild.nodeValue; } catch(c) { try { cell2 = getTextNodes(row2.cells[column]); } catch(cx) { cell2 = ""; }}

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsHiddenAlphaASC(row1, row2) {
    column = sortRowsHiddenAlphaASC.col;
    try { cell1 = (findFirstHiddenChild(row1.cells[column]).value).toLowerCase(); } catch(c) { try { cell1 = (getFirstElementNodeValue(row1.cells[column], "INPUT", "INPUT", "hidden", "value")).toLowerCase(); } catch(c) { cell1 = ""; }}
    try { cell2 = (findFirstHiddenChild(row2.cells[column]).value).toLowerCase(); } catch(c) { try { cell2 = (getFirstElementNodeValue(row2.cells[column], "INPUT", "INPUT", "hidden", "value")).toLowerCase(); } catch(c) { cell2 = ""; }}

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsHiddenAlphaCaseASC(row1, row2) {
    column = sortRowsHiddenAlphaCaseASC.col;
    try { cell1 = findFirstHiddenChild(row1.cells[column]).value; } catch(c) { try { cell1 = getFirstElementNodeValue(row1.cells[column], "INPUT", "INPUT", "hidden", "value"); } catch(c) { cell1 = ""; }}
    try { cell2 = findFirstHiddenChild(row2.cells[column]).value; } catch(c) { try { cell2 = getFirstElementNodeValue(row2.cells[column], "INPUT", "INPUT", "hidden", "value"); } catch(c) { cell2 = ""; }}

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsHiddenAlphaDESC(row1, row2) {
    column = sortRowsHiddenAlphaDESC.col;
    try { cell1 = (findFirstHiddenChild(row1.cells[column]).value).toLowerCase(); } catch(c) { try { cell1 = (getFirstElementNodeValue(row1.cells[column], "INPUT", "INPUT", "hidden", "value")).toLowerCase(); } catch(c) { cell1 = ""; }}
    try { cell2 = (findFirstHiddenChild(row2.cells[column]).value).toLowerCase(); } catch(c) { try { cell2 = (getFirstElementNodeValue(row2.cells[column], "INPUT", "INPUT", "hidden", "value")).toLowerCase(); } catch(c) { cell2 = ""; }}

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsHiddenAlphaCaseDESC(row1, row2) {
    column = sortRowsHiddenAlphaCaseDESC.col;
    try { cell1 = findFirstHiddenChild(row1.cells[column]).value; } catch(c) { try { cell1 = getFirstElementNodeValue(row1.cells[column], "INPUT", "INPUT", "hidden", "value"); } catch(c) { cell1 = ""; }}
    try { cell2 = findFirstHiddenChild(row2.cells[column]).value; } catch(c) { try { cell2 = getFirstElementNodeValue(row2.cells[column], "INPUT", "INPUT", "hidden", "value"); } catch(c) { cell2 = ""; }}

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsNumberASC(row1, row2) {
    column = sortRowsNumberASC.col;
    try { cell1 = parseFloat(row1.cells[column].firstChild.nodeValue); } catch(c) { try { cell1 = parseFloat(getTextNodes(row1.cells[column])); } catch(cx) { cell1 = 0.0; }}
    try { cell2 = parseFloat(row2.cells[column].firstChild.nodeValue); } catch(c) { try { cell2 = parseFloat(getTextNodes(row2.cells[column])); } catch(cx) { cell2 = 0.0; }}

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsNumberDESC(row1, row2) {
    column = sortRowsNumberDESC.col;
    try { cell1 = parseFloat(row1.cells[column].firstChild.nodeValue); } catch(c) { try { cell1 = parseFloat(getTextNodes(row1.cells[column])); } catch(cx) { cell1 = 0.0; }}
    try { cell2 = parseFloat(row2.cells[column].firstChild.nodeValue); } catch(c) { try { cell2 = parseFloat(getTextNodes(row2.cells[column])); } catch(cx) { cell2 = 0.0; }}

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsHiddenNumberASC(row1, row2) {
    column = sortRowsHiddenNumberASC.col;
    try { cell1 = parseFloat(findFirstHiddenChild(row1.cells[column]).value); } catch(c) { try { cell1 = parseFloat(getFirstElementNodeValue(row1.cells[column], "INPUT", "INPUT", "hidden", "value")); } catch(c) { cell1 = 0.0; }}
    try { cell2 = parseFloat(findFirstHiddenChild(row2.cells[column]).value); } catch(c) { try { cell2 = parseFloat(getFirstElementNodeValue(row2.cells[column], "INPUT", "INPUT", "hidden", "value")); } catch(c) { cell2 = 0.0; }}

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsHiddenNumberDESC(row1, row2) {
    column = sortRowsHiddenNumberDESC.col;
    try { cell1 = parseFloat(findFirstHiddenChild(row1.cells[column]).value); } catch(c) { try { cell1 = parseFloat(getFirstElementNodeValue(row1.cells[column], "INPUT", "INPUT", "hidden", "value")); } catch(c) { cell1 = 0.0; }}
    try { cell2 = parseFloat(findFirstHiddenChild(row2.cells[column]).value); } catch(c) { try { cell2 = parseFloat(getFirstElementNodeValue(row2.cells[column], "INPUT", "INPUT", "hidden", "value")); } catch(c) { cell2 = 0.0; }}

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsLinkASC(row1, row2) {
    sortby = sortRowsLinkASC.sortby;
    column = sortRowsLinkASC.col;

    if (sortby == "href") {
      // this will return only the link href
      try { cell1 = (findFirstLinkChild(row1.cells[column]).href).toLowerCase(); } catch(c) { try { cell1 = (getFirstElementNodeValue(row1.cells[column], "A", "A", "", "href")).toLowerCase(); } catch(c) { cell1 = ""; }}
      try { cell2 = (findFirstLinkChild(row2.cells[column]).href).toLowerCase(); } catch(c) { try { cell2 = (getFirstElementNodeValue(row2.cells[column], "A", "A", "", "href")).toLowerCase(); } catch(c) { cell2 = ""; }}
    }
    else {
      // this will return all text for the cell - not just the text which is the link
      try { cell1 = (getTextNodes(row1.cells[column])).toLowerCase(); } catch(c) { cell1 = ""; }
      try { cell2 = (getTextNodes(row2.cells[column])).toLowerCase(); } catch(c) { cell2 = ""; }
    }

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsLinkCaseASC(row1, row2) {
    sortby = sortRowsLinkCaseASC.sortby;
    column = sortRowsLinkCaseASC.col;

    if (sortby == "href") {
      // this will return only the link href
      try { cell1 = findFirstLinkChild(row1.cells[column]).href; } catch(c) { try { cell1 = getFirstElementNodeValue(row1.cells[column], "A", "A", "", "href"); } catch(c) { cell1 = ""; }}
      try { cell2 = findFirstLinkChild(row2.cells[column]).href; } catch(c) { try { cell2 = getFirstElementNodeValue(row2.cells[column], "A", "A", "", "href"); } catch(c) { cell2 = ""; }}
    }
    else {
      // this will return all text for the cell - not just the text which is the link
      try { cell1 = getTextNodes(row1.cells[column]); } catch(c) { cell1 = ""; }
      try { cell2 = getTextNodes(row2.cells[column]); } catch(c) { cell2 = ""; }
    }

    sortAsc = true;
    return ((cell1 < cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsLinkDESC(row1, row2) {
    sortby = sortRowsLinkDESC.sortby;
    column = sortRowsLinkDESC.col;

    if (sortby == "href") {
      // this will return only the link href
      try { cell1 = (findFirstLinkChild(row1.cells[column]).href).toLowerCase(); } catch(c) { try { cell1 = (getFirstElementNodeValue(row1.cells[column], "A", "A", "", "href")).toLowerCase(); } catch(c) { cell1 = ""; }}
      try { cell2 = (findFirstLinkChild(row2.cells[column]).href).toLowerCase(); } catch(c) { try { cell2 = (getFirstElementNodeValue(row2.cells[column], "A", "A", "", "href")).toLowerCase(); } catch(c) { cell2 = ""; }}
    }
    else {
      // this will return all text for the cell - not just the text which is the link
      try { cell1 = (getTextNodes(row1.cells[column])).toLowerCase(); } catch(c) { cell1 = ""; }
      try { cell2 = (getTextNodes(row2.cells[column])).toLowerCase(); } catch(c) { cell2 = ""; }
    }

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

  function sortRowsLinkCaseDESC(row1, row2) {
    sortby = sortRowsLinkCaseDESC.sortby;
    column = sortRowsLinkCaseDESC.col;

    if (sortby == "href") {
      // this will return only the link href
      try { cell1 = findFirstLinkChild(row1.cells[column]).href; } catch(c) { try { cell1 = getFirstElementNodeValue(row1.cells[column], "A", "A", "", "href"); } catch(c) { cell1 = ""; }}
      try { cell2 = findFirstLinkChild(row2.cells[column]).href; } catch(c) { try { cell2 = getFirstElementNodeValue(row2.cells[column], "A", "A", "", "href"); } catch(c) { cell2 = ""; }}
    }
    else {
      // this will return all text for the cell - not just the text which is the link
      try { cell1 = getTextNodes(row1.cells[column]); } catch(c) { cell1 = ""; }
      try { cell2 = getTextNodes(row2.cells[column]); } catch(c) { cell2 = ""; }
    }

    sortAsc = false;
    return ((cell1 > cell2) ? -1 : (cell1 == cell2 ? 0 : 1));
  }

// -- End Table Sorting Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// DOM Parsing Utilities
// ---------------------------

  // http://www.webreference.com/programming/javascript/definitive/chap17/index.html
  // If there is no Node object, define one with the following properties and values.
  // ** Note: that these are HTML node types only. For XML-specific nodes, you need to add other constants here.
  if (!window.Node) {
    var Node = {
      ELEMENT_NODE: 1,
      ATTRIBUTE_NODE: 2,
      TEXT_NODE: 3,
      COMMENT_NODE: 8,
      DOCUMENT_NODE: 9,
      DOCUMENT_FRAGMENT_NODE: 11
    }
  }

  function findBodyParent(node) {
    node = node.parentNode;
    // tagName is uppercase
    while (node.tagName != "BODY") {
      node = node.parentNode;
    }
    return node;
  }

  function findTableParent(node) {
    node = node.parentNode;
    // tagName is uppercase
    while (node.tagName != "TABLE") {
      node = node.parentNode;
    }
    return node;
  }

  function findDivParent(node) {
    node = node.parentNode;
    // tagName is uppercase
    while (node.tagName != "DIV") {
      node = node.parentNode;
    }
    return node;
  }

 function findRowParent(node) {
    node = node.parentNode;
    // tagName is uppercase
    while (node.tagName != "TR") {
      node = node.parentNode;
    }
    return node;
  }

  function findCellParent(node) {
    node = node.parentNode;
    // tagName is uppercase
    while (node.tagName != "TD") {
      node = node.parentNode;
    }
    return node;
  }

  function findFirstLinkChild(node) {
    node = node.firstChild;
    // tagName is uppercase
    while (node.tagName != "A") {
      node = node.nextSibling;
    }
    return node;
  }

  function findFirstSelectChild(node) {
    node = node.firstChild;
    // tagName is uppercase
    while (node.tagName != "SELECT") {
      node = node.nextSibling;
    }
    return node;
  }

  function findFirstHiddenChild(node) {
    var idcompare = false;
    if ((arguments[1] != null) && (arguments[1] != "")) {
      idcompare = true;
    }

    node = node.firstChild;
    if (node != null) {
      // tagName is uppercase
      // type is lowercase
      var notFound = (!((node.tagName == "INPUT") && (node.type == "hidden")));
      if(idcompare && (node.id != null) && (node.id != arguments[1])) {
        notFound = true;
      }

      while (notFound) {
        node = node.nextSibling;
        var notFound = (!((node.tagName == "INPUT") && (node.type == "hidden")));
        if(idcompare && (node.id != null) && (node.id != arguments[1])) {
          notFound = true;
        }
      }
    }
    // developer tool needs to be alert
    //alert('findFirstHiddenChild -> node.tagName: '+node.tagName+' node.type: '+node.type);
    return node;
  }

  function findFirstCheckboxChild(node) {
    node = node.firstChild;
    if (node != null) {
      // tagName is uppercase
      // type is lowercase
      var notFound = (!((node.tagName == "INPUT") && (node.type == "checkbox")));
      while (notFound) {
        node = node.nextSibling;
        var notFound = (!((node.tagName == "INPUT") && (node.type == "checkbox")));
      }
    }
    // developer tool needs to be alert
    //alert('findFirstCheckboxChild -> node.tagName: '+node.tagName+' node.type: '+node.type);
    return node;
  }

  function findFirstRadiodialChild(node) {
    node = node.firstChild;
    if (node != null) {
      // tagName is uppercase
      // type is lowercase
      var notFound = (!((node.tagName == "INPUT") && (node.type == "radio")));
      while (notFound) {
        node = node.nextSibling;
        var notFound = (!((node.tagName == "INPUT") && (node.type == "radio")));
      }
    }
    // developer tool needs to be alert
    //alert('findFirstRadiodialChild -> node.tagName: '+node.tagName+' node.type: '+node.type);
    return node;
  }

  function findFirstInputChild(node) {
    node = node.firstChild;
    if (node != null) {
      var notFound = (!((node.tagName == "INPUT") && (node.type == "text")));
      // tagName is uppercase
      // type is lowercase
      while (notFound) {
        node = node.nextSibling;
        var notFound = (!((node.tagName == "INPUT") && (node.type == "text")));
      }
    }
    // developer tool needs to be alert
    //alert('findFirstInputChild -> node.tagName: '+node.tagName+' node.type: '+node.type);
    return node;
  }

  function findFirstFormEntryChild(node) {
    node = node.firstChild;
    if (node != null) {
      // tagName is uppercase
      // type is lowercase
      var notFound = ((node.tagName != "INPUT" && node.tagName != "SELECT") || node.type == "hidden" || node.type == null);
      while (notFound) {
        node = node.nextSibling;
        if (node == null) {
          break;
        }
        notFound = ((node.tagName != "INPUT" && node.tagName != "SELECT") || node.type == "hidden" || node.type == null);
      }
    }
    // developer tool needs to be alert
    //alert('findFirstFormEntryChild -> node.tagName: '+node.tagName+' node.type: '+node.type);
    return node;
  }

  function findFirstButtonChild(node) {
    node = node.firstChild;
    if (node != null) {
      // tagName is uppercase
      // type is lowercase
      var notFound = (!(((node.tagName == "INPUT") && (node.type == "button")) || (node.tagName == "BUTTON")));
      while (notFound) {
        node = node.nextSibling;
        var notFound = (!(((node.tagName == "INPUT") && (node.type == "button")) || (node.tagName == "BUTTON")));
      }
    }
    // developer tool needs to be alert
    //alert('findFirstButtonChild -> node.tagName: '+node.tagName+' node.type: '+node.type);
    return node;
  }

  // get the text from all TextNodes within the given node
  function getTextNodes(node) {
    var counter = 0;
    var retVal = "";

    if (node.childNodes.length > 0) {
      var children = node.childNodes;
      var nextChild = children.item(counter);

      while (nextChild) {
        retVal += getTextNodes(nextChild);

        if (counter < node.childNodes.length-1) nextChild = children.item(++counter);
        else nextChild = false;
      }
    }

    if (node.nodeType == Node.TEXT_NODE) { // node.nodeName == "#text"
      retVal += node.data;
    }

    return retVal;
  }

  // http://www.webreference.com/programming/javascript/definitive/chap17/index.html
  // nodeName, tagName and type are NODE attributes --> use can use the alert in the code below to see the DOM traversal
  function getFirstElementNodeValue(node, nodeName, tagName, type, attr) {
    var counter = 0;
    var retVal = "";

    if (arguments[5] == null) {
      nodeName = nodeName.toUpperCase()
      tagName = tagName.toUpperCase()
      type = type.toLowerCase()
    }

    if (node.childNodes.length > 0) {
      var children = node.childNodes;
      var nextChild = children.item(counter);

      while (nextChild) {
        retVal += getFirstElementNodeValue(nextChild, nodeName, tagName, type, attr, "recurse");

        if ((counter < node.childNodes.length-1) && (retVal == "")) nextChild = children.item(++counter);
        else nextChild = false;
      }
    }

    // developer tool needs to be alert
    //alert('getFirstElementNodeValue ->\n node.nodeName: '+node.nodeName+'\n node.tagName: '+node.tagName+'\n node.type: '+node.type+'\n\n ** node.'+attr+': '+eval("node."+attr)+'\n\n node.href: '+node.href+'\n node.value: '+node.value+'\n node.data: '+node.data);

    // nodeName is uppercase
    // tagName is uppercase
    // type is lowercase
    if (((node.nodeType == Node.ELEMENT_NODE) && (node.nodeName == nodeName)) && ((node.tagName == tagName) && (node.type == type))) {
      retVal += eval("node."+attr);
    }

    return retVal;
  } // ENDS getFirstElementNodeValue

  function rowNumber(node) {
    var table = findTableParent(node);

    // tagName is uppercase
    if (node.tagName != "TR") {
      // developer tool needs to be alert
      alert("ERROR: utilities:rowNumber => given node is not a row object");
    }
    else {
      for (var i=0; i<table.rows.length; i++) {
        if (table.rows[i] == node) return i;
      }
    }

    return -1;
  }

// -- End DOM Parsing Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Table Formatting Utilities
// ---------------------------

  // set table width and cells widths to mimic the masterTable width and cells widths
  function mimicTable(masterTable, table) {
    // set the tables width
    table.style.width = masterTable.offsetWidth;

    var masterTableSection;
    if ((masterTable.tHead == null) && (masterTable.tFoot == null)) masterTableSection = masterTable;
    else masterTableSection = masterTable.tBodies[masterTable.tBodies.length - 1];

    var tableSection;
    if ((table.tHead == null) && (table.tFoot == null)) tableSection = table;
    else tableSection = table.tBodies[table.tBodies.length - 1];

    // set the tables cells width
    var tableCellWidths = new Array();

    // -- due to a memory leak in IE
    // copy of the cell widths to a temporary array
    var collectGoodCells = false;
    var r = 0;
    while (!collectGoodCells) {
      collectGoodCells = true;
      for (var c = 0; c < masterTableSection.rows[r].cells.length; c++) {
        // ignore rows with cells which span unless we are looking at the last row of the table
        if (((masterTableSection.rows[r].cells[c].colSpan == 1) && (r < masterTableSection.rows.length-1)) || (r == masterTableSection.rows.length-1)) {
          cellWidth = masterTableSection.rows[r].cells[c].offsetWidth;
          if (tableCellWidths[c] == null || cellWidth > tableCellWidths[c]) {
            tableCellWidths[c] = cellWidth;
          }
        }
        else {
          collectGoodCells = false;
          r++;
          break;
        }
      }
    }

    // developer tool needs to be alert
    //alert("mimicTable::tableCellWidths = "+tableCellWidths+" \n length = "+tableCellWidths.length);

    // now set cells widths from the temporary array
    for (var r = 0; r < tableSection.rows.length; r++) {
      for (var c = 0; c < tableSection.rows[r].cells.length; c++) {
        tableSection.rows[r].cells[c].style.width = tableCellWidths[c];
      }
    }
  } // ENDS mimicTable

  // set all tables to equalize their widths and cell widths in order to appear as 1(one) whole table.
  // equalization: for each column of each table, the largest width is used
  // can pass in either a list of table objects (as individual parameters)
  // -- or --
  // a list of table ids delimited by "^" (in 1 paramter) -- example:  table1^etc.
  // -- or --
  // a list of table references delimited by "^" (in 1 paramter) -- example:  top.logframe.getElementById('table1')^etc.
  function equalizeTables() {
    if (arguments.length > 1) {
      var equalizeTableObjectCommand = "equalizeTableObjects(arguments[0]";
      for (var t = 1; t < arguments.length; t++) {
        equalizeTableObjectCommand = equalizeTableObjectCommand + ",arguments["+t+"]";
      }
      equalizeTableObjectCommand = equalizeTableObjectCommand + ")";

      // call equalizeTableOjbects with table objects
      eval(equalizeTableObjectCommand);
    }
    else {
      // convert table references into objects
      if (arguments[0].indexOf("^") == -1) return;

      var listType = ((arguments[0].indexOf("getElementById") == -1) ? "idlist" : "reflist");

      var tables = arguments[0].split("^");
      var tableObjects = new Array();
      for (var t = 0; t < tables.length; t++) {
        if ((listType == "idlist") && (document.getElementById(tables[t]) != null)) tableObjects[t] = document.getElementById(tables[t]);
        if ((listType == "reflist") && (eval(tables[t]) != null)) tableObjects[t] = eval(tables[t]);
      }

      if (tableObjects.length > 0) {
        var equalizeTableObjectCommand = "equalizeTableObjects(tableObjects[0]";
        for (var t = 1; t < tableObjects.length; t++) {
          equalizeTableObjectCommand = equalizeTableObjectCommand + ",tableObjects["+t+"]";
        }
        equalizeTableObjectCommand = equalizeTableObjectCommand + ")";

        // call equalizeTableOjbects with table objects
        eval(equalizeTableObjectCommand);
      }
    }
  } // ENDS equalizeTables

  function equalizeTableObjects() {
    var tables = arguments; // list of table objects

    try {

// RRL - 8/4/04 - is causing problems and doesn't seem to be helping anything
//      // set the tables width
//      for (var a = 0; a < 2; a++) { // repeat the whole process twice - 2nd pass is for cleanup
//        var tableWidth = 0;
//
//        for (var t = 0; t < tables.length; t++) {
//          if (tables[t].offsetWidth > tableWidth) {
//            tableWidth = tables[t].offsetWidth;
//          }
//        }
//      } // ENDS for (var a = 0; a < 1; a++)
//
//      for (var t = 0; t < tables.length; t++) {
//        tables[t].style.width = tableWidth;
//      }

      // set the table cells width
      for (var a = 0; a < 2; a++) { // repeat the whole process twice - 2nd pass is for cleanup
        var tableCellWidths = new Array();

        for (var t = 0; t < tables.length; t++) {
          var theTable = tables[t];
          var tableSection;
          if ((theTable.tHead == null) && (theTable.tFoot == null)) tableSection = theTable;
          else tableSection = theTable.tBodies[theTable.tBodies.length - 1];

          if (tableSection.rows.length==0) continue;

          var collectGoodCells = false;
          var r = 0;
          while (!collectGoodCells) {
            collectGoodCells = true;
            for (var c = 0; c < tableSection.rows[r].cells.length; c++) {
              // ignore rows with cells which span unless we are looking at the last row of the table
              if (((tableSection.rows[r].cells[c].colSpan == 1) && (r < tableSection.rows.length-1)) || (r == tableSection.rows.length-1)) {
                cellWidth = tableSection.rows[r].cells[c].offsetWidth;
                if (tableCellWidths[c] == null || cellWidth > tableCellWidths[c]) {
                  tableCellWidths[c] = cellWidth;
                }
              }
              else {
                collectGoodCells = false;
                r++;
                break;
              }
            }
          }
        } // ENDS for (var t = 0; t < tables.length; t++)

        // developer tool needs to be alert
        //alert("utilities:equalizeTableObjects::tableCellWidths = "+tableCellWidths+" \n length = "+tableCellWidths.length);

        var rightPadding = parseInt(getStyleClass('gridheader', 'paddingRight'));
        for (var t = 0; t < tables.length; t++) {
          tableSection = tables[t];

          // developer tool needs to be alert
          //alert("table["+t+"].id = "+tables[t].id+"\n rows = "+tableSection.rows.length+"\n cells = "+tableSection.rows[0].cells.length);

          for (var r = 0; r < tableSection.rows.length; r++) {
            for (var c = 0; c < tableSection.rows[r].cells.length; c++) {
              try {
                // ignore cells which span
                if (tableSection.rows[r].cells[c].colSpan == 1) {
                  tableSection.rows[r].cells[c].style.width = tableCellWidths[c];
                  if ((tableSection.rows[r].cells[c].firstChild != null) && (tableSection.rows[r].cells[c].firstChild.tagName == "DIV")) {
                    tableSection.rows[r].cells[c].firstChild.style.width = ((tableCellWidths[c] - rightPadding - tables[t].cellSpacing < 0) ? 0 : tableCellWidths[c] - rightPadding - tables[t].cellSpacing);
                  }
                }
              }
              catch(mismatchedcells) {
                displayError("utilities:equalizeTableObjects mismatch table cell length.",e,DEBUGALL);
              }
            }
          }
        } // ENDS for (var t = 0; t < tables.length; t++)
      } // ENDS for (var a = 0; a < 1; a++)
    }
    catch(e) {
      displayError("utilities:equalizeTableObjects errors for table objects => "+tables,e,DEBUGALL);
    }
  } // ENDS equalizeTableObjects

  function updateChildGridTotals() {
    for (var i = 0; i < arguments.length; i++) {
      var childGrid = arguments[i];

      if ((childGrid != null) && (childGrid != "")) {
        var childGridDiv = document.getElementById(childGrid+"logarea");
        var childGridTotalDiv = document.getElementById(childGrid+"logarea_totals");

        var childGridTable = document.getElementById(childGrid+"table");
        var childGridTableTotal = document.getElementById(childGrid+"table_totals");

        try {
          if (childGridTotalDiv != null) {
            childGridTotalDiv.style.width = childGridDiv.style.width;

            // the only reason we do this here is because app:exponlinediv does not currently support the onResize attribute for div tags
            childGridDiv.onResize = "document.getElementById('"+childGrid+"logarea_totals').style.width = document.getElementById('"+childGrid+"logarea').style.width;";

            childGridDiv.style.overflowX = "hidden";
            childGridDiv.style.overflowY = "auto";

            childGridTotalDiv.style.overflowX = "auto";
            childGridTotalDiv.style.overflowY = "auto";

            // set table and cell width to mimic log table
            mimicTable(childGridTable, childGridTableTotal);

            // adjust table and cells widths so table columns line up if a total is wider than the original column width
            equalizeTables(childGridTable, childGridTableTotal);
          } // ENDS if (childGridTotalDiv != null)
        } catch(e) { displayError("utilities:updateChildGridTotals."+childGrid,e); }
      } // ENDS if ((childGrid != null) && (childGrid != ""))
    } // ENDS for (var i = 0; i < arguments.length; i++)
  } // ENDS updateChildGridTotals

  function synchronizeChildGridTotalScroll(childGrid) {
    try {
      var childGridDiv = document.getElementById(childGrid+"logarea");
      var childGridTotalDiv = document.getElementById(childGrid+"logarea_totals");

      if (is_ie) childGridDiv.scrollLeft = childGridTotalDiv.scrollLeft;
      else childGridDiv.pageXOffset = childGridTotalDiv.pageXOffset;
    } catch(e) { displayError("utilities:synchronizeChildGridTotalScroll."+childGrid,e); }
  } // ENDS synchronizeChildGridTotalScroll

// -- Table Formatting Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Big Decimal Utilities
// ---------------------------

  function addBigDecimal(x, y) {
    try {
      return UTILSFRAME.UtilitiesApplet.addBigDec(x, y);
    } catch(e) { if (breakout!=null) displayError("utilities:addBigDecimal.",e,DEBUGMODERATE); }
  } // ENDS addBigDecimal

  function subtractBigDecimal(x, y) {
    try {
      return UTILSFRAME.UtilitiesApplet.subBigDec(x, y);
    } catch(e) { if (breakout!=null) displayError("utilities:subtractBigDecimal.",e,DEBUGMODERATE); }
  } // ENDS subtractBigDecimal

  function multiplyBigDecimal(x, y) {
    try {
      return UTILSFRAME.UtilitiesApplet.mulBigDec(x, y);
    } catch(e) { if (breakout!=null) displayError("utilities:multiplyBigDecimal.",e,DEBUGMODERATE); }
  } // ENDS multiplyBigDecimal

  function divideBigDecimal(x, y) {
    try {
      return UTILSFRAME.UtilitiesApplet.divBigDec(x, y);
    } catch(e) { if (breakout!=null) displayError("utilities:divideBigDecimal.",e,DEBUGMODERATE); }
  } // ENDS divideBigDecimal

  function divideBigDecimalToScale(x, y, scale) {
    try {
      return UTILSFRAME.UtilitiesApplet.divBigDecToScale(x, y, scale);
    } catch(e) { if (breakout!=null) displayError("utilities:divideBigDecimalToScale.",e,DEBUGMODERATE); }
  } // ENDS divideBigDecimalToScale

// -- Big Decimal Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Admin Utilities
// ---------------------------

  function setAdminModule(moduleName) {
    try {
      var breakout = top.adminanchorframe;
      top.adminanchorframe.document.getElementById('modulename').innerHTML=moduleName;
    } catch(e) { if (breakout!=null) displayError("setAdminModule error",e,DEBUGMODERATE); }
  } // ENDS setAdminModule

  function adminDynamicResize() {
    if (is_ie) percentage = 4.9;  else percentage = 8.7;
    var fullcols = parseInt((document.body.offsetWidth - 60) / percentage);
    if (fullcols < 50) fullcols = 50;

    // logarea resize
    var indentPadding = getStyleClass('indent', 'padding');
    var fullwidth = document.body.offsetWidth;
    if (fullwidth < 50) fullwidth = 50;
    document.getElementById('adminlog').style.width = fullwidth - 15;
    document.getElementById('adminlog').style.height = document.body.offsetHeight - 70 ;
  } // ENDS adminDynamicResize

  function confirmLeaveInAdmin(strHref) {
    try {
      var doc = top.logframe.document;
      doc.forms[0].gotoId.value = strHref;

      triggerDirty(doc);

      if (top.logframe.isFormDirty()) {
        top.logframe.openConfirmWindow("LEAVE");
      }
      else {
        top.logframe.location.replace(strHref);
      }
    } catch(veryleast) {
      top.logframe.location.replace(strHref);
    }
  } // ENDS confirmLeaveInAdmin

  // Added for Admin module by Tarun Singhal dated 13/8/2002
  function adminProcessDelete() {

    if ((!mModalWindow) || (mModalWindow.closed)) {
      width=350;height=150;
      strFeatures   = "scrollbars=no,resizable=no,width="+width+",height="+height+","+centerWindow(width, height);
      windowName    = "CONFIRMDELETE";

    if(arguments.length==0 || arguments[1]==null || arguments[1]==""){
        customMessageText = "Delete this User?";
      }else{
        customMessageText = arguments[1];
      }
      href = arguments[0];
      strHref = "confirmdelete.jsp?custommessage="+ customMessageText +"&deletehref=" + expEncode(href) + "&gotoid=" + arguments[1];

      mModalWindow = window.open(strHref, 'ALERT', strFeatures);
      if (mModalWindow.opener == null) mModalWindow.opener = self;
    }
  } // ENDS adminProcessDelete

  function splitStringCheckDelimiter(astrOriginal, aDelimiter) {
    arrList = new Array();
    index = 0;
    carrot  = '^';
    n = 'n';
    strConcat = astrOriginal;

    if (astrOriginal == null) {
      return null; // IMPORTANT! return a null because the original string is of zero length
    }

    // add a delimiter to the end of the string
    strConcat = strConcat + aDelimiter;

    for (var cntr=0; cntr<strConcat.length; cntr++) {
      if ((strConcat.charAt(cntr) == carrot) && (strConcat.charAt(cntr+1) == n)) {

        try {
          if ((cntr != 0) && (strConcat.charAt(cntr - 1) == carrot) && (strConcat.charAt(cntr - 2) != carrot)) {
            continue;
          }
          else {
            strTemp = strConcat.substring(0,cntr);
            counter = 0;

            for (var p=0; p<strTemp.length; p++) {
              if (strTemp.charAt(p) == carrot) counter++;
            }

            if (counter%2 == 0) {
              strFoundToken = strTemp;
              for (var iter=0; iter<strFoundToken.length; iter++) {
                if ((strFoundToken.charAt(iter) == carrot) && (strFoundToken.charAt(iter+1) == carrot)) {
                  strFoundToken = strFoundToken.substring(0,iter) + strFoundToken.substring(iter+1);
                }
              }
              arrList[index++] = strFoundToken;
              strConcat = strConcat.substring(cntr+2);
              cntr = 0;
            }
          }
        }
        catch(eIndex) {
          continue;
        }

      } // ENDS if ((strConcat.charAt(cntr) == carrot) && (strConcat.charAt(cntr+1) == n))
    } // ENDS for (var cntr=0; cntr<strConcat.length; cntr++)

    return arrList;
  } // ENDS splitStringCheckDelimiter

  function checkCarrot(astrElement) {
    if ((astrElement == null) || (astrElement == '')) {
      return astrElement;
    }

    carrot = '^';
    for (var i=0; i<astrElement.length; i++) {
      if (astrElement.charAt(i) == carrot) {
        astrElement = astrElement.substring(0,i) + "^" + astrElement.substring(i);
        i++;
      }
    }

    return astrElement;
  } // ENDS checkCarrot

// -- Admin Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Status Header Utilities
// ---------------------------

  // global priority images
  highPriority = new Image; highPriority.src = "img/priority_icon_0.gif";
  normalPriority = new Image; normalPriority.src = "img/priority_icon_1.gif";
  lowPriority = new Image; lowPriority.src = "img/priority_icon_2.gif";

  function setStatusHeaderBIC(bic) {
    try {
      document.getElementById("status_header_bic").innerHTML = bic;
    } catch(e) { displayError("utilities:setStatusHeaderBIC - "+bic+".",e,DEBUGWARNING); }
  }

  function setStatusHeaderPriority(priority) {
    try {
      priority = ""+priority;

      if ((priority == "0") || (priority == "high")) {
        document.getElementById("status_header_priortiy").src = highPriority.src;
      }
      else if ((priority == "1") || (priority == "normal")) {
        document.getElementById("status_header_priortiy").src = normalPriority.src;
      }
      else if ((priority == "2") || (priority == "low")) {
        document.getElementById("status_header_priortiy").src = lowPriority.src;
      }
      else {
        return;
      }
    } catch(e) { displayError("utilities:setStatusHeaderPriority - "+priority+".",e,DEBUGWARNING); }
  }

  function setStatusHeaderDescription(desc) {
    try {
      document.getElementById("status_header_description").innerHTML = desc;
    } catch(e) { displayError("utilities:setStatusHeaderDescription - "+desc+".",e,DEBUGWARNING); }
  }

  function setStatusHeader(bic, priority, desc) {
    setStatusHeaderBIC(bic);
    setStatusHeaderPriority(priority);
    setStatusHeaderDescription(desc);
  }

// -- Status Header Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Schedule Header Utilties
// ---------------------------

  // global priority images   **** declared above in Status Header Utilities ****

  function setScheduleHeaderBIC(bic) {
//    try {
//      top.logframe.document.getElementById("schedule_header_bic").innerHTML = bic;
//    } catch(e) { displayError("utilities:setScheduleHeaderBIC - "+bic+".",e,DEBUGWARNING); }
  }

  function setScheduleHeaderPriority(priority) {
//    try {
//      priority = ""+priority;
//
//      var editMode = false;
//      if (arguments[1] != null && arguments[1] == "edit") editMode = true;
//
//      if ((priority == "0") || (priority == "high")) {
//        top.logframe.document.getElementById("schedule_header_priority").src = ((!editMode) ? highPriority.src : highPriorityEdit.src);
//      }
//      else if ((priority == "1") || (priority == "normal")) {
//        top.logframe.document.getElementById("schedule_header_priority").src = ((!editMode) ? normalPriority.src : normalPriorityEdit.src);
//      }
//      else if ((priority == "2") || (priority == "low")) {
//        top.logframe.document.getElementById("schedule_header_priority").src = ((!editMode) ? lowPriority.src : lowPriorityEdit.src);
//      }
//      else {
//        return;
//      }
//    } catch(e) { displayError("utilities:setScheduleHeaderPriority - "+priority+".",e,DEBUGWARNING); }
  }

  function setScheduleHeaderDescription(desc) {
//    try {
//      top.logframe.document.getElementById("schedule_header_description").innerHTML = desc;
//    } catch(e) { displayError("utilities:setScheduleHeaderDescription - "+desc+".",e,DEBUGWARNING); }
  }

  function setScheduleHeader(bic, priority, desc) {
    setScheduleHeaderBIC(bic);
    setScheduleHeaderPriority(priority);
    setScheduleHeaderDescription(desc);
  }

// -- Schedule Header Utilities --

// ------------------------------------------------------------
// ------------------------------------------------------------
// Custom Field Utilties
// ---------------------------

  var customFieldDictionary;

  function setCheckboxValue(checkBox) {
    setFormDirty();

    var saveID = "save_" + checkBox.name;
    if (checkBox.checked) {
      document.getElementById(saveID).value = "1";
    }
    else {
      document.getElementById(saveID).value = "0";
    }
  }

  function popupCustomFieldDicionaryPicker(masterKey, customFieldID) {
    customFieldDictionary = customFieldID;
    popupPickerWindow('customfielddictionarypicker.do?action=show&amp;parentkey=' + masterKey + '&amp;', 'CDIPICKER', 'scrollbars=no,resizable=no,width=500,height=430,top=75,left=75');
  }

  function setCustomFieldFromPicker(value) {
    if (customFieldDictionary == null) return;

    setFormDirty();

    document.getElementById("save_"+customFieldDictionary).value=value;
    document.getElementById(customFieldDictionary).value=value;
  }

  function clearCustomFieldDictionary(customFieldID) {
    setFormDirty();

    document.getElementById("save_"+customFieldID).value="";
    document.getElementById(customFieldID).value="";
  }

	function launchWord(sWordUrl,sDataSource)
	{
		var errMsgWordNotInstalled;		
		var errMsgWordVersionNotSupported;			
		try 
		{ 
			errMsgWordNotInstalled = top.utilitiesframe.errMsgWordNotInstalled; 
		} 
		catch(uf) 
		{ 
			try{errMsgWordNotInstalled = opener.top.utilitiesframe.errMsgWordNotInstalled; }catch(error){errMsgWordNotInstalled = "MS Word must be installed on the system. Also, configure the browser to run ActiveX controls: open the browser, select Tools, Internet Options, Security, Custom Level, and click the Enable button under Run ActiveX controls and plug-ins."; }
		}
	
		try 
		{ 
			errMsgWordVersionNotSupported = top.utilitiesframe.errMsgWordVersionNotSupported; 
		} 
		catch(uf) 
		{ 
			try{errMsgWordVersionNotSupported = opener.top.utilitiesframe.errMsgWordVersionNotSupported; }catch(error){errMsgWordVersionNotSupported = "Word 2000 or later is required for this feature.";}  
		}
	
		try
		{
		  var wordApp = new ActiveXObject("Word.Application");
		  if(wordApp!=null || sWordUrl!=null)
		  {
			  var wordVersion = wordApp.Version;
			  if(parseFloat(wordVersion) <= 8)
			  {
				wordApp.Quit();
				alert(errMsgWordVersionNotSupported);
			  }
			  else
			  {
				wordApp.Visible=true;
				wordApp.Activate();
				wordApp.Documents.Open(sWordUrl);
				if(sDataSource!=null && sDataSource!='')
					wordApp.ActiveDocument.MailMerge.OpenDataSource(sDataSource);
			  }
		  }
		  else
		  {
			alert(errMsgWordNotInstalled);
		  }
		}
		catch(error)
		{
		  alert(error.description + '\n' + errMsgWordNotInstalled);
		}
	}
	// -- Custom Field Utilities --
	
	// -- Below function is used to write out the object tags in applets --
	function PageWriter()
	{
	    this.write = function(line)
	    {
	        document.write(line + '\n');
	    }
	}

	function brava(strURL)
	{
		try
		{
		    var launchBravaForm = document.createElement("form");
		
			launchBravaForm.setAttribute("id","bravaform");
			launchBravaForm.setAttribute("name","bravaform");
			launchBravaForm.setAttribute("action","brava.jsp");
			launchBravaForm.setAttribute("method","POST");
			launchBravaForm.setAttribute("target","bravawindow");
		
			// Create BRAVA_DOCID
			var bravaDocId = document.createElement("input");
			bravaDocId.setAttribute("type","hidden");
			bravaDocId.setAttribute("name","BRAVA_DOCID");
			bravaDocId.setAttribute("id","BRAVA_DOCID");
			bravaDocId.setAttribute("value", strURL);
		
			// Add BRAVA_DOCID to the FORM
			launchBravaForm.appendChild(bravaDocId);
			
			//Add for to body
			var theBody = document.getElementsByTagName("body").item(0);
			theBody.appendChild(launchBravaForm);
			window.open("bravaticker.jsp","bravawindow","width=800,height=800,toolbar=0 resizable=1");
		}
		catch(exp)
		{
			alert(exp.description);
		}
	}
	
// End -->
