/* CSR.js
 * --------
 * The CSR Javascript Library
 * Version 1.0
 * Created: 02.21.2002
 *
 */


/****************************
GUI Functions
*****************************/

function CSR_popupTextArea(formName, inputName, txtValue) {
  pop = window.open("","details","dependent=yes,height=270,width=200,menu=yes");
  pop.document.write("<html><head><title>Details<\/title>\n");
  pop.document.write('<\/head><body>\n');
  pop.document.write('<form name="popup">\n');
  pop.document.write('<textarea name="details" cols="20" rows="10">' + txtValue + '<\/textarea>\n');
  var js = "details.value=' '";
  pop.document.write('<br><center><input type="button" value="Clear" onclick="javascript:' + js + '">\n');
  pop.document.write('<input type="button" value="Save" onclick="javascript:window.opener.document.forms.' + formName + '.' + inputName + '.value=details.value;window.close();"><\/form><\/center>\n');
  pop.document.write("<\/body><\/html>");
  pop.document.close();
}


// TWH (CWI 3.10.1) CR 3200 - this function is called from an onload event.  It replaces all occurrences of 
// "&apos;" within a flex question answer with an apostrophe (').
function CSR_ReplaceApostrophes(tForm) {
  for (var i=0; i<tForm.elements.length; i++) {
    // Require a contact number for every contract type specified.	
		if (tForm.elements[i].name.indexOf("fn_") != -1){
			while (tForm.elements[i].value.indexOf("&apos;") != -1){
				tForm.elements[i].value = tForm.elements[i].value.replace("&apos;","'");
			}
			
		}
	}
}

/****************************
 Smart Date & Time Functions
*****************************/
// TWH (CWI 3.10.1) CR 3198 - changed logic to more closely resemble the standard CSR client application.
function CSR_SmartTime(inputTime)
{
  // Tested under IE5 and NSC4.75 - exceptions documented in-line 11/1/2000
  // Store user input in persistent variable, force input to uppercase, and
  // replace time delimiters with null spaces.
  var input = originalInput = inputTime.value;
  input = input.toUpperCase();
  input = input.replace(";","");
  input = input.replace(",","");
  // Following line had to be commented out because Netscape Communicator 4.75
  // replaces the first character in the string with null, so users who delimit
  // the time with a period will get an invalid time warning.
  // input = input.replace(".","");
  input = input.replace("/","");
  input = input.replace("-","");
  input = input.replace(":","");
  input = input.replace(" ","");
  // Define variables used to determine which case to process.
  var lastChar = parseInt(input.substring(input.length-1, input.length));
  lastChar = lastChar.toString();
  var inputString = input.split('M');
  var inputNumber = parseInt(inputString[0],10);
  var inputNbr2String = inputNumber.toString();
  // Loop through each character of input string to determine if input
  // is valid for proceeding into case processing
  for (var loopCounter = 0; loopCounter < input.length; loopCounter++){
    var stringChar = input.substring(loopCounter,loopCounter+1);
    var stringNbr = parseInt(stringChar);
    var stringNbr2String = stringNbr.toString();
    if (stringNbr2String.length == 3 && (stringChar == "%" ||
                                         stringChar == "A" ||
                                         stringChar == "P" ||
                                         stringChar == "M")){
      continue
    }
    else if (stringNbr2String.length == 1){
      continue
    }
    else {
      inputTime.value = "";
      inputTime.focus();
      alert("The time you entered - " + originalInput +
              " - was invalid, please enter again. Time is " +
              "expected to be in the format - 12:00 AM.");
      return false;
      break
    }
  }
  // Begin processing input to determine which case to process.
  if (input == "0"){
    var caseVar = 0;
  }
  else if ((lastChar.length == 3) && (inputString[0].length <= 3) &&
           ((inputString[0].substring(0,inputString[0].length - 1) <= 12) &&
            (inputString[0].substring(0,inputString[0].length - 1) >= 1))){
    var hourString = inputString[0].substring(0,inputString[0].length - 1);
    caseVar = 4;
  }
  else
    if ((inputNumber > 0) &&
        (inputNumber <= 2400) &&
        (inputNbr2String.substr(inputNbr2String.length - 2) < 60) &&
        (inputNbr2String.substring(0,inputNbr2String.length - 2) < 25)){
      caseVar = ((lastChar.length == 1) ? 1 : 2);
  }
  else if (input == "" || input == "%"){
    caseVar = 3;
  }
  else {
    caseVar = 5;
  }
  // Un-comment out the next line to tell which case applies
  // alert("caseVar = " + caseVar);
  // Based on preceding logic, only one given case will be processed.
  // Note, for cases not listed, the default case is processed.
  switch(caseVar) {
    case 0:
      var now = new Date();
      var nowHours = now.getHours();
      var nowMinutes = now.getMinutes();
      var nowMinutes = ((nowMinutes < 10) ? "0" + nowMinutes : nowMinutes);
      var nowAMPM = ((nowHours > 12) ? " PM" : " AM");
      var nowHours = ((nowHours > 12) ? (nowHours - 12) : nowHours);
      inputTime.value = nowHours + ":" + nowMinutes + nowAMPM;
      break;
    case 1:
      var InputHours = 0;
      if ( input > 12 && input < 100 ) {
      	inputTime.value = "";
        inputTime.focus();
      	alert("The time you entered - " + originalInput +
                " - is invalid. Please enter time in the format HH:MM AM.");
        break;
      }
      if ( input > 0 && input < 13 ) {
        InputHours = parseInt(input);
      }
      else {
	      InputHours = ((parseInt(input) > 1259) ?
	                   ((input.substring(0,input.length-2)) - 12) :
	                   ((input.substring(0,input.length-2))));
	      InputHours = ((parseInt(input) < 100) ? "12" : InputHours);
	    }

      var InputMinutes = "00";
      if ( input > 0 && input < 13 ) {
      	InputMinutes = "00";
      }
      else {
	      InputMinutes = input.substring(input.length-2,input.length);
	      InputMinutes = ((parseInt(InputMinutes) < 10 && InputMinutes.length == 1) ? "0" + InputMinutes : InputMinutes);
	    }

      
      var InputAMPMInd = ((parseInt(input) > 1159) &&
                      (parseInt(input) < 2400) ? " PM" : " AM");
      inputTime.value = input = InputHours + ":" + InputMinutes + InputAMPMInd;
      break;
    case 2:
      var tempNumber = input.replace("P","");
      var tempNumber = tempNumber.replace("M","");
      if ( tempNumber < 100 ) {
      	inputTime.value = "";
        inputTime.focus();
      	alert("The time you entered - " + originalInput +
                " - is invalid. Please enter time in the format HH:MM AM.");
        break;
      }
      input = input.replace(" ","");
      input = input.replace("M","");
      input = (input.substring(0,input.length - 3) == null ||
               input.substring(0,input.length - 3) == "0"  ||
               input.substring(0,input.length - 3) == "00" ?
               "12" : input.substring(0,input.length - 3)) + ":" +
              input.substring(input.length - 3,input.length - 1) + " " +
              input.substr(input.length - 1) + "M";
      var finalTestString = input.split(':');
      if (finalTestString[0] > 12){
        inputTime.value = "";
        inputTime.focus();
        alert("The time you entered - " + originalInput +
                " - was invalid, please enter again. Time is " +
                "expected to be in the format - 12:00 AM.");
      }
      else
        inputTime.value = input;
      break;
    case 3:
      break;
    case 4:
      inputTime.value = hourString + ":00 " +
                        inputString[0].substr(inputString[0].length - 1) +
                        "M";
      break;
    default:
      inputTime.value = "";
      inputTime.focus();
      alert("The time you entered - " + originalInput +
              " - was invalid, please enter again. Time is " +
              "expected to be in the format - 12:00 AM.");
      break;
  }
}
function CSR_SmartDate(inputDate)
{
  // Tested under IE5 and Netscape Communicator 4.75 successfully - 11/02/2000
  // Store user input in persistent variable, force input to uppercase, and
  // define the current date and other variables used to control processing.
  var input = originalInput = inputDate.value;
  input = input.toUpperCase();
  var today = new Date();
  var newYear = todayYear = today.getFullYear();
  var newMonth = todayMonth = today.getMonth();
  var newDay = todayDay = today.getDate();
  var caseVar = null;
  var timeToAdd = 0;
  // Begin processing input to determine which case to process.
  if (input == "0"){
    caseVar = 0;
  }
  else if ((input > 0) || (input < 0)){
    caseVar = 1;
  }
  else if (input == "EM"){
    caseVar = 2;
  }
  else if (input == "BM"){
    caseVar = 3;
  }
  else if (input == "EY"){
    caseVar = 4;
  }
  else if (input == "BY"){
    caseVar = 5;
  }
  else if ((input.lastIndexOf('-') - input.indexOf('-')) == 4){
    caseVar = 6;
  }
  else if (input.length > 5){
    caseVar = 7;
  }
  else if (input == "" || input == "%"){
    caseVar = 8;
  }
  else {
    inputDate.value = "";
    inputDate.focus();
    alert("The date you entered - " + originalInput +
      " - is invalid.  Please enter again. Dates are " +
      "expected to be in the format - MON dd, yyyy.");
    return false;
  }
  // Based on preceding logic, only one given case will be processed.
  switch(caseVar){
    case 0:
      break;
    case 1:
      if (parseInt(input,10) > 1010000 && parseInt(input,10) <= 12319999){
        newYear = parseInt(input.substr(input.length - 4),10);
        newDay = parseInt(input.substr(input.length - 6, 2),10);
        newMonth = parseInt(input.substr(0,(input.length == 8 ? 2 : 1)),10) - 1;
        break;
      }
      else if (parseInt(input,10) > 10100 && parseInt(input,10) <= 123199){
        newYear = parseInt(input.substr(input.length - 2),10);
        //alert('newYear='+newYear);
        if (newYear < 100) {
          if (parseInt(newYear) >=50) {
            newYear = 1900 +  newYear;
          }
          else {
            newYear = 2000 + newYear;
          }
        }
        //alert('newYear='+newYear);
        newDay = parseInt(input.substr(input.length - 4, 2),10);
        newMonth = parseInt(input.substr(0,(input.length == 6 ? 2 : 1)),10) - 1;
        break;
      }
      else {
        //alert("else");
        //newYear = parseInt(input.substr(input.length - 4),10);
        //newDay = parseInt(input.substr(input.length - 6, 2),10);
        //newMonth = parseInt(input.substr(0,(input.length == 8 ? 2 : 1)),10) - 1;
        // Netscape 4.75 cannot utilize math based on days to extend beyond the
        // beginning of the current month, so subtracting a number of days greater
        // than the day of the month returns the first day of the month.  Curiously,
        // adding a number of days past the end of the month is calculated correctly.
        // To circumvent this shortcoming, we simply multiply the negative
        // number by the equivalent of a day in milliseconds (864000000) to get
        // the number of milliseconds to subtract from the current time.

        var bErr = false;
        if ((input.charAt(0) == "+") || (input.charAt(0) == "-")) {
          //alert("plus!");
          if ((parseInt(input,10) < 1010000) && (parseInt(input,10) > -1009999)) {
            timeToAdd = parseInt(input,10) * 86400000;
          }
          else {
            bErr = true;
          }
        }
        else {
          //alert("else");
          if (parseInt(input,10) <= 1010000) {
              newDay = parseInt(input,10);
          }
          else {
            newYear = parseInt(input.substr(input.length - 4),10);
            newDay = parseInt(input.substr(input.length - 6, 2),10);
            newMonth = parseInt(input.substr(0,(input.length == 8 ? 2 : 1)),10) - 1;
          }
        }
        if (bErr) {
          inputDate.value = "";
          inputDate.focus();
          alert("The date you entered - " + originalInput +
                " - is invalid.  Please enter again. Dates are " +
                "expected to be in the format - MON dd, yyyy.");
         return false;
        }
        //newDay = parseInt(newDay) + parseInt(input,10);
        //var calcDate = new Date(newYear,newMonth,newDay);
        //newYear = calcDate.getFullYear();
        //newMonth = calcDate.getMonth();
        //newDay = calcDate.getDate();
        break;
      }
    case 2:
      // Since Netscape bases reverse date calculation on milliseconds, we
      // have to set the date to the first of the next month and then add
      // the equivalent of a negative day (-86400000 milliseconds).
      newMonth = parseInt(today.getMonth()) + 1;
      newDay = 1;
      timeToAdd = -86400000;
      break;
    case 3:
      newDay = 1;
      break;
    case 4:
      newMonth = 11;
      newDay = 31;
      break;
    case 5:
      // The Netscape browser cannot interpret 2/0/1999 as 1/31/1999, so
      // the end of month function returns the first day of the next month
      // and does not work correctly.
      newMonth = 0;
      newDay = 1;
      break;
    case 6:
      var datestring = input.split('-');
      newYear = datestring[2];
      if (newYear.length == 2) {
        if (parseInt(newYear) >=50) {
          newYear = '19' +  newYear;
        }
        else {
          newYear = '20' + newYear;
        }
      }
      newDay = datestring[0];
      newMonth = Month2Num(datestring[1]);
      //alert(newMonth);
      if (newMonth == "NULL") {
        inputDate.value = "";
        inputDate.focus();
        alert("The date you entered - " + originalInput +
                " - is invalid.  Please enter again. Dates are " +
                "expected to be in the format - MON dd, yyyy.");
        return false;
      }
      break;
    case 7:
      if (input.indexOf('/') != -1){
        var datestring = input.split("/");
      }
      else if (input.indexOf('-') != -1){
        var datestring = input.split("-");
      }
      else if (input.indexOf('.') != -1){
        var datestring = input.split(".");
      }
      else if (input.indexOf(',') != -1) {
        if (input.charAt(input.indexOf(',') + 1) != " ") {
          input = input.substring(0, input.indexOf(',')+1) + " " + input.substring(input.indexOf(',')+1);
        }
        var datestring = input.split(" ");
        var eMonth = datestring[0];
        var tMonth = Month2Num(eMonth);
        if (tMonth == "NULL") {
          inputDate.value = "";
          inputDate.focus();
          alert("The month you entered - " + eMonth  +
                " - is invalid.  Please enter again using a 3-digit format (MON).");
          return false;
        }
        //alert("tMonth="+tMonth);
        var tDay = datestring[1].substring(0,datestring[1].length-1);
        //alert("tDay="+tDay);
        var tYear = datestring[2];
        //alert("tYear="+tYear);
        datestring = [tMonth+1, tDay, tYear];
      }
      else {
        inputDate.value = "";
        inputDate.focus();
        alert("The date you entered - " + originalInput +
                " - is invalid.  Please enter again. Dates are " +
                "expected to be in the format - MON dd, yyyy.");
        return false;
      }
      newMonth = datestring[0] - 1;
      // make sure newMonth is a number
      if (isNaN(newMonth)) {
        inputDate.value = "";
        inputDate.focus();
        alert("The date you entered - " + originalInput +
                " - is invalid.  Please enter again. Dates are " +
                "expected to be in the format - MON dd, yyyy.");
        return false;
      }
      newDay = datestring[1];
      newYear = datestring[2];
      if (newYear.length == 2) {
        if (parseInt(newYear) >=50) {
          newYear = '19' +  newYear;
        }
        else {
          newYear = '20' + newYear;
        }
      }
      else if (parseInt(newYear) >=100 && parseInt(newYear) < 1000) {
        alert("The year you entered - " + newYear + " - is an invalid year. Please enter again.");
        return false;
      }

      /*
      alert('newMonth=' + newMonth);
      alert('newDay=' + newDay);
      alert('newYear=' + newYear);
      */
      break;
    case 8:
      return false;
      break;
  }
  // Format and validate the date set by the previous case processing.
  var daysInMonth = new Array(12);
  daysInMonth[0] = 31;
  daysInMonth[1] = (isLeapYear(newYear) ? 29 : 28);
  daysInMonth[2] = 31;
  daysInMonth[3] = 30;
  daysInMonth[4] = 31;
  daysInMonth[5] = 30;
  daysInMonth[6] = 31;
  daysInMonth[7] = 31;
  daysInMonth[8] = 30;
  daysInMonth[9] = 31;
  daysInMonth[10] = 30;
  daysInMonth[11] = 31;
  var outputDate = new Date(newYear,newMonth,newDay);
  //alert('outputDate='+outputDate);
  outputDate.setTime(outputDate.getTime() + timeToAdd);
  var outputYear = outputDate.getFullYear(); //change to .getYear() for 2-digit yr
  //alert('outputYear=' + outputYear);
  var outputMonth = outputDate.getMonth();
  var outputDay = outputDate.getDate();
  if ((newYear >= 0) && (newYear <= 9999)){
    if ((newMonth >= 0) && (newMonth <= 11)){
      if((newDay >= 0) && (newDay <= daysInMonth[newMonth])){
        outputMonth = Num2Month(outputMonth);
        inputDate.value = (outputMonth + ' ' + (parseInt(outputDay,10) < 10 ? '0' + outputDay : outputDay) + ', '+ outputYear);
      }
      else {
        inputDate.value = "";
        inputDate.focus();
        alert("The day you entered - " + newDay +
          " - is invalid.  Please enter a day between 1 and " +
          daysInMonth[newMonth] + ".");
        return false;
      }
    }
    else {
      inputDate.value = "";
      inputDate.focus();
      alert("The month you entered - " + (newMonth + 1) +
        " - is invalid.  Please enter a month between 1 and 12.");
      return false;
    }
  }
  else {
    inputDate.value = "";
    inputDate.focus();
    alert("The year you entered - " + newYear +
      " - is invalid, please enter a year between 0 and 3000.");
    return false;
  }
}
// helper function
function isLeapYear(newYear)
{
  if (newYear % 4 == 0 && newYear % 400 == 0){
    return true;
  }
  else {
    return false;
  }
}
// helper function
function Month2Num(month) {
  var newMonth;
  switch(month){
    case "JAN":
      newMonth = 0;
      break;
    case "FEB":
      newMonth = 1;
      break;
    case "MAR":
      newMonth = 2;
      break;
    case "APR":
      newMonth = 3;
      break;
    case "MAY":
      newMonth = 4;
      break;
    case "JUN":
      newMonth = 5;
      break;
    case "JUL":
      newMonth = 6;
      break;
    case "AUG":
      newMonth = 7;
      break;
    case "SEP":
      newMonth = 8;
      break;
    case "OCT":
      newMonth = 9;
      break;
    case "NOV":
      newMonth = 10;
      break;
    case "DEC":
      newMonth = 11;
      break;
    default:
      newMonth = "NULL";
      break;
  }
  return newMonth;
}
// helper function
function Num2Month(number) {
  var outputMonth;
  switch(number){
    case 0:
      outputMonth = "JAN";
      break;
    case 1:
      outputMonth = "FEB";
      break;
    case 2:
      outputMonth = "MAR";
      break;
    case 3:
      outputMonth = "APR";
      break;
    case 4:
      outputMonth = "MAY";
      break;
    case 5:
      outputMonth = "JUN";
      break;
    case 6:
      outputMonth = "JUL";
      break;
    case 7:
      outputMonth = "AUG";
      break;
    case 8:
      outputMonth = "SEP";
      break;
    case 9:
      outputMonth = "OCT";
      break;
    case 10:
      outputMonth = "NOV";
      break;
    case 11:
      outputMonth = "DEC";
      break;
    default:
      outputMonth = "NULL";
      break;
  }
  return outputMonth;
}

/****************************
 Validation Functions
*****************************/

// Flex Question Min/Max validation
function CSR_CheckRange(field, min, max) {
  if (field.value == '') return;
  // TWH 1/25/2005 (CQT 2761) - changed isInteger call to isFloat
  if (isFloat(field.value, false)==false) {
    warnInvalid(field, "You must enter a valid number (or leave blank) to continue.");
  }
  else {
    if (min!=0 && max!=0) {
      // check range
      if (field.value < min || field.value > max) {
        warnInvalid(field, "You must enter a number between " + min + " and " + max + " to continue.");
      }
    }
  }
}

function CSR_ForceUpperCase(field) {
  // Forces the field value to uppercase
  var input = field.value;
  input = input.toUpperCase();
  field.value = input;
}


// *******************************
// from FormChek.js
//
// 18 Feb 97 created Eric Krock
//
// (c) 1997 Netscape Communications Corporation


var defaultEmptyOK = true

// non-digit characters which are allowed in phone numbers
var phoneNumberDelimiters = "()- ";

var iUSPhone = "This field must be a 10 digit U.S. phone number (like 415-555-1212). Please reenter it now."
var iEmail = "This field must be a valid email address (like foo@bar.com). Please reenter it now."
var iZIPCode = "This field must be a 5 or 9 digit U.S. ZIP Code (like 94043). Please reenter it now."

var digits = "0123456789";
// characters which are allowed in US phone numbers
var validUSPhoneChars = digits + phoneNumberDelimiters;
// U.S. phone numbers have 10 digits.
// They are formatted as 123 456 7890 or (123) 456-7890.
var digitsInUSPhoneNumber = 10;

// U.S. ZIP codes have 5 or 9 digits.
// They are formatted as 12345 or 12345-6789.
var digitsInZIPCode1 = 5
var digitsInZIPCode2 = 9

// non-digit characters which are allowed in ZIP Codes
var ZIPCodeDelimiters = "-";


// whitespace characters
var whitespace = " \t\n\r";


// Check whether string s is empty.

function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}

// Returns true if character c is a digit
// (0 .. 9).

function isDigit (c)
{   return ((c >= "0") && (c <= "9"))
}


//
// isInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters in string s are numbers.
//
// Accepts non-signed integers only. Does not accept floating
// point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// By default, returns defaultEmptyOK if s is empty.
// There is an optional second argument called emptyOK.
// emptyOK is used to override for a single function call
//      the default behavior which is specified globally by
//      defaultEmptyOK.
// If emptyOK is false (or any value other than true),
//      the function will return false if s is empty.
// If emptyOK is true, the function will return true if s is empty.
//
// EXAMPLE FUNCTION CALL:     RESULT:
// isInteger ("5")            true
// isInteger ("")             defaultEmptyOK
// isInteger ("-5")           false
// isInteger ("", true)       true
// isInteger ("", false)      false
// isInteger ("5", false)     true

function isInteger (s)

{   var i;

    if (isEmpty(s))
       if (isInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isInteger.arguments[1] == true);

    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {
        // Check that current character is number.
        var c = s.charAt(i);

        if (!isDigit(c)) return false;
    }

    // All characters are numbers.
    return true;
}

/* TWH 1/25/2005 (CQT 2761) - found from popular form checking javascript (formchek.js)*/
// isFloat (STRING s [, BOOLEAN emptyOK])
// 
// True if string s is an unsigned floating point (real) number. 
//
// Also returns true for unsigned integers. If you wish
// to distinguish between integers and floating point numbers,
// first call isInteger, then call isFloat.
//
// Does not accept exponential notation.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isFloat (s) {   
	// BOI, followed by one of these two patterns:
  // (a) one or more digits, followed by ., followed by zero or more digits
  // ... followed by EOI.
  var reFloat = /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/
	if (isEmpty(s)) 
    if (isFloat.arguments.length == 1) return defaultEmptyOK;
    else return (isFloat.arguments[1] == true);

  return reFloat.test(s)
}



/* Notify user that contents of field theField are invalid.
 * String s describes expected contents of theField.value.
 * Put select theField, put focus in it, and return false.
 * 13 OCT 99: Modified so the alert is fired before focus()
 * and select().  IE doesn't mind if alert is fired after
 * focus and select.  Navigator does seem to mind.  Evidently,
 * alert causes focus to leave the field when use in conjunction
 * with an onBlur event handler.  DEC.
*/

function warnInvalid (theField, s)
{   //theField.focus();
    //theField.select();
    alert(s);
    theField.focus();
    
    if ( theField.type.indexOf("select-") == -1 ) {
      theField.select();
    }

    return false;
}


// Returns true if string s is empty or
// whitespace characters only.
function isWhitespace (s)

{   var i;

    // Is s empty?
    if (isEmpty(s)) return true;

    // Search through string's characters one by one
    // until we find a non-whitespace character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {
        // Check that current character isn't whitespace.
        var c = s.charAt(i);

        if (whitespace.indexOf(c) == -1) return false;
    }

    // All characters are whitespace.
    return true;
}


// isEmail (STRING s [, BOOLEAN emptyOK])
//
// Email address must be of form a@b.c -- in other words:
// * there must be at least one character before the @
// * there must be at least one character before and after the .
// * the characters @ and . are both required
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isEmail (s)
{   if (isEmpty(s))
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);

    // is s whitespace?
    if (isWhitespace(s)) return false;

    // there must be >= 1 character before @, so we
    // start looking at character position 1
    // (i.e. second character)
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@")) return false;
    else i += 2;

    // look for .
    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false;
    else return true;
}

// takes USPhone, a string of 10 digits
// and reformats as (123) 456-789

function reformatUSPhone (USPhone)
{   //return (reformat (USPhone, "(", 3, ") ", 3, "-", 4))
    return( reformat ( USPhone,"",3,"-",3,"-",4 ))
}



// reformat (TARGETSTRING, STRING, INTEGER, STRING, INTEGER ... )
//
// Handy function for arbitrarily inserting formatting characters
// or delimiters of various kinds within TARGETSTRING.
//
// reformat takes one named argument, a string s, and any number
// of other arguments.  The other arguments must be integers or
// strings.  These other arguments specify how string s is to be
// reformatted and how and where other strings are to be inserted
// into it.
//
// reformat processes the other arguments in order one by one.
// * If the argument is an integer, reformat appends that number
//   of sequential characters from s to the resultString.
// * If the argument is a string, reformat appends the string
//   to the resultString.
//
// NOTE: The first argument after TARGETSTRING must be a string.
// (It can be empty.)  The second argument must be an integer.
// Thereafter, integers and strings must alternate.  This is to
// provide backward compatibility to Navigator 2.0.2 JavaScript
// by avoiding use of the typeof operator.
//
// It is the caller's responsibility to make sure that we do not
// try to copy more characters from s than s.length.
//
// EXAMPLES:
//
// * To reformat a 10-digit U.S. phone number from "1234567890"
//   to "(123) 456-7890" make this function call:
//   reformat("1234567890", "(", 3, ") ", 3, "-", 4)
//
// * To reformat a 9-digit U.S. Social Security number from
//   "123456789" to "123-45-6789" make this function call:
//   reformat("123456789", "", 3, "-", 2, "-", 4)
//
// HINT:
//
// If you have a string which is already delimited in one way
// (example: a phone number delimited with spaces as "123 456 7890")
// and you want to delimit it in another way using function reformat,
// call function stripCharsNotInBag to remove the unwanted
// characters, THEN call function reformat to delimit as desired.
//
// EXAMPLE:
//
// reformat (stripCharsNotInBag ("123 456 7890", digits),
//           "(", 3, ") ", 3, "-", 4)

function reformat (s)

{   var arg;
    var sPos = 0;
    var resultString = "";

    for (var i = 1; i < reformat.arguments.length; i++) {
       arg = reformat.arguments[i];
       if (i % 2 == 1) resultString += arg;
       else {
           resultString += s.substring(sPos, sPos + arg);
           sPos += arg;
       }
    }
    return resultString;
}

// Removes all characters which appear in string bag from string s.

function stripCharsInBag (s, bag)

{   var i;
    var returnString = "";

    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.

    for (i = 0; i < s.length; i++)
    {
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }

    return returnString;
}

// isUSPhoneNumber (STRING s [, BOOLEAN emptyOK])
//
// isUSPhoneNumber returns true if string s is a valid U.S. Phone
// Number.  Must be 10 digits.
//
// NOTE: Strip out any delimiters (spaces, hyphens, parentheses, etc.)
// from string s before calling this function.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isUSPhoneNumber (s)
{   if (isEmpty(s))
       if (isUSPhoneNumber.arguments.length == 1) return defaultEmptyOK;
       else return (isUSPhoneNumber.arguments[1] == true);
    return (isInteger(s) && s.length == digitsInUSPhoneNumber)
}


// isZIPCode (STRING s [, BOOLEAN emptyOK])
//
// isZIPCode returns true if string s is a valid
// U.S. ZIP code.  Must be 5 or 9 digits only.
//
// NOTE: Strip out any delimiters (spaces, hyphens, etc.)
// from string s before calling this function.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isZIPCode (s)
{  if (isEmpty(s))
       if (isZIPCode.arguments.length == 1) return defaultEmptyOK;
       else return (isZIPCode.arguments[1] == true);
   return (isInteger(s) &&
            ((s.length == digitsInZIPCode1) ||
             (s.length == digitsInZIPCode2)))
}

// takes ZIPString, a string of 5 or 9 digits;
// if 9 digits, inserts separator hyphen

function reformatZIPCode (ZIPString)
{   if (ZIPString.length == 5) return ZIPString;
    else return (reformat (ZIPString, "", 5, "-", 4));
}


// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid Email.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function CSR_CheckEmail (theField, emptyOK)
{   if (CSR_CheckEmail.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else if (!isEmail(theField.value, false))
       return warnInvalid (theField, iEmail);
    else return true;
}


// checkUSPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid US Phone.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function CSR_CheckUSPhone (theField, emptyOK)
{   if (CSR_CheckUSPhone.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    {  var normalizedPhone = stripCharsInBag(theField.value, phoneNumberDelimiters)
       if (!isUSPhoneNumber(normalizedPhone, false))
          return warnInvalid (theField, iUSPhone);
       else
       {  // if you don't want to reformat as (123) 456-789, comment next line out
          theField.value = reformatUSPhone(normalizedPhone)
          return true;
       }
    }
}

// checkZIPCode (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid ZIP code.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function CSR_CheckZIPCode (theField, emptyOK)
{   if (CSR_CheckZIPCode.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    { var normalizedZIP = stripCharsInBag(theField.value, ZIPCodeDelimiters)
      if (!isZIPCode(normalizedZIP, false))
         return warnInvalid (theField, iZIPCode);
      else
      {  // if you don't want to insert a hyphen, comment next line out
         theField.value = reformatZIPCode(normalizedZIP)
         return true;
      }
    }
}
// for web intake
function validatelocForm(tForm){
      //alert("in validateForm");
      if (confirmStreetNumberName(tForm)) tForm.submit();
}
// for web intake
function confirmStreetNumberName(tForm) {
      var bValid = true;
      var bAnd = false;

      // if the street name contains 'and', don't
      // require street number
      if (tForm.invStreetName.value != "")
      {
        var sname = new String(tForm.invStreetName.value);
        if ((sname.indexOf(" and ") != -1) ||(sname.indexOf(" AND ") != -1) || (sname.indexOf(" And ") != -1)) {
            bAnd = true;
            bValid = true;
        }
      }
      // if the street name doesn't contain 'and', *always* require street number
      // per Doug on 3/20/03
      if (!bAnd) {
      	// TWH CR 1229 - added invStreetNumRequired field check
        if ( (tForm.invStreetNumber.value == "") && (tForm.invStreetNumRequired.value == "Y") ) {
          //warnInvalid(tForm.invStreetNumber, "You must enter a valid Street Number to continue.");
          warnInvalid(tForm.invStreetNumber, "You must enter a valid Street Number to continue.  If you don't know the street number, use a crossing street to indicate the intersection; for example enter MAIN AND FIFTH to indicate a location on Main Street near the intersection of Fifth Avenue.");
          bValid = false;
        }
        if (tForm.invStreetName.value == "") {
          warnInvalid(tForm.invStreetName, "You must enter a valid Street Name to continue.");
          bValid = false;
        }
      }

      return bValid;
}

// for web intake
function buildIMSLink(tForm) {
      //alert(tForm.name);
      var streetNumber, streetPrefix, streetName, streetSuffix;
      streetNumber = tForm.invStreetNumber.value;
      streetPrefix = tForm.invStreetPrefix.value;
      streetName = tForm.invStreetName.value;
      streetSuffix = tForm.invStreetSuffix.value;
      if (streetNumber == "" || streetName == "") {
        alert("You Must Enter a Valid Street Number and Street Name to Map Address.");
      }
      else {
        var tAddress;
        tAddress = streetNumber + "_";
        if (streetPrefix != "") tAddress += streetPrefix + "_";
        if (streetSuffix != "") {
          tAddress += streetName + "_" + streetSuffix;
        }
        else {
          tAddress += streetName;
        }
        var tURL;
        var tHost;
        // testing
        //tHost = "fl27-dg49m01";
        tHost = location.host;
        tURL = "http://" + tHost + "/website/sanantonio1/viewer.htm?address=" + tAddress;
        //alert(tURL);
        window.open(tURL);
      }

}
// for web intake
function validateinputForm(tForm) {
  // TWH CR 2606 - added call to validateParticpantPhones()
  if ( confirmNoEmail(tForm) &&
       validateRequiredFlexQuestions(tForm) &&
       validateRequiredParticipants(tForm) &&
       validateParticipantPhones(tForm) 
       )
    tForm.submit();
}

// for web intake
// TWH CR 3193, changed message to "or OK to review..."
function confirmNoEmail(tForm) {

    // *********** Checks for CITIZEN type code, if found,
    // *********** then checks if email address is filled in or not
    // *********** if not filled in, popup warning about notification
    // *********** then does the same for CALLER type code
    //alert("in confirmNoEmail");
      for (var i=0; i<tForm.elements.length; i++) {
        //alert(tForm.elements[i].name);
        if (tForm.elements[i].name == "invParticipantEmailAddress_CITIZEN") {
          //alert("found CITIZEN");
          if (tForm.elements[i].value == "") {
            if (confirm("The Citizen E-mail address is required if you want " +
                        "the ability to query the status of your Service " +
                        "Request.  Click Cancel to enter the Citizen E-mail " +
                        "address or OK to review your Service Request.")){
            }
            else {
              tForm.invParticipantEmailAddress_CITIZEN.focus();
              return false;
            }
          }
        }
        else if (tForm.elements[i].name == "invParticipantEmailAddress_CALLER") {
          //alert("found CALLER");
          if (tForm.elements[i].value == "") {
            if (confirm("The Caller E-mail address is required if you want " +
                        "the ability to query the status of your Service " +
                        "Request.  Click Cancel to enter the Caller E-mail " +
                        "address or OK to submit your Service Request.")){
            }
            else {
              tForm.invParticipantEmailAddress_CALLER.focus();
              return false;
            }
          }
        }
      }
      return true;
}

/* validate that required flex
 * questions have answers
 * for web intake
 */

function validateRequiredFlexQuestions (tForm)
	{
		/*
		 * there are at 2 fields created for each flex question,
		 * a hidden field whose name starts with 'req_ind_',
		 * the value will by Y or N. The second field is the
		 * form element for the user to enter/select the answer,
		 * field name starts with 'fn_'.
		 *
		 * this method creates two arrays, one containing the
		 * flags indicating if a flex question is required, the
		 * other containing the values entered by the user. It
		 * then checks to make sure all required fields have data.
		 */

		var flags = new Array();
		var values = new Array();
		var flagcount=0;
		var valuecount=0;


		// build arrays containing flags and flex question values

		for (var i=0; i<tForm.elements.length; i++)
		{
		
			if (tForm.elements[i].name.indexOf("req_ind_") != -1)
			{	flags[flagcount++] = tForm.elements[i].value;
			}

			if (tForm.elements[i].name.indexOf("fn_") != -1)
			{
				if (tForm.elements[i].type=="select-one" || tForm.elements[i].type=="select-multiple")
			    {
					value = "";
					for (var k=0; k<tForm.elements[i].options.length; k++)
					{
						if (tForm.elements[i].options[k].selected)
							value = tForm.elements[i].options[k].text;
					}

					values[valuecount++] = value;
				}
				else
					values[valuecount++] = tForm.elements[i].value;
			}
		}


		// check if a required flex question does not have a value

		for (var j=0; j<flagcount; j++)
		{
			if ((flags[j] == "Y") &&
				((values[j]==null) || (values[j].length==0)))
			{
				alert ("Please answer all mandatory questions (marked in red)");
				return false;
			}
		}

		return true;

} // validateReqiredFlexQuestions()

// for web intake
function doSubmit() {
   document.motForm.submit()
}

// TWH 8/25/2004 web intake
// CR 2633
function doKeywordSubmit(tForm) {
	if ( isEmpty(tForm.invKeyword.value) ) {
		alert("Please enter a Keyword.");
	}
	else {
		document.motForm.submit()
	}	
}

// TWH 1/27/2004 added this function... same as validateRequiredFlexQuestions w/ some minor modifications
// for web intake
function validateRequiredParticipants (tForm)
	{
		/*
		 * there are at 2 fields created for each participant,
		 * a hidden field whose name starts with 'req_part_ind_',
		 * the value will by Y or N. The second field is the
		 * form element for the user to enter/select the answer,
		 * field name starts with 'invParticipant'.
		 *
		 * this method creates two arrays, one containing the
		 * flags indicating if a participant field is required, the
		 * other containing the values entered by the user. It
		 * then checks to make sure all required fields have data.
		 */

		var flags = new Array();
		var values = new Array();
		var flagcount=0;
		var valuecount=0;


		// build arrays containing flags and flex question values
		for (var i=0; i<tForm.elements.length; i++)
		{
			if (tForm.elements[i].name.indexOf("req_part_ind") != -1) {	
			  flags[flagcount++] = tForm.elements[i].value;
			}
					
			if ((tForm.elements[i].name.indexOf("invParticipant") != -1) && (tForm.elements[i].name.indexOf("ContactPhone") == -1))
			//if (tForm.elements[i].name.indexOf("invParticipant") != -1) 
			{			
				if (tForm.elements[i].type=="select-one" || tForm.elements[i].type=="select-multiple")
			    {
					value = "";
					for (var k=0; k<tForm.elements[i].options.length; k++)
					{
						if (tForm.elements[i].options[k].selected) {
						  if (k==0){
					        value = ""; 
					        break;
					      }
					      else {
					        value = tForm.elements[i].options[k].text;
					      }

					    }
					    
					}
					values[valuecount++] = value;
				}
				else {
					values[valuecount++] = tForm.elements[i].value;
				}
			}
			
		}

		// check if a required participant field does not have a value
		for (var j=0; j<flagcount; j++)
		{		
			if ((flags[j] == "Y") &&
				((values[j]==null) || (values[j].length==0)))
			{
				alert ("Please fill in all required Participant information (marked in red)");
				return false;
			}
		}

		return true;

} // validateReqiredParticipants()



/* TWH CR 2606 - new function to
 * validate that appropriate data is filled out for participant phones
 */
function validateParticipantPhones(tForm) {
  
  for (var i=0; i<tForm.elements.length; i++) {
    // Require a contact number for every contract type specified.	
		if (tForm.elements[i].name.indexOf("invParticipantContactPhoneType") != -1){
			var participantCode = "";
			var phoneIndex = 0;
			var lookup = "";
			
			if (tForm.elements[i].value.length > 0) {
				participantCode = tForm.elements[i].name;
        participantCode = participantCode.substr(participantCode.indexOf("_")+1);
        phoneIndex = participantCode.substr(participantCode.indexOf("_")+1);
        participantCode = participantCode.substr(0,participantCode.indexOf("_"));
        lookup = "invParticipantContactPhoneNumber_" + participantCode + "_" + phoneIndex;
				
				for (var s=0; s<tForm.elements.length; s++) {
          if (tForm.elements[s].name.indexOf(lookup) != -1){
		  	    if (tForm.elements[s].value.length == 0) {	  	      
		  	      warnInvalid(tForm.elements[s],"A Contact Number is required for every Contact Type selected.");
		  	      return false;
		  	    }
		  	  }
		    }
		  }
		}
		
		// Require a contact type for every contract number specified.	
		if (tForm.elements[i].name.indexOf("invParticipantContactPhoneNumber") != -1){
			var participantCode = "";
			var phoneIndex = 0;
			var lookup = "";
			
			if (tForm.elements[i].value.length > 0) {
				participantCode = tForm.elements[i].name;
        participantCode = participantCode.substr(participantCode.indexOf("_")+1);
        phoneIndex = participantCode.substr(participantCode.indexOf("_")+1);
        participantCode = participantCode.substr(0,participantCode.indexOf("_"));
        lookup = "invParticipantContactPhoneType_" + participantCode + "_" + phoneIndex;
				
				for (var s=0; s<tForm.elements.length; s++) {
          if (tForm.elements[s].name.indexOf(lookup) != -1){
		  	    if (tForm.elements[s].value.length == 0) {	  	      
		  	      warnInvalid(tForm.elements[s],"A Contact Type must be specified for every Contact Number entered.");
		  	      return false;
		  	    }
		  	  }
		    }
		  }
		}
	}
 
	return true;

} // validateParticipantPhones



// TWH 2/13/2004 added this function.
// for web intake
function GotoURL(site)
{
  if (site == '1') document.motForm.action='Controller?op=csrform';
  if (site == '2') document.motForm.action='Controller?op=reset';
  if (site == '3') document.motForm.action='Controller?op=csrupdate';
  document.motForm.submit();
}

// TWH 8/9/2004 new web intake function
function validateSRQueryForm(tForm)
{
  if (isEmpty(tForm.invSRReferenceNum.value)) {
  	alert("A Service Request Number is required.");
  	return false;
  }
  else if (isEmpty(tForm.invEmailAddress.value)) {
  	alert("An Email Address is required");
  	return false;
  }
  else tForm.submit();
}