// JavaScript Document
/* Common javascript utilities for BuildWithCentex
Validation Functions:
validateNumber(val, min, max)
validateText( obj, spaces) spaces is boolean
validateDate(obj, min, max, format) format mm/dd or dd/mm

isSomethingChecked( obj )
isSomethingSelected( obj )
whatIsSelected(myList)
whatIsSelectedValue(myList)
whatIsSelectedValueRadio(myRadio)
clearFields(myFieldsArray, thisForm)

General Utilities:
getHomeLocation(targetDocument) - Returns path to current .nsf
openDBRelativeURL( url, target ) - Takes us to the relative URL. If target isn't supplied, uses current
getDBDirectory(targetDocument) - get the url directory path (2nd layer up)

replaceSubstring(originalString, targetString, newString)
helpwindow(helpref)
windowOpener(url, name, args)
closeWindow()
closeWindowEditConfirm()
changeCSS(ccsClass,element,value)
changeToHourglass(setOnOff)

viewOpenDoc(id, viewname, parms, scrollbars, menubar, toolbars, statusbar) - currDB + "/" + viewname + "/" + id
whatsnewOpenDoc(div, id, parms)
openDoc(dbpath, id, parms, linktype, scrollbars, menubar, toolbars, statusbar)
rowopen(rowid)
viewOpenMarkRead(id, parms, scrollbars, menubar, toolbars, statusbar) - currDB + "/opendoc?openagent&docid=" + id + "&parms=" + parmbase
viewOpenMarkReadSource(type, var1, var2, scrollbars, toolbars, statusbar, pathoverride, overridediv)
whatsnewMarkRead(div, id, parms, linktype) - dbpath + "/opendoc?openagent&docid=" + id + "&parms="
openMarkRead(dbpath, id, parms, linktype, scrollbars, menubar, toolbars, statusbar)
openPaymentDetail(type, var1, var2, scrollbars, toolbars, statusbar, pathoverride, overridediv)

ResizeIFrame(iframeName, vertOffset,iframevMin)
ResizeObject(objName, vertOffset, vMin, horzOffset, hMin)
setDivVisibility(divID,isVis)

For PickLists:
selectAll(opt) - select all items in a box
deSelectAll(opt)
move(fbox,tbox) - move selected from one listbox to another
SortD(box) - Sort down
BumpUp(box) - remove empty value entries - NOTE: ignores select text. If no VALUE is available, it is deleted

For Multivalue cookies:
CookieAppendVal(cCookieVal, cName, cValue)
CookieExtractVal(cCookieVal, cName)
CookieSave(doc, cStoreName, cCookieVal, nSeconds, cDomain, cPath, bSecure )
CookieLoad(doc, cStoreName)
*************************************************/
var ie5=document.all&&document.getElementById
var ns6=document.getElementById&&!document.all
var agt=navigator.userAgent.toLowerCase(); 
var opera = (agt.indexOf("opera") != -1) 
var bmajor = parseInt(navigator.appVersion);
var opera6 = (this.opera && (bmajor ==6));

/***********************************************************
validateNumber()
Checks that the value of a field is a number, optionally within a certain range..
Arguments:
val = Value to be checked
min = Optional min allowed value
max = Optional max allowed value
************************************************************/
function validateNumber(val, min, max){
 if ( isNaN( val ) ) return false;
 if ( min && val < min ) return false;
 if ( max && val > max ) return false;
 return true;
}

/***********************************************************
validateText( obj, spaces)
Checks that a name, i.e. only alpha characters plus space, dash or period, is entered.
***********************************************************/
function validateText( obj, spaces ) {
 var Teststr = obj.value;
 var regExp;
 
 if (spaces) {
  regExp = /^[a-zA-Z\s]+$/;
 } else {
  regExp = /^[a-zA-Z]+$/;
 }
 
 if(regExp.test(Teststr)) {
  return true;
 } else {
  return false;
 }
}

/***********************************************************
validateDate()
Checks that the value of a date is in the correct format, optionally within a certain range.
Arguments:
obj = Input whose value is to be checked
min = Optional min allowed value
max = Optional max allowed value
format = date format, ie mm/dd or dd/mm
************************************************************/
function validateDate(obj, minDateIn, maxDateIn, format){
 
 dateBits = dateComponents(obj.value, format);
 if (dateBits == null) return false;


//Check it is a valid date first
 day = dateBits[0];
 month = dateBits[1];
 year = dateBits[2];

 if ((month < 1 || month > 12) || (day < 1 || day > 31)) { // check month range 
  return false;
 } 
 if ((month==4 || month==6 || month==9 || month==11) && day==31) {
  return false;
 }
 if (month == 2) {
 // check for february 29th 
  var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); 
  if (day>29 || (day==29 && !isleap)) {
   return false;
  }
 } 

//Now check whether a range is specified and if in bounds
 var theDate = new Date(dateBits[2], parseInt(dateBits[1]) - 1, dateBits[0]);

 if ( minDateIn ) {
  minBits = dateComponents (minDateIn, format);
  var minDate = new Date(minBits[2], parseInt(minBits[1]) - 1, minBits[0]);
  if ( minDate.getTime() > theDate.getTime() ) return false;
 } 
 if ( maxDateIn ) {
  maxBits = dateComponents (maxDateIn, format);
  var maxDate = new Date(maxBits[2], parseInt(maxBits[1]) - 1, maxBits[0]);
  if ( theDate.getTime() > maxDate.getTime() ) return false;
 }
 return true;
}

/***********************************************************
dateComponents()
Splits a date in to the day, month and year components, depending on the format supplied. 
Used by validateDate function.
Arguments:
dateStr = Input string to be checked
format = date format, ie mm/dd or dd/mm
************************************************************/
function dateComponents(dateStr, format) {
 var results = new Array();
 var datePat = /^(\d{1,2})(\/|-|\.)(\d{1,2})\2(\d{2}|\d{4})$/;
 var matchArray = dateStr.match(datePat);
 
 if (matchArray == null) { 
  return null; 
 }

 //check for two digit years and prepend 19 or 20 based on year 25 flip.
 if (matchArray[4].length == 2) {
  yearval = new Number(matchArray[4].value);
  if (yearval > 25) {
   matchArray[4] = '19' + matchArray[4]
  } else {
   matchArray[4] = '20' + matchArray[4]
  }
 }
 
 //strip leading 0 in date and month
 var stripPat = /^0/;
 matchArray[1] = matchArray[1].replace(stripPat,"");
 matchArray[3] = matchArray[3].replace(stripPat,"");
 
 // parse date into variables
 if (format.charAt(0)=="d"){ //what format does the server use for dates? 
  results[0] = matchArray[1];
  results[1] = matchArray[3];
 } else { 
  results[1] = matchArray[1];
  results[0] = matchArray[3]; 
 }
 results[2] = matchArray[4];

 return results;
}


/***********************************************************
isSomethingChecked()
Checks that an object of type radio group or checkbox has something selected.
Arguments:
obj = Reference to the parent object of the group.
************************************************************/
function isSomethingChecked( obj ){
 for (var r=0; r < obj.length; r++){
  if ( obj[r].checked ) return true;
 }
}

/***********************************************************
isSomethingSelected()
Checks that a select object has something selected.
Arguments:
obj = Reference to the parent object of the group.
************************************************************/
function isSomethingSelected( obj ){
  for (iDx = 0; iDx < obj.options.length; iDx++) {
  if (obj.options[iDx].selected) {
   return true;  
  }
  }
 return false;
}

function whatIsSelected(myList) {
  myStuff = new Array();
  var iCount = 0;
  for (iDx = 0; iDx < myList.options.length; iDx++) {
  if (myList.options[iDx].selected) {
   myStuff[iCount] = myList.options[iDx].text;
   iCount = iCount + 1;  
  }
  }
  if (iCount == 0) {
   return null;
  } else {
  return myStuff;
  }
}

function whatIsSelectedValue(myList) {
  myStuff = new Array();
  var iCount = 0;
  for (iDx = 0; iDx < myList.options.length; iDx++) {
  if (myList.options[iDx].selected) {
   myStuff[iCount] = myList.options[iDx].value;
   iCount = iCount + 1;  
  }
  }
  if (iCount == 0) {
   return null;
  } else {
  return myStuff;
  }
}

function whatIsSelectedValueRadio(myRadio) {
    var checkedButton = ""
 var found = false;
 var index = 0;
 var val = null;
 while(!found && index < myRadio.length){
  if(myRadio[index].checked){
   val = myRadio[index].value;
   found = true;
  } else {
   index++;
  }
 } 
 return val;
}

function clearFields(myFieldsArray, thisForm) {
 var arrayCount;
 var myFieldN;
 var myObj;
 
 for (arrayCount in myFieldsArray) {
  myFieldN = myFieldsArray[arrayCount];
  
  if(thisForm.elements[myFieldN]) {
   myObj = thisForm.elements[myFieldN];
   
   switch(myObj.type) {
    case "text":
     myObj.value = "";
     break;
    case "textarea":
     myObj.value = "";
     break;
    case "select-one":
     myObj[0].selected = true;
      //alert(myObj.selectedIndex)
     break;
    case "select-multiple":
     for(var i=0; i<myObj.length; i++) {
      myObj[i].selected = false;
     }
     //alert(myObj.selectedIndex)
     break;
    default:
     //alert(myObj.length)
     switch (myObj[0].type) {
      case "radio":
       myObj[0].checked = true;
       break;
      case "checkbox":
       for(var i=0; i<myObj.length; i++) {
        myObj[i].checked = false;
       }
       break;
      default:
     }
   }
  }
  //alert(arrayCount + " " + myFieldN + " - " + typeof(thisForm.elements[myFieldN]));
 }
}

//****    General Utilities    ************************************************
function getHomeLocation(targetDocument) {
 //Returns current Domino db's URL
    var tempString = targetDocument.location.href.toString();
    var currentURL = tempString.toLowerCase();
    var nsfPos = currentURL.indexOf(".nsf");
    var homeLocation = currentURL.substring(0,nsfPos) + ".nsf";
    return homeLocation;
}
function getPath(testpath) {
    var ltestpath = testpath.toLowerCase();
    var hasHttp = ltestpath.indexOf(".com");
    if(hasHttp==-1) {
        return testpath;
    } else {
        return ltestpath.slice(hasHttp+4,-1);
    }
}
function openDBRelativeURL( url, target ){
    //Takes us to the relative URL. If target isn't supplied, uses current
    //Check for a target window;
    var target = (target == null ) ? window : target;
    //Work out the path of the database;
    var path = location.pathname.split('.nsf')[0] + '.nsf/';
    target.location.href = path + url;
    target.focus()
}
function getDBDirectory(targetDocument){
    //Returns URL directory of current Domino db (looks for nsf, then one layer up);
    var dbpath = getHomeLocation(targetDocument);
    var homeDir = dbpath.substring(0,dbpath.lastIndexOf('/'));
    return homeDir;
}

function replaceSubstring(originalString, targetString, newString) {
    a = originalString.split(targetString);
    return a.join(newString);
}

function helpwindow(helpref) { //deprecated
    //Pops a window with the referenced help
    helpWindow(helpref)
}
function helpWindow(helpref) {
    //Pops a window with the referenced help
    window.open("http://" + window.location.host + "/shared/bwckbase.nsf/pages/"+ helpref,"","toolbar=no,resizable=yes,scrollbars=yes,location=no,menubar=no,directories=no,height=500,width=800");
    void("")
    }
    //Window Utilities
    windowparmBase = "width=780, height=580, resizable=yes"
    //Must be defined globally to keep from being redefined with each call
    popupWins = new Array();
    function windowOpener(url, name, args) {
    /******************************* 
    the popupWins array stores an object reference for each separate window that is called, based upon
    the name attribute that is supplied as an argument
    *******************************/
     if ( typeof( popupWins[name] ) != "object" ){
      popupWins[name] = window.open(url,name,args);
     } else {
      if (!popupWins[name].closed){
       popupWins[name].location.href = url;
      } else {
       popupWins[name] = window.open(url, name,args);
      }
     }

     popupWins[name].focus();
}
function viewOpenDoc(id, viewname, parms, scrollbars, menubar, toolbars, statusbar) {
 dbpath = getHomeLocation(window);
 openDoc(dbpath, id, viewname, parms, scrollbars, menubar, toolbars, statusbar);
}
function whatsnewOpenDoc(div, id, parms) {
 dbpath = '/shared/Divisions/' + div + '/bidmgmt.nsf';
 openDoc(dbpath, id, 'wdocsbyid', parms, 'yes', 'yes', 'no', 'yes');
}
function openDoc(dbpath, id, viewname, parms, scrollbars, menubar, toolbars, statusbar) {
 target = dbpath + "/" + viewname + "/" + id + "?open&login";
 if (parms.length > 0) {
  target = target + parms;
 }
 winParms = windowparmBase + ",scrollbars=" + scrollbars + ", menubar=yes, toolbars=" + toolbars + ", status=" + statusbar;
 //DROMyWindow = window.open(target, id, winParms);
 MyWindow = window.open(target, "_blank", winParms);
 //MyWindow.window.focus();
}
function rowopen(x){ //only for use by internal users
 window.open(window.location.pathname + "/" + x);
}

function viewOpenMarkRead(id, parms, linktype, scrollbars, menubar, toolbars, statusbar) {
 dbpath = getHomeLocation(window);
 openMarkRead(dbpath, id, parms, linktype, scrollbars, menubar, toolbars, statusbar);
}
function whatsnewMarkRead(div, id, parms, linktype) {
 dbpath = '/shared/Divisions/' + div + '/bidmgmt.nsf';
 openMarkReadDoc(dbpath, id, parms, linktype, 'yes', 'yes', 'no', 'yes');
}
function openMarkRead(dbpath, id, parms, linktype, scrollbars, menubar, toolbars, statusbar) {
 var parmbase = parms;
 switch (linktype){
  case "bid":
   parmbase = "?editdocument&login&count=50&start=1!!";
   break;
  case "bidsheet":
   parmbase = "?editdocument&login&count=50&start=1!!";
   break;
  case "file":
   if (parms=='' || parms=='XMLData') {
    parmbase = "!!";
   } else {
    parmbase = "/$file/" + parms + "?open&login!!";
   }
   break;
  case "xmlcontent":
   if (parms=='') {
    parmbase = "xmlcontent!!";
   } else {
    parmbase = parms + "!!";
   }
   break;
  case "xml":
   if (parms=='') {
    parmbase = "xmlcontent!!";
   } else {
    parmbase = parms + "!!";
   }
   break;
  default:
   parmbase = parms;
 }
 
 target = dbpath + "/opendoc?openagent&login&docid=" + id + "&parms=" + parmbase;
 winParms = windowparmBase + ",scrollbars=" + scrollbars + ", menubar=yes, toolbars=" + toolbars + ", status=" + statusbar;
 //DROMyWindow = window.open(target, id, winParms);
 MyWindow = window.open(target, "_blank", winParms);
 pageTracker._trackPageview(getPath(target));
 //MyWindow.window.focus();
}
function viewOpenMarkReadSource(type, var1, var2, scrollbars, toolbars, statusbar, pathoverride, overridediv) {
    //open data from specified method
    var dbpath;
    var winParms;
    var parmbase;
    switch (type) {
	    case 'ponum':
        	parmbase = '&type=ponum&ponum=' + var1;
	        break;
	    case 'pojobcc':
        	parmbase = '&type=pojobcc&jobid=' + var1 + '&cc=' + var2;
	        break;
	    default:
        	parmbase = '&type=other&docid=' + var1 + '&parms=' + '&v0=' + type + '&v2=' +var2 + '!!';
    }
    if (pathoverride==true) {
        dbpath = '/shared/Divisions/' + overridediv + '/bidmgmt.nsf';
    } else {
        dbpath = getDBDirectory(document) + '/bidmgmt.nsf';
    }
    var target = dbpath + '/opendoc?open&login' + parmbase;
    winParms = windowparmBase + ',scrollbars=' + scrollbars + ', menubar=yes, toolbars=' + toolbars + ', status=' + statusbar;
    MyWindow = window.open(target, '_blank', winParms);
    pageTracker._trackPageview(getPath(target));
}
function openMarkReadDoc(dbpath, id, parms, linktype, scrollbars, menubar, toolbars, statusbar) {
     var parmbase = parms;
     switch (linktype){
      case "bid":
       parmbase = "?editdocument&login&count=50&start=1!!";
       break;
      case "bidsheet":
       parmbase = "?editdocument&login&count=50&start=1!!";
       break;
      case "file":
       if (parms=='' || parms=='XMLData') {
        parmbase = "!!";
       } else {
        parmbase = "/$file/" + parms + "?open&login!!";
       }
       break;
      case "xmlcontent":
       if (parms=='') {
        parmbase = "xmlcontent!!";
       } else {
        parmbase = parms + "!!";
       }
       break;
      default:
       parmbase = parms;
     }
     
     target = dbpath + "/openatt?open&login&docid=" + id + "&parms=" + parmbase;
     winParms = windowparmBase + ",scrollbars=" + scrollbars + ", menubar=yes, toolbars=" + toolbars + ", status=" + statusbar;
     //DROMyWindow = window.open(target, id, winParms);
     MyWindow = window.open(target, "_blank", winParms);
     pageTracker._trackPageview(getPath(target));
     //MyWindow.window.focus();
}
function openPaymentDetail(type, var1, var2, scrollbars, toolbars, statusbar, pathoverride, overridediv) {
    var dbpath;
    var target;
    dbpath = getDBDirectory(document) + '/paymentinfo.nsf';
    winParms = windowparmBase + ',scrollbars=' + scrollbars + ', menubar=yes, toolbars=' + toolbars + ', status=' + statusbar;
    switch (type) {
      case 'jobcc':
        target = dbpath + '/opendoc?open&login&type=' + type + '&job=' + var1 + '&cc=' + var2;
        MyWindow = window.open(target, '_blank', winParms);
        break;
      case 'ponum':
        target = dbpath + '/opendoc?open&login&type=' + type + '&ponum=' + var1;
        MyWindow = window.open(target, '_blank', winParms);
        break;
      default:
        alert('We apologize: A connection could not be made');
    }
}

function closeWindow() {
 if(window.opener) {
  try {
    if(window.opener.top.document.view) {
     window.opener.top.document.view.location.reload();
     window.close();
    } else if (window.opener.top.document.div) {
     window.opener.top.document.div.location.reload();
     window.close();
    } else {
     window.opener.top.location.reload();
     window.close();
    }
  }
  catch(er){
   window.top.location.href = "http://" + location.host;
  }
 }else{
  if (window.top.location.pathname == "/shared/vendors.nsf/wcontact") {
   window.top.location="/";
  } else {
   window.top.location="/mybuildwithcentex";
  }
 }
}
function closeWindowEditConfirm() {
 if (confirm("Any changes you have not saved will be lost. Do you wish to continue?")) {
  closeWindow()
 }
}
function changeCSS(cssClass,element,value) {
  var cssRules;
  if (document.all) {
   cssRules = 'rules';
  }
  else if (document.getElementById) {
   cssRules = 'cssRules';
  }
  for (var S = 0; S < document.styleSheets.length; S++){
   for (var R = 0; R < document.styleSheets[S][cssRules].length; R++) {
   if (document.styleSheets[S][cssRules][R].selectorText == cssClass) {
    document.styleSheets[S][cssRules][R].style[element] = value;
   }
  }
 } 
}
function changeToHourglass(setOnOff) {
 if (setOnOff) {
  document.body.style.cursor='wait';
  changeCSS('.button','cursor','wait');
 } else {
  document.body.style.cursor='';
  changeCSS('.button','cursor','hand'); 
 }
}
 
function ResizeIFrame(iframeName, vertOffset,iframevMin) {
 if (vertOffset == "") vertOffset = 100;
 if (iframevMin == "") iframevMin = 100;
 
 if(document.getElementById(iframeName)) {
  if(navigator.appName=="Microsoft Internet Explorer") {
   var y= document.body.offsetHeight-document.getElementById(iframeName).offsetTop-vertOffset;
  } else {
   var y= window.innerHeight-document.getElementById(iframeName).offsetTop-vertOffset;
  }
  if (y<iframevMin) {
   y=iframevMin;
  }
  document.getElementById(iframeName).height = y;
 }
}
function ResizeObject(objName, vertOffset, vMin, horzOffset, hMin) {
 if (vertOffset == "") vertOffset = 100;
 if (vMin == "") vMin = 100;
 
 if(document.getElementById(objName)){
  if(navigator.appName=="Microsoft Internet Explorer") {
   var y= document.body.offsetHeight-document.getElementById(objName).offsetTop-vertOffset;
  } else {
   var y= window.innerHeight-document.getElementById(objName).offsetTop-vertOffset;
  }
  if (y<vMin) {
   y=vMin;
  }
 
  document.getElementById(objName).height = y;
 
  if(horzOffset) {
   if(navigator.appName=="Microsoft Internet Explorer") {
    var x= document.body.offsetWidth-(horzOffset*2);
   } else {
    var x= window.innerWidth-(horzOffset*2);
   }
   if (vMin == "") vMin = 5;
   if (x<hMin) {
    x=hMin;
   }
   document.getElementById(objName).width = x;
  }
 }
}
function viewExpandCollapse(myview, vpath, vtype) {
 vpathcat = new String("");
 vpathNew = new String("");
 
 switch (vtype) {
  case "Expand":
  case "+":
  case "expand":
   arg1 = "&ExpandView";
   find1 = "&Collapse";
   find2 = "&Expand";
   break
  case "Collapse":
  case "collapse":
  case "contract":
  case "-":
   arg1 = "&CollapseView";
   find1 = "&Expand";
   find2 = "&Collapse";
   break
  default :
   return;
 }
 vpathNew = vpath;
 if(vpath.indexOf("&restricttocategory")>0) { //is the view a sub category
  myvar = vpath.split("&restricttocategory=");
  vpathcat = myvar[1];
  vpathNew = myvar[0];
 } else if(vpath.indexOf("&RestrictToCategory")>0) { //is the view a sub category
  myvar = vpath.split("&RestrictToCategory=");
  vpathcat = myvar[1];
  vpathNew = myvar[0];
 }
 if(vpathcat.indexOf("&")>0) vpathcat = vpathcat.substr(0, vpathcat.indexOf("&"));
 if(vpathcat.indexOf("#")>0) vpathcat = vpathcat.substr(0, vpathcat.indexOf("#"));
 if(vpathcat != "") vpathcat = "&restricttocategory=" + vpathcat
 

 //alert("vpathcat=" + vpathcat);
 
 if(vpath.indexOf(arg1)>0) { //already in requested state
  //alert('0. ' + vpath)
 } else {
  if(vpath.indexOf(find1)>0) vpathNew = vpath.substr(0, vpath.indexOf(find1));
  if(vpath.indexOf(find2)>0) vpathNew = vpath.substr(0, vpath.indexOf(find2));
  if(vpathcat !="" && !(vpathNew.indexOf("&restricttocategory")>0 || vpathNew.indexOf("&RestrictToCategory")>0)) {
   vpathNew = vpathNew + vpathcat;
   //alert("Base Path: " + vpath + "\n\nNew  Path: " + vpathNew)
  }
  myview.location = vpathNew + arg1 + "&login";
 }
}
function setDivVisibility(divID,isVis) {
 if (isVis) {
  vis = "visible";
  disp = "block";
 } else {
  vis = "hidden";
  disp = "none";
 }
 if (document.layers) {
  document.layers[divID].visibility = vis;
  document.layers[divID].display = disp;
 } else if (document.all) {
  document.all(divID).style.visibility = vis;
  document.all(divID).style.display = disp;
 } else {
  document.getElementById(divID).style.visibility = vis;
  document.getElementById(divID).style.display = disp;
 }
}
function setDivInnerHTML(divID, textMsg) {
 if (document.layers) {
  document.layers[divID].innerHTML = textMsg;
 } else if (document.all) {
  document.all(divID).innerHTML = textMsg;
 } else {
  document.getElementById(divID).innerHTML = textMsg;
 }
}

//****    PickList Utilities   ***************************************************************
function selectAll(opt){
 for(var i=0; i<opt.length; i++) {
  opt[i].selected = true;
 }
}

function deSelectAll(opt){
 for(var i=0; i<opt.length; i++) {
  opt[i].selected = false;
 }
}
sortitems = 1;  // Automatically sort items within lists? (1 or 0)
function move(fbox,tbox) {
 for(var i=0; i<tbox.options.length; i++) {
  if(tbox.options[i].text == "") {
   tbox.options[i] = null;
  }
 }
 for(var i=0; i<fbox.options.length; i++) {
  if(fbox.options[i].selected && fbox.options[i].value != "") {
   var no = new Option();
   no.value = fbox.options[i].value;
   no.text = fbox.options[i].text;
   tbox.options[tbox.options.length] = no;
   fbox.options[i].value = "";
   fbox.options[i].text = "";
  }
 }
 BumpUp(fbox);
 if (sortitems) SortD(tbox);
}

function BumpUp(box)  {
 for(var i=0; i<box.options.length; i++) {
  if(box.options[i].value == "")  {
   for(var j=i; j<box.options.length-1; j++)  {
    box.options[j].value = box.options[j+1].value;
    box.options[j].text = box.options[j+1].text;
   }
   var ln = i;
   break;
  }
 }
 if(ln < box.options.length)  {
  box.options.length -= 1;
  BumpUp(box);
 }
}

function SortD(box)  {
 var temp_opts = new Array();
 var temp = new Object();
 for(var i=0; i<box.options.length; i++)  {
  temp_opts[i] = box.options[i];
 }
 for(var x=0; x<temp_opts.length-1; x++)  {
  for(var y=(x+1); y<temp_opts.length; y++)  {
   if(temp_opts[x].text > temp_opts[y].text)  {
    temp = temp_opts[x].text;
    temp_opts[x].text = temp_opts[y].text;
    temp_opts[y].text = temp;
    
    tempv = temp_opts[x].value;
    temp_opts[x].value = temp_opts[y].value;
    temp_opts[y].value = tempv;
    }
    }
 }
 
 for(var i=0; i<box.options.length; i++)  {
  box.options[i].value = temp_opts[i].value;
  box.options[i].text = temp_opts[i].text;
   }
}

//****    Cookie Utilities     ***************************************************************
// appendCookie: Append a name/value pair to a CookieVal string
// cCookieVal - CookieVal string to which the name/value pair should be appended.
// cName - name of the name/value pair. No duplicate name checking.
// cValue - value of the name/value pair.
// returns - new CookieVal
function CookieAppendVal(cCookieVal, cName, cValue) {
   // We concatenate a new name/value pair to the Cookie value.
   // This is stored in string format
   return cCookieVal + "&" + cName + ":" + escape(cValue);
}

// extractCookie: Given the name, extract a value from a CookieVal string
// cCookieVal - CookieVal string from which the value should be extracted.
// cName - name of the name/value pair. 
// returns - value or empty string if not found.
function CookieExtractVal(cCookieVal, cName) {
   // look for specified name and return value
   // CookieVal is stored as string
   var cReturn;   // The return value
   if ("" == cCookieVal) return "";   // No values
   
   // Now find the specific cStoreName cookie in the string
   var nStart = cCookieVal.indexOf("&" + cName + ":");
   if (-1 == nStart) return "";  // cName not found
   nStart += cName.length + 2;   // Point at first data char
   var nEnd = cCookieVal.indexOf("&", nStart); // Find the end
   if (-1 == nEnd) {
      nEnd = cCookieVal.length; // Point at last char
   }
   cReturn = cCookieVal.substring(nStart, nEnd); // Extract the Cookie
   return cReturn;  // and return it
}

// saveCookie: Save a CookieVal to Web browser. May have several name/value pairs
// cStoreName - Actual cookie name for browser.
// cCookieVal - CookieVal to save.
// nSeconds - (optional) (integer) Duration the cookie should live (secs).
// cDomain - (optional) Domain name.
// cPath - (optional) Path for the cookie.
// bSecure - (optional) (boolean)
// returns - void
function CookieSave(doc, cStoreName, cCookieVal, nSeconds, cDomain, cPath, bSecure ) {
   var cCooking;  // Used to store intermediate strings
   var dtExpires = new Date(today.getTime() + (60 * 60 * 24 * 365 * 1000)); // Date this cookie expires
   cCooking = cStoreName + "=" + cCookieVal // The name=value
   if (nSeconds) { // Calculate expiration date
      dtExpires = new Date((new Date()).getTime() + 1000 * nSeconds);
   cCooking += "; expires=" + dtExpires.toGMTString();
   }
   if (cDomain) {cCooking += "; domain=" + cDomain}
   if (cPath) {cCooking += "; path=" + cPath}
   if (bSecure) {cCooking += "; secure"}
   // Done cooking, now assign the cookie
   doc.cookie = cCooking;
}

// loadCookie: Load a CookieVal - May contain several name/value pairs.
// cStoreName - cookie name for browser.
// returns - CookieVal string or empty string if not found.
function CookieLoad(doc, cStoreName) {
   var cCooking;  // store intermediate strings
   var cReturn;   // return value
   cCooking = doc.cookie; // Get all the Cookie name/values
   if ("" == cCooking) return "";   // No values
   
   // find the specific cStoreName cookie in the string
   var nStart = cCooking.indexOf(cStoreName + "=");
   if (-1 == nStart) return "";  // cStoreName not found
   nStart += cStoreName.length + 1; // Point at first data char
   var nEnd = cCooking.indexOf(";", nStart); // Find the end
   if (-1 == nEnd) {
      nEnd = cCooking.length; // Point at last char
   }
   cReturn = cCooking.substring(nStart, nEnd); // Extract the CookieVal
   return cReturn;
}