// define global vars used in all functions
var regDate = /^(0[1-9]|1[012])[\/](0[1-9]|[12][0-9]|3[01])[\/]20\d\d$/;
var regEmail = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
var regInteger = /^\d+$/;
var regIntegerZeroTo999 = /^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$/; 
var regPostalCode = /^[A-Za-z0-9]+( |-)?[A-Za-z0-9]+$/;
var regCanadianProvinces = /AB|BC|MB|NB|NF|NT|NS|ON|PE|QC|SK|YT/;
var regUSAStates = /AK|AL|AR|AZ|CA|CO|CT|DC|DE|FL|GA|GU|HI|IA|ID|IL|IN|KS|KY|LA|MA|MD|ME|MI|MN|MO|MS|MT|NC|ND|NE|NH|NJ|NM|NV|NY|OH|OK|OR|PA|PR|RI|SC|SD|TN|TX|UT|VA|VT|WA|WI|WV|WY/;
var highlightColor = "#ffff99";
var optionalBackgroundColor = "#eeeeee";
var optionalFontColor = "#6666ff";
var optionalFontStyle = "italic";
var optionalFontSize = "9px";
var optionalString = "Optional";

function validateForm(myForm)
{
  var blankFields = "";
  var foundBlank = false;
  // look for blanks on required fields
  for (var i=0; i < myForm.elements.length; i++) // loop thru all the form elements
  {		
    if (myForm.elements[i]._validate) // test elements with "validate" attribute defined and true
    {
			myForm.elements[i].value = trim(myForm.elements[i].value); // remove leading and trailing spaces
      myForm.elements[i].style.backgroundColor=""; // get rid of the special style if already applied
      if (myForm.elements[i]._required) // test elements with "required" attribute defined and true
      {
        // if blank or negative 1 (used for the "please select" select list values)
        // add the name to the list and change the element's style
        if (myForm.elements[i].value=="" || myForm.elements[i].value=="-1")
        {
          blankFields = blankFields + myForm.elements[i].name + "\n";
          myForm.elements[i].style.backgroundColor=highlightColor;
          if (!foundBlank) // set the id of the field to put focus on when return to form
          {
            foundBlank = true;
            firstProblemField=myForm.elements[i];
          } // end if (!foundBlank)
        } // end if (myForm.elements[i].value=="" || myForm.elements[i].value=="-1")
      } // end if (myForm.elements[i]._required)
			else
			{ // if not (myForm.elements[i]._required)
				if (myForm.elements[i].value=="-1")
				{
					myForm.elements[i].value="";
				} // end if (myForm.elements[i].value=="-1")
			} // end if not (myForm.elements[i]._required)
    } // end if (myForm.elements[i]._validate)
  } // end looping thru all form elements  
  
  // if there are any blanks on the required fields, display an alert and return to the form
  if (!blankFields=="")
  {
		//alert ("The following fields are required: \n\n" + blankFields); // this will list the field names
		alert ("The highlighted fields are required.");
    setTimeout("firstProblemField.focus();",100); // the timeout is required; don't know why
    return;
  }
  
  // examine patterns on fields with patterns defined, whether required or not
  for (var i=0; i < myForm.elements.length; i++) // loop thru all the form elements
  {
    if (myForm.elements[i]._validate) // test elements with "validate" attribute defined and true
    {
      myForm.elements[i].style.backgroundColor=""; // get rid of the special style if already applied
      if (myForm.elements[i]._pattern && !myForm.elements[i]._pattern=="") // test elements with "pattern" attribute defined and not blank
      {
        switch (myForm.elements[i]._pattern)
        {
          case "int_0_to_999": // integer greater than zero
						if ((myForm.elements[i]._required && !regIntegerZeroTo999.test(myForm.elements[i].value)) || (!myForm.elements[i]._required && !regIntegerZeroTo999.test(myForm.elements[i].value) && !myForm.elements[i].value==""))
            {
              myForm.elements[i].style.backgroundColor=highlightColor;
              alert ('The highlighted field must be a whole number between 0 and 999.')
              problemField=myForm.elements[i];
              setTimeout("problemField.focus();",100); // the timeout is required; don't know why
              problemField.select();
              return;
            }
            break;
          case "email":
						if ((myForm.elements[i]._required && !regEmail.test(myForm.elements[i].value)) || (!myForm.elements[i]._required && !regEmail.test(myForm.elements[i].value) && !myForm.elements[i].value=="" && !myForm.elements[i].value==optionalString.toLowerCase()))
						{
              myForm.elements[i].style.backgroundColor=highlightColor;
              alert ('The highlighted field is not a valid email address.')
              problemField=myForm.elements[i];
              setTimeout("problemField.focus();",100); // the timeout is required; don't know why
              problemField.select();
              return;
            }
            break;
          case "postalcode":
						if ((myForm.elements[i]._required && !regPostalCode.test(myForm.elements[i].value)) || (!myForm.elements[i]._required && !regPostalCode.test(myForm.elements[i].value) && !myForm.elements[i].value==""))
            {
              myForm.elements[i].style.backgroundColor=highlightColor;
              alert ('The highlighted field is not a valid postal code.')
              problemField=myForm.elements[i];
              setTimeout("problemField.focus();",100); // the timeout is required; don't know why
              problemField.select();
              return;
            }
            break;
          case "phone":
            var stripped = myForm.elements[i].value.replace(/[\(\)\.\-\ ]/g, '');
						if ((myForm.elements[i]._required && isNaN(parseInt(stripped))) || (!myForm.elements[i]._required && isNaN(parseInt(stripped)) && !myForm.elements[i].value==""))
            {
              if (stripped != optionalString )
							{
								myForm.elements[i].style.backgroundColor=highlightColor;
								alert ('The highligted field is not a valid telephone number.')
								problemField=myForm.elements[i];
								setTimeout("problemField.focus();",100); // the timeout is required; don't know why
								problemField.select();
								return;
							}
            }
            break;
          case "date":
						if ((myForm.elements[i]._required && !regDate.test(myForm.elements[i].value)) || (!myForm.elements[i]._required && !regDate.test(myForm.elements[i].value) && !myForm.elements[i].value==""))
            {
              myForm.elements[i].style.backgroundColor=highlightColor;
              alert ('The highligted field is not a valid date (mm/dd/yyyy).')
              problemField=myForm.elements[i];
              setTimeout("problemField.focus();",100); // the timeout is required; don't know why
              problemField.select();
              return;
            }
            break;           
          default:
            alert ("Error -- look at switch statement");
            return;
            break;          
        }  // end switch
      } // end if (myForm.elements[i]._pattern)
    } // end if (myForm.elements[i]._validate)
  } // end looping thru all form elements
	
	var dateTimeToday = new Date; 
	var dateTimeDue = new Date(myForm.duedate.value + " " + myForm.duetime.value);
	var hoursDifference = (dateTimeDue - dateTimeToday)/3600000;
	// make sure due date and time have not already passed
	if (hoursDifference<=0)
	{
		myForm.duedate.style.backgroundColor=highlightColor;
		myForm.duetime.style.backgroundColor=highlightColor;
		alert ("The due date/time has already passed.  Please select another due date/time.")
		problemField=myForm.duedate;
		setTimeout("problemField.focus();",100); // the timeout is required; don't know why
		problemField.select();
		return;
	}
	// make sure the due date and time are within the allowable lead time
	if (hoursDifference<myForm.minLeadTimeHours.value && hoursDifference>=0)
	{
		myForm.duedate.style.backgroundColor=highlightColor;
		myForm.duetime.style.backgroundColor=highlightColor;
		alert ("The due date/time for this job is less than " + myForm.minLeadTimeHours.value + " hours from now. Please select another due time.")
		problemField=myForm.duedate;
		setTimeout("problemField.focus();",100); // the timeout is required; don't know why
		problemField.select();
		return;
	}
	
	// make sure combined qty of full and half size is greater than zero unless it's an archive job, but only if fields exist
	if (myForm.qtyFullSizeSets && myForm.qtyHalfSizeSets && myForm.archive)
	{
		if ((myForm.qtyFullSizeSets.value + myForm.qtyHalfSizeSets.value <= 0) && (!myForm.archive.checked))
		{
			myForm.qtyFullSizeSets.style.backgroundColor=highlightColor;
			myForm.qtyHalfSizeSets.style.backgroundColor=highlightColor;
			alert ("Unless the \"Archive\" option is selected, the total quantity must be greater than zero.\nPlease update the quantities, or select the \"Archive\" option.")
			problemField=myForm.qtyFullSizeSets;
			setTimeout("problemField.focus();",100); // the timeout is required; don't know why
			problemField.select();
			return;
		}
	}
	
	// if state and country fields exist, validate to make sure the combination is valid
	if (myForm.country && myForm.state)
	{
		if ((/USA/.test(myForm.country.value) && !regUSAStates.test(myForm.state.value)) || (/Canada/.test(myForm.country.value) && !regCanadianProvinces.test(myForm.state.value)))
		{
			myForm.state.style.backgroundColor=highlightColor;
			myForm.country.style.backgroundColor=highlightColor;
			alert ('The state and country pairing you have chosen is invalid.')
			problemField=myForm.state;
			setTimeout("problemField.focus();",100); // the timeout is required; don't know why
			//problemField.select(); // this statement was causing a javascript error; commented out 1/6/08
			return;
		}
		if ((/USA|Canada/.test(myForm.country.value)) && (myForm.state.value == "INTERNATIONAL"))
		{
			myForm.state.style.backgroundColor=highlightColor;
			myForm.country.style.backgroundColor=highlightColor;
			alert ('The state and country pairing you have chosen is invalid.')
			problemField=myForm.country;
			setTimeout("problemField.focus();",100); // the timeout is required; don't know why
			//problemField.select(); // this statement was causing a javascript error; commented out 1/6/08
			return;
		}
	}

  // everything is validated, time to submit the form
	// set the hidden form field value to true indicating that validation is complete
	myForm.formValidated.value = "true";
	clean(myForm); // remove the word Optional from the field values
	return;
}

// function that can be called by an onChange event in a state field to automatically change the country
function updateCountry(myForm) {
  for (var i = 0; i < myForm.state.length; i++)
  {
    if ((myForm.state.options[i].selected)&&(myForm.state.options[i].value != "INTERNATIONAL")) 
    {
      if (regCanadianProvinces.test(myForm.state.options[i].value))
      {
        myForm.country.selectedIndex = 2;
      }
      else
      {
        myForm.country.selectedIndex = 1;
      }
    }
  }
}

// function that can be called by an onChange event in a country field to automatically change the state
function updateState(myForm) {
  for (var i = 0; i < myForm.country.length; i++)
  {
    if ((myForm.country.options[i].selected)&&(!/USA|Canada/.test(myForm.country.options[i].value)))
    {
      myForm.state.selectedIndex = 1;
    }
  }
}

// function that can be called by onKeyUp and onKeyDown events in text areas to limit the input length
function maxlimit(field, maxlimit)
{
  if (field.value.length > maxlimit)
  {
    field.value = field.value.substring(0, maxlimit);
    alert("The " + field.name + " field will accept a maximum of " + maxlimit + " characters, and your entry has been truncated to fit.  Please verify the contents of this field before submitting.");
  }
}

function cleanTextArea(field)
{
	// reduce 2 spaces to 1 space
	field.value = field.value.replace(/ {2,}/g,' ');
	// IE replace space followed by CRLF with CRLF
	field.value = field.value.replace(/ \r\n/g, "\r\n");
	// FF replace space followed by LF with LF
	field.value = field.value.replace(/ \n/g, "\r\n");
	// replace three or more conseqcutive occurences of CRLF with 2 CRLF's
	field.value = field.value.replace(/(\r\n){3,}/g, "\r\n\r\n");
	//FF replace three or more conseqcutive occurences of LF with 2 LF's
	field.value = field.value.replace(/\n{3,}/g, "\n\n");
}

// onChange event handler for phone number fields
function formatPhone(field) {
  field.value = trim(field.value);
  var ov = field.value;
  var v = "";
  var x = -1;
  // is this phone number 'escaped' by a leading plus?
  if (0 < ov.length && '+' != ov.charAt(0)) { // format it
    // count number of digits
    var n = 0;
    if ('1' == ov.charAt(0)) {  // skip it
      ov = ov.substring(1, ov.length);
    }
    for (i = 0; i < ov.length; i++) {
      var ch = ov.charAt(i);
      // build up formatted number
      if (ch >= '0' && ch <= '9') {
        if (n == 0) v += "(";
        else if (n == 3) v += ") ";
        else if (n == 6) v += "-";
        v += ch;
        n++;
      }
      // check for extension type section;
      // are spaces, dots, dashes and parentheses the only valid non-digits in a phone number?
      if (! (ch >= '0' && ch <= '9') && ch != ' ' && ch != '-' && ch != '.' && ch != '(' && ch != ')') {
        x = i;
        break;
      }
    }
    // add the extension
    if (x >= 0) v += " " + ov.substring(x, ov.length);
    // if we recognize the number, then format it
    if (n == 10 && v.length <= 40) field.value = v;
  }
  return true;
}

// to remove leading and trailing spaces
function trim(st) {
	var len = st.length
	var begin = 0, end = len - 1;
	while (st.charAt(begin) == " " && begin < len) {
		begin++;
	}
	while (st.charAt(end) == " " && begin < end) {
		end--;
	}
	return st.substring(begin, end+1);
}

// to make a string lower case
function lowerCase(field)
{
	field.value=field.value.toLowerCase();
	return true;
}

function modifyOptionalElementAppearance(myForm) {
	for (var i=0; i < myForm.elements.length; i++) { // loop thru all the form elements
    if (typeof(myForm.elements[i]._required) !== "undefined" && myForm.elements[i]._required==false) {
			myForm.elements[i].style.backgroundColor=optionalBackgroundColor;
			myForm.elements[i].style.color=optionalFontColor;
			myForm.elements[i].style.fontStyle=optionalFontStyle;
			myForm.elements[i].fontSize=optionalFontSize;    
      if ((/^text/.test(myForm.elements[i].type))&&(myForm.elements[i].value=="")) {
        myForm.elements[i].value = optionalString;
        myForm.elements[i].defaultValue = optionalString;
      }
      if (/^select/.test(myForm.elements[i].type)) {
        optional = new Option(optionalString, "", true, true);
        myForm.elements[i].options[myForm.elements[i].length] = optional;
      }
    } //end if
  } // end for
}

function clean(myForm) {
// replace the OptionalStrings with nulls
	for (var i = 0; i < myForm.elements.length; i++) {
		if (typeof(myForm.elements[i]._required) !== "undefined" && myForm.elements[i]._required==false) {
			regOptionalString = new RegExp("^" + optionalString);
			if (regOptionalString.test(myForm.elements[i].value)) {
				myForm.elements[i].value = myForm.elements[i].value.replace(regOptionalString,'')
			}
		} //end if
	} //end for
}
