/* formValidationDotNet.js */
/* Written from use with A2 Generic Controls only */
// How to call validation functions...
// validate(nStr, ElementName, ElementLabel)

// Where nStr is a string containing a number referring to the type of validation (Listed below)
// Where ElementName is the name of the form input element
// Where Label is the name used to identify the element to the user.

// Validation Codes.

// A negative validation code indicates a mandatory form element.
//    1  = GENERAL (All characters allowed)
//    2  = ALPHA-NUMERIC (Only Characters in the Charset and whitespace are permitted)
//    3  = ALPHA ONLY (Upper or lowercase)
//    4  = NUMBER (integer with commas)
//    5  = NUMBER (real with commas)
//    6_min_max = NUMBER (range between min and max)
//    7  = EMAIL (a@b.c)
//    8  = ONLY ALPHA-NUMERIC (Leters and numbers only - no whitespace or symbols)
//    9  = DATE (Any UTC date, of format: YYYY-MM-DDThh:mm:ss.sssZ, or normal date of format: DD/MM/YYYY)
//    10 = TIME (TIMES of format: HH, or,HH:MM, or, HH:MM:SS )

// Special Validation Codes.

//    50 = Compares 2 strings (Used with password when confirm = true)
//    51 = Compares a string with an array of strings. (The array must be the same name as the textbox)
//    60 = DATE-TIME (ONLY DD/MM/YYYY:HH:MM:SS, SQL uses date-times of this format but uses whitespace at subString(10,11))

// VARIABLE DECLARATIONS
var specialchars = "";
var basicpunc    = ".,?£$()-!+=#@_&^~*{}[];:|\/";
var numbers      = "0123456789";
var numbersonly  = "0123456789";
var alpha        = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ";
var whitespace = " \t\n\r";
var SpecialNameCharacters = "'-";


// This function is designed to check, and maybe change, the format of a submitted date
// you can have a standard ISO or UTC date (YYYY-MM-DDThh:mm:ss.sssZ), or all the possible permutations
// of a character from 'basicPunc' as the delimiter, with the date in british format.
function isDate(date) {
    var allValid;
    var delimitType = "";
    var dArr = new Array();
    if ((date.length == 25) && (date.substring(24,25) == "Z") && (date.substring(10,11) == "T")) {
      allValid = true;
    } else if ((date.length == 9) || (date.length == 10) || (date.length == 8)) {
      for(var aa=0;aa<basicpunc.length;aa++) {
         var ab=(aa+1);
         if(date.indexOf(basicpunc.substring(aa,ab))!= Number(-1)) {
         delimitType = basicpunc.substring(aa,ab);
         }
      }
      if (delimitType != "") {
         dArr = date.split(delimitType);
         if ((Number(dArr[0])<= 31) && (Number(dArr[1])<= 12) && (Number(dArr[2])<=9999) && (Number(dArr[0])> 0) && (Number(dArr[1])> 0) && (Number(dArr[2] > 0)))  {
            allValid = true;
         } else {
            allValid = false;
         }
      } else {
         allValid = false;
      }
    }
return allValid;
}
// Times can be passed as HH, HH:MM, or HH:MM:SS, the delimiter MUST be a colon.
function isTime(time) {
   if(time.indexOf(":") != Number(-1)) {
      var allValid=false;
      if((time.length==2) && (isFinite(Number(time.subString(0,2)))) && ((Number(time.subString(0,2))) < 24) && ((Number(time.subString(0,2))) >= 0)) {
         allValid=true;
      } else if((time.length==5) && (isFinite(Number(time.subString(0,2)))) && (isFinite(Number(time.subString(3,5)))) && ((Number(time.subString(0,2))) < 24) && ((Number(time.subString(0,2))) >= 0) && ((Number(time.subString(3,5))) < 60) && ((Number(time.subString(3,5))) >= 0)) {
         allValid=true;
      } else if((time.length==8) && (isFinite(Number(time.subString(0,2)))) && (isFinite(Number(time.subString(3,5)))) && (isFinite(Number(time.subString(6,8)))) && ((Number(time.subString(0,2))) < 24) && ((Number(time.subString(0,2))) >= 0) && ((Number(time.subString(3,5))) < 60) && ((Number(time.subString(3,5))) >= 0) && ((Number(time.subString(6,8))) < 60) && ((Number(time.subString(6,8))) >= 0)) {
         allValid=true;
      }
   }
return allValid;
}
// Abuses the isDate and isTime functions because SQL server doesn't use any 'standard' delimiters
// to split the date from the time.  It's lovely really.
function isDateTime(dateTime) {
   var allValid = false;
   if(dateTime.length==19) {
      var strDate = dateTime.subSting(0,10);
      var strTime = dateTime.subString(11,19);
      if ((isDate(strDate)) && (isTime(strTime))) {
         allValid =  true;
      }
   }
return allValid;
}
// isEmpty returns true if TestString is not empty or whitespace.
function isEmpty(TestString) {
	if ((TestString == null) || (TestString.length == 0)) return true
	else {
		for (i = 0; i < TestString.length; i++) {
		    // Check that current character isn't whitespace.
		    var c = TestString.charAt(i);
		    if (whitespace.indexOf(c) == -1) return false;
		}
	}
	return true;
}
// fullOf returns true if every character is 'car'
function fullOf(TestString, car){
   for (i = 0; i < TestString.length; i++)
      if(TestString.charAt(i) != car)
         return false;
   return true;
}
// isValid returns true if all characters in TestString are also in ValidChars
function isValid(TestString, ValidChars) {
	for (i = 0; i < TestString.length; i++) {
		var c = TestString.charAt(i);
		if (ValidChars.indexOf(c) == -1) return false;
	}
	return true;
}
// isValid returns true if all characters in TestString are also in ValidChars
function isValidDomain(TestString, ValidChars) {
    var blnHasFullStop = false;
    
	for (i = 0; i < TestString.length; i++) {
		var c = TestString.charAt(i);
		if (ValidChars.indexOf(c) == -1) return false;
		if (c == ".") blnHasFullStop = true;
    }

    return blnHasFullStop;
}

function isInRange(testValue, minValue, maxValue) {
	if(testValue == NaN) return false;
	if((testValue >= minValue) && (testValue <= maxValue)) return true;
	else return false;
}
function isEmail(TestString){
	i = 1;
    StringLength = TestString.length;
    while ((i < StringLength) && (TestString.charAt(i) != "@")){ i++ }
    if ((i >= StringLength) || (TestString.charAt(i) != "@")) return false;
    else i += 2;
    while ((i < StringLength) && (TestString.charAt(i) != ".")){ i++ }
    if ((i >= StringLength - 1) || (TestString.charAt(i) != ".")) return false;
    else return true;
  }

  function isPcodeNum(TestString, ValidChars) {
    for (i = 0; i < TestString.length; i++) {
      var c = TestString.charAt(i);
      if (ValidChars.indexOf(c) == -1) return false;
    }
    if (TestString.length != 5) return false;
    return true;
  }

// This function is used to show 'non-mandatory' validation errors
function displaySubErrorMsg() {
   // alert(SubErrorMsg)
	ProblemField = document.forms[0].elements[SubErrorMsg[0]]
	ProblemField.className = "redoutline";
	if(ProblemField.type != "hidden")
	   {
	   ProblemField.select();
	   ProblemField.focus();
	   }
    //alert("The value in \"" + SubErrorMsg[1] + "\" field is invalid because\n" + SubErrorMsg[2]);
    fcnShowPopupBySize2('ifPopup', 330, 150, '/Public/Alert.aspx?PopupName=ifPopup&Msg=The value in \'' + SubErrorMsg[1] + '\' field is invalid because[br]' + SubErrorMsg[2]);
}
// ----------------------------------------- VALIDATE STARTS HERE -----------------
function validate(CodeInput, ElementName, ElementLabel) {
  //alert("ElementName=" + ElementName);
  //alert("CodeInput=" + CodeInput);

	CodeNumber = parseInt(CodeInput);
	InputField = document.forms[0].elements[ElementName];
	if(InputField.tagName == "TEXTAREA") InputField.className = "inputbox1 PSelectScroll";
	else InputField.className = "inputbox1";
	if (isNaN(CodeNumber)) {
		alert("formValidation Error:\n\""+ CodeInput +"\" is not a valid code number");
		return false;
		}
// ------------- This bit checks all required fields are completed --------------------------
	if(CodeNumber < 0) {
		CodeNumber = Math.abs(CodeNumber)
		if(isEmpty(InputField.value)) {
			ErrorMsg = "Please fill in all required fields.";
			InputField.className = "redoutline";
			return false;
			}
		}
// ------------- This bit checks that inputs are correct to their validation type ----------

if ((!isEmpty(InputField.value)) && (ErrorMsg == "") && (SubErrorMsg[2] == "")) {
  //alert(ElementName);
  //alert("codenumber=" + CodeNumber);
		switch(CodeNumber)
			{
			case 0 : 
			         break;
			case 1 : 
			         break;
			case 2 : if(!isValid(InputField.value, alpha + numbers + whitespace + basicpunc)) SubErrorMsg[2] = "this field cannot contain special characters.";
			         break;
			case 3 : if(!isValid(InputField.value, alpha)) SubErrorMsg[2] = "this field can only contain alphabetical characters.";
			         break;
			case 4 : if(!isValid(InputField.value, numbers + ",") || fullOf(InputField.value,",")) SubErrorMsg[2] = "this field must be an integer.";
			         break;
			case 5 : if(!isValid(InputField.value, numbers + ",.-") || !(InputField.value.indexOf(".") == InputField.value.lastIndexOf(".")) || fullOf(InputField.value,",")) SubErrorMsg[2] = "this field must be a number.";
			         break;
			case 6 : CodeInput = CodeInput.split("_");
			         minValue = parseFloat(CodeInput[1]);
			         maxValue = parseFloat(CodeInput[2]);
			         if(!isInRange(parseFloat(InputField.value), minValue, maxValue)) SubErrorMsg[2] = "this field must be a number between "+ minValue +" and "+ maxValue +".";
			         break;
			case 7 : if(!isEmail(InputField.value)) SubErrorMsg[2] = "this field must be a valid e-mail address."
			         break;
			case 8 : if(!isValid(InputField.value, alpha + numbers)) SubErrorMsg[2] = "this field must not contain whitespace or symbols.";
			         break;
			case 9 : if(!isDate(InputField.value)) SubErrorMsg[2] = "this field must be a valid date, ie: 02/04/1983.";
			         break;
			case 10 : if(!isDate(InputField.value)) SubErrorMsg[2] = "this field must be a valid 24 hour time, ie: 17:30:00.";
			         break;
			case 11: if (!isValid(InputField.value, numbersonly)) SubErrorMsg[2] = "this field must contain numbers only. (no spaces!)";
			         break;
			case 12: if (!isValid(InputField.value, alpha + whitespace)) SubErrorMsg[2] = "this field can only contain alphabetical characters.";
			         break;
			case 13: if (!isValid(InputField.value, alpha + SpecialNameCharacters + whitespace)) SubErrorMsg[2] = "this field can only contain characters used within a name.";
			         break;
			case 14: if (!isPcodeNum(InputField.value, numbersonly)) SubErrorMsg[2] = "this field must contain 5 numeric characters only.";
			         break;
			case 15: if (!isZipCode(InputField.value, numbersonly)) SubErrorMsg[2] = "this field must contain either 5 numeric characters only\nor 5 numeric, a hyphen and 4 numeric characters.";
			         break;
			case 16: if (!isValid(InputField.value, numbersonly + ".")) SubErrorMsg[2] = "this field must contain a currency value only.";
			         break;
			case 17: if (!isValidDomain(InputField.value, alpha + numbers + ".")) SubErrorMsg[2] = "this field must be a valid domain name.";
			         break;
                     
			case 50 : if(InputField.value != document.forms[0].elements["Confirm" + ElementName].value) {
			            SubErrorMsg[2] = "this field and Confirm "+ ElementLabel +" are not the same value.";
			            document.forms[0].elements["Confirm" + ElementName].className = "redoutline";
			          }
			          break;
			case 51 : CheckArray = eval(ElementName);
			          for(GFcount=0; GFcount < CheckArray.length; GFcount++)
			             {
			             if(InputField.value.toLowerCase() == CheckArray[GFcount].toLowerCase())
			                {
			                SubErrorMsg[2] = InputField.value + " already exists in the database.";
			                break;
			                }
			             }
			          break;
			case 60 : if(!isDateTime(InputField.value)) SubErrorMsg[2] = "this field must be a valid date-time\nie: 02/04/1983:17:30:00.";
			         break;
			 }
            
		if(SubErrorMsg[2] != "") {
			SubErrorMsg[0] = ElementName;
			SubErrorMsg[1] = ElementLabel;
			}
		}
	else return false;
}
//-------------In case needing to validate with a different form number------------
//----------------------------- VALIDATE STARTS HERE ------------------------------
function validateform(CodeInput, ElementName, ElementLabel, formno) {
	CodeNumber = parseInt(CodeInput);
	InputField = document.forms[formno].elements[ElementName];
	if(InputField.tagName == "TEXTAREA") InputField.className = "inputbox1 PSelectScroll";
	else InputField.className = "inputbox1";
	if (isNaN(CodeNumber)) {
		alert("formValidation Error:\n\""+ CodeInput +"\" is not a valid code number");
		return false;
		}
// ------------- This bit checks all required fields are completed --------------------------
	if(CodeNumber < 0) {
		CodeNumber = Math.abs(CodeNumber)
		if(isEmpty(InputField.value)) {
			ErrorMsg = "Please fill in all required fields.";
			InputField.className = "redoutline";
			return false;
			}
		}
// ------------- This bit checks that inputs are correct to their validation type ----------
	if((!isEmpty(InputField.value)) && (ErrorMsg == "") && (SubErrorMsg[2] == "")) {
		switch(CodeNumber)
			{
			case 0 : 
			         break;
			case 1 : 
			         break;
			case 2 : if(!isValid(InputField.value, alpha + numbers + whitespace + basicpunc)) SubErrorMsg[2] = "this field cannot contain special characters.";
			         break;
			case 3 : if(!isValid(InputField.value, alpha)) SubErrorMsg[2] = "this field can only contain alphabetical characters.";
			         break;
			case 4 : if(!isValid(InputField.value, numbers + ",") || fullOf(InputField.value,",")) SubErrorMsg[2] = "this field must be an integer.";
			         break;
			case 5 : if(!isValid(InputField.value, numbers + ",.-") || !(InputField.value.indexOf(".") == InputField.value.lastIndexOf(".")) || fullOf(InputField.value,",")) SubErrorMsg[2] = "this field must be a number.";
			         break;
			case 6 : CodeInput = CodeInput.split("_");
			         minValue = parseFloat(CodeInput[1]);
			         maxValue = parseFloat(CodeInput[2]);
			         if(!isInRange(parseFloat(InputField.value), minValue, maxValue)) SubErrorMsg[2] = "this field must be a number between "+ minValue +" and "+ maxValue +".";
			         break;
			case 7 : if(!isEmail(InputField.value)) SubErrorMsg[2] = "this field must be a valid e-mail address."
			         break;
			case 8 : if(!isValid(InputField.value, alpha + numbers)) SubErrorMsg[2] = "this field must not contain whitespace or symbols.";
			         break;
			case 9 : if(!isDate(InputField.value)) SubErrorMsg[2] = "this field must be a valid date, ie: 02/04/1983.";
			         break;
			case 10 : if(!isDate(InputField.value)) SubErrorMsg[2] = "this field must be a valid 24 hour time, ie: 17:30:00.";
			         break;
			case 50 : if(InputField.value != document.forms[0].elements["Confirm" + ElementName].value) {
			            SubErrorMsg[2] = "this field and Confirm "+ ElementLabel +" are not the same value.";
			            document.forms[0].elements["Confirm" + ElementName].className = "redoutline";
			          }
			          break;
			case 51 : CheckArray = eval(ElementName);
			          for(GFcount=0; GFcount < CheckArray.length; GFcount++)
			             {
			             if(InputField.value.toLowerCase() == CheckArray[GFcount].toLowerCase())
			                {
			                SubErrorMsg[2] = InputField.value + " already exists in the database.";
			                break;
			                }
			             }
			          break;
			case 60 : if(!isDateTime(InputField.value)) SubErrorMsg[2] = "this field must be a valid date-time\nie: 02/04/1983:17:30:00.";
			         break;
			}
		if(SubErrorMsg[2] != "") {
			SubErrorMsg[0] = ElementName;
			SubErrorMsg[1] = ElementLabel;
			}
		}
	else return false;
}
//--------------------------
function isFormValid() {

if ((ErrorMsg == "") && (SubErrorMsg[0] == ""))	return true;
else {
	if(ErrorMsg == "") displaySubErrorMsg();
	else fcnShowPopupBySize2('ifPopup', 330, 150, '/Public/Alert.aspx?PopupName=ifPopup&Msg=' + ErrorMsg);
	return false;
	}
}
