var ERRMSG_LESSTHAN ="Warning: value is expected to be less than "
var ERRMSG_GREATERTHAN = "Warning: value is expected to be greater than "
var ERRMSG_BETWEEN ="Warning: value expected to be between "
var ERRMSG_INVALID_INTEGER_SEARCH_EXPR =  "Invalid Integer search expression"
var ERRMSG_INVALID_REAL_SEARCH_EXPR = "Invalid format for Real Number Search Expression"
var ERRMSG_INVALID_OPERATOR_BEFORE_DATE="Invalid operator before date"
var ERRMSG_INVALID_DATE="Invalid Date (must be mm/dd/yy or mm/dd/yyyy)"
var ERRMSG_NONDATE_MISSING_FIELDS_MUST_BE_EMPTY="Non-date fields previously designated as missing values must remain empty."
var ERRMSG_CANNOT_BE_BLANK= "This value cannot be left blank."
var ERRMSG_MAX_CHARS = "The number of characters in this field cannot exceed this number: "
var ERRMSG_INVALID_INTEGER="Invalid format for Integer"
var ERRMSG_INVALID_REAL="Invalid format for Real Number"
var ERRMSG_PERCENTAGE= "When changing a value containing the percent symbol,  please enter a new number without the symbol but with a leading decimal point- e.g., to enter 25%, type in 0.25"
var ERRMSG_EARLIEST_DATE="Sorry, the earliest date you can enter is 1/1/1800."
var ERRMSG_NO_FUTURE_DATE="The value entered cannot be a Date in the future."
var ERRMSG_NO_END_EVENT="You cannot enter an end-of-event date if the start-of-event date is blank."
var ERRMSG_END_EVENT_MUST_BE_GREATER_THAN_START="End-of-event date-time must be greater than start-of-event date-time."
var ERRMSG_LESSTHAN_ABS =  "value should be less than "
var ERRMSG_GREATERTHAN_ABS =  "value should be greater than "
var ERRMSG_BETWEEN_ABS ="value should be  between "
function Validate (Datatype, decimals, MinVal, MaxVal, MinValWarn, MaxValWarn, NotNull, tRegExp, Custom_ErrorMsg, NoCheckFutureDates, IsSearchMode)
//this validates the contents of a textboxplus against a bunch of constraints - range checks, regular expressions, data type
// 10/24 - this function used to be in VBScript until we needed to add extra parameters to it, without having to break every
// previously generated form. javascript functions can take an arbitrary number of parameters. So this is simply a wrapper function
// that calls Validate_Core (the original function, renamed && modified to take extra parameters).
{ 
   if (arguments.length == 7 )
   { NoCheckFutureDates= false;
     Custom_ErrorMsg = "";
     tRegExp = "";
   }
  Validate_Core (Datatype, decimals, MinVal, MaxVal, MinValWarn, MaxValWarn, NotNull, tRegExp, Custom_ErrorMsg, NoCheckFutureDates,IsSearchMode);
}
// provides the VBA/VB6 function Nz within JavaScript
function Nz(Value, ValueifNull)
{ if (Value == null) 
 return  ValueifNull
else
return  Value;
}

var SkipFlag	;
var CurrentElem, CurVal, Bypass_On_focus;
var Invalid_Data; //as Boolean
var SavedColor;  //saves the background color of the current field, 8/20/99


// supposed to set the current field- unfortunately, does not seem to work in .NET forms.
function Set_Current()
{ if (Invalid_Data) return;
var  F = window.event.srcElement;
	 CurrentElem = F; 	CurVal = F.value
//	window.document.all("srcElem").value= F.name - only for CRFs
if (F.style.backgroundColor != "lightblue" )
	{SavedColor = F.style.backgroundColor;
	 F.style.backgroundColor="lightblue";
 }
}

// supposed to put up an error message unfortunately, the cursoe does not seem to stay in the same field. 
function Data_Error(SrcElem,ErrMsg)
{ 
SrcElem.value="";;
Invalid_Data=true;
alert ( ErrMsg);
SrcElem.focus();
}

//the next routine is similar to above, except that the SrcElem is (!blanked out
function Data_Error_DoNotBlank (SrcElem,ErrMsg)
{ SrcElem.focus(); //note - focus without the parens does not work
Invalid_Data=true;
alert ( ErrMsg);
}

function testRegExp ( RgXp,  InputDat)
{
//This function tests the string InputDat against the RegExp pattern RgXp.
//It returns true only if there is a single match, whose length is equal to the length of the input string
var Rg= new RegExp(RgXp);
var Mc = InputDat.match(Rg);
if (Mc == null) return false;
return (Mc[0].length == InputDat.length);
}

function IsNumeric(sText)
{  var ValidFirstChars = "+-0123456789.";
   var ValidChars = "0123456789.";
   var Char;
    Char = sText.charAt(0); 
  if (ValidFirstChars.indexOf(Char) == -1) 
         return  false;
   if (sText.length ==1 && (Char == "+" || Char == "-"))
       return  false;
   for (i = 1; i < sText.length; i++) 
      { 
      Char = sText.charAt(i); 
      if (ValidChars.indexOf(Char) == -1) 
         return  false;
      }
   return true;
   }
   
function round(number, rlength) {
var pw = Math.pow(10,rlength);
	var newNumber = Math.round(number * pw ) / pw;
	return newNumber;
}


function Validate_Contents_SearchMode(Text, Datatype)
    //this routine validates the contents of numeric or date fields
// to determine if they are valid for search patterns
    //the strategy is to use regular expressions
 {   var relOpSt = "(=|<>|>|>=|<|<=)?"
  var SrcElem = window.event.srcElement;;
    if (Text == "")  return true;
    switch (Datatype)
     { case "S" :
       case "T": 
      case "C" :
        return true; // no validation needed
      case "I" :
        if (! testRegExp(relOpSt + "[0-9]+", Text)) 
        { Data_Error(SrcElem,ERRMSG_INVALID_INTEGER_SEARCH_EXPR)
           return false;
         }
      case "R":
        if (!  testRegExp(relOpSt + "[0-9]+(\.[0-9]+)?", Text)) 
        { Data_Error(SrcElem, ERRMSG_INVALID_REAL_SEARCH_EXPR);
        return false;
        }
      case "D":
      {  var pos, dval ;
        dval = Text;
        pos = 0
        while (! (dval.charAt(pos) >= "0" && dval.charAt(pos) <= "9") )
          pos ++
        var datePart  = dval.substring(pos); 
        if ( (pos) > 0 ) { 
          var relop = dval.substring(0, pos);
          if (!testRegExp (relOpSt, relop))
           Data_Error(SrcElem, ERRMSG_INVALID_OPERATOR_BEFORE_DATE)
           return false;
         }
        if (! isValid_date (datePart)){
          Data_Error(SrcElem,ERRMSG_INVALID_DATE ) 
          return false;
        }
        }
    }
    return true;
}

function Validate_Core (Datatype, decimals, MinVal, MaxVal, MinValWarn, MaxValWarn, NotNull, 
   vRegExp, Custom_ErrorMsg, NoCheckFutureDates,IsSearchMode)
{
var MAXSTRLEN = 255;
var Value, SrcElem, tag, month, datearr, cmonth, pos;
var NullMinVal, NullMaxVal, NullMaxWarn, NullMinWarn; //all Booleans
//prevents this script from being fired after a Save && Resume button has been clicked
//"\n" = chr(13) + chr(10)
 SrcElem = window.event.srcElement;
Invalid_Data=false; 
//added to accomodate KM code 3/2 escapepressed
if (SkipFlag) {
	SkipFlag=false;
	SrcElem.style.backgroundColor=SavedColor; 
	return;
}
if (Datatype != "D" && SavedColor == "gold" && SrcElem.value != "") {
	Data_Error (SrcElem,ERRMSG_NONDATE_MISSING_FIELDS_MUST_BE_EMPTY);
	return;
}

var DirtyBitField = window.document.all("_DirtyBit"); //so we don't need to insert this hidden field in every page
if (DirtyBitField != null) window.document.all("_DirtyBit").value= "1";
Value = Nz(SrcElem.value,"");
 var SrcName = SrcElem.name;
if ( Value == ""  && NotNull == true) {
  if ( SrcName.indexOf("_EE_") ==  -1 && SrcName.indexOf ("_ES_")== -1) { 
        //note - the LIKE operator does not exist in VBscript
	      	Data_Error (SrcElem, ERRMSG_CANNOT_BE_BLANK)
	       	return;
       //note - blank date errors are caught later in any case
	   } //srcName
} // value == ""

if (! Invalid_Data && Value==CurVal) { //no change in the contents of the field
	  SrcElem.style.backgroundColor=SavedColor; 
	  return;
}
if (Value=="") {
  SrcElem.style.backgroundColor=SavedColor;
  Invalid_Data=false;
  //Call Change(srcElem)
  return;
}  // value == ""
if (IsSearchMode) return Validate_Contents_SearchMode(Value, Datatype)
NullMinVal = (MinVal == null); 
NullMaxVal = (MaxVal == null);
NullMaxWarn = (MaxValWarn  == null); 
NullMinWarn = (MinValWarn == null);
if (Datatype == "C"  || Datatype == "T") return;  //C is used for choice sets, instance labels etc. which don//t require range validation
	switch (Datatype) {
	 case "S" : //added 9/19/02
	    if (Value.length > MAXSTRLEN) {
			     Data_Error (SrcElem, ERRMSG_MAX_CHARS + MAXSTRLEN);
			    return; 
	    };
	    if (Value.indexOf ( "\n") != -1)  {			SrcElem.value = Value.replace ("\n"," ")	    };
	    break;
	    // case S
	 case "I": 
	 	    if (IsNumeric(Value) ) {
	        Value = parseInt(Value,10);
	        SrcElem.value = Value;
	       }
	    else {
	        Data_Error (SrcElem, ERRMSG_INVALID_INTEGER); return;
	      } 
	    break;
	    // case I
	 case "R":
	    if (IsNumeric(Value) ) {
	        if (decimals == null) decimals = 2;
	        SrcElem.value = round(Value, decimals);
	        Value = parseFloat(Value); // will this have the same stupid conversion bug?
	       } 
	    else if (Value.indexOf ("%") != -1) {
	        Data_Error (SrcElem, ERRMSG_PERCENTAGE)
	       return; 
	       } 
	    else {
	         Data_Error (SrcElem, ERRMSG_INVALID_REAL )
	         return;
	       }
	    break;
	    //case R
	 case "D" : 
		  var lenDt, Increm, IncremSt;
		  lenDt = Value.length;
		  switch (Value.substring(0,1)) {
			  case "T": case "t" :
				  Increm = 0;
				  if (lenDt > 1) { 
					  Incremst = Value.substring(1) //this should be of the form +n || -n
					  if (IsNumeric(Incremst)) { 
					  Increm = parseInt(Incremst,10)	;
				  Value = DaysAdd(Increm) //this is short format
				    SrcElem.value = Value;
			     }	
			  } // lendt > 1
			  break;	//case T, t
			  case "N": 	  case "n":
				  Value = Today();
				  SrcElem.value = Value;
			  } // switch	
			var valDate = VBparseDate(Value);
	 
    if (valDate == null) {
       Data_Error (SrcElem, ERRMSG_INVALID_DATE)
       return;
       }
      else
        SrcElem.value = valDate;
    Value = new Date(valDate);
   if ( Value < new Date(1800, 1, 1) ) {
       Data_Error (SrcElem,  ERRMSG_EARLIEST_DATE);
	      return;
     }
  var Now = new Date();
   if (!NoCheckFutureDates && Value.getTime() >Now.getTime()) { 
      Data_Error (SrcElem,  ERRMSG_NO_FUTURE_DATE)
    	return;
   } // future dates
	    //7/17/02- special tests for an end-of-event date-
	 if (SrcName.indexOf( "_EE_") != -1) {
			 var StartEventFieldName, StartEventFieldValue;
			 StartEventFieldName = replace(SrcElem.name, "_EE_", "_ES_")
					StartEventFieldValue = window.document.all(StartEventFieldName).Value
			//two possibilities - if end-of-event is (!blank && start-of-event is blank { Error
			//if end-of-event date (!greater than the start of event date, ehen error
			if ( StartEventFieldValue == "") {
				Data_Error (SrcElem, ERRMSG_NO_END_EVENT)
				return;
			}
			StartEventFieldValue = new Date(VBparseDate(StartEventFieldValue));
			if (StartEventFieldValue > Value) {
				Data_Error (SrcElem, ERRMSG_END_EVENT_MUST_BE_GREATER_THAN_START)
				return;
			}
	} //special tests for end-of-event
} //switch
// now test for range errors	
//	 SrcElem.value = Value;
   	//handle the range error logic
	if (NullMinVal && NullMaxVal && NullMaxWarn && NullMinWarn && !(Datatype == "S" && vRegExp != "") ) {
        SrcElem.style.backgroundColor=SavedColor;
        Invalid_Data=false;
  } 

  if (Invalid_Data) return;
  var  MinValInternal, MaxValInternal;
  // these variables were introduced to make the output more reasonable
	if (! (NullMinVal && NullMaxVal)) { // test for absolute range errors 	
  if (Datatype == "D" ){
     if (!NullMinVal)    MinValInternal = CheckDate(MinVal);
      if (!NullMaxVal) MaxValInternal = CheckDate(MaxVal) ; 
      if (MaxValInternal==null || MinValInternal == null) return;
     }  // date
  else if ( Datatype == "I" || Datatype =="R") {
     if (!NullMinVal) MinValInternal = parseFloat(MinVal) ; 
     if (!NullMaxVal)  MaxValInternal = parseFloat(MaxVal) ; 
  }	 // numeric
 if (NullMinVal && (Value > MaxValInternal)) {
	  Data_Error (SrcElem, ERRMSG_LESSTHAN_ABS + MaxVal); 
	  return;
    } //lower bound only
 else if (NullMaxVal  && (Value < MinValInternal)) {
	    Data_Error (SrcElem, ERRMSG_GREATERTHAN_ABS + MinVal)
	    return;
    } //upper bound only
 else
    if (Value < MinValInternal || Value > MaxValInternal) {
	    Data_Error (SrcElem, ERRMSG_BETWEEN_ABS + MinVal + "  - " + MaxVal)
	    return;
    } // both bounds violated
 } // absolute range error check
	// now handle the warning logic- do (!exit, pass to Change anyway
	if (!(NullMaxWarn && NullMinWarn) ){
 if (Datatype =="D") {
   if (!NullMinWarn)  MinValInternal = CheckDate(MinValWarn);
    if (!NullMaxWarn)  MaxValInternal = CheckDate(MaxValWarn) ;
    if (MinValInternal == null || MaxValWarn == null) return;
  } 
else if (Datatype == "I" || Datatype =="R" ) {
   if (!NullMinWarn)  MinValInternal = parseFloat(MinValWarn);
    if (!NullMaxWarn) MaxValInternal = parseFloat(MaxValWarn) ;
}		
	 if (NullMinWarn && (Value > MaxValInternal) ) 
	 alert (ERRMSG_LESSTHAN + MaxValWarn);
	   // upper bound warning only
	 else if (NullMaxWarn  && (Value < MinValInternal) ) 
	   alert ( ERRMSG_GREATERTHAN + MinValWarn); 
	    // lower bound warning only
	 else if ( Value < MinValInternal || Value > MaxValInternal) 
	    alert ( ERRMSG_BETWEEN  + MinValWarn + " - " + MaxValWarn )
	   // both warning bounds
	} // end of warning logic

// regular expression check
if (vRegExp != "") {
  //perform regular Expression Checks- make sure that the entire string matches the RegExp
  if (!testRegExp (vRegExp, Value)) Data_Error_DoNotBlank  (SrcElem, Custom_ErrorMsg);
} // regular expression check 
SrcElem.style.backgroundColor=SavedColor;
Invalid_Data=false;

} // end function

function CheckDate(dt)
{ var tDate = VBparseDate(dt) ; 
     if (tDate == null) 
       {alert(dt + " " + ERRMSG_INVALID_DATE ); 
         return null;
       }
      else
      return  new Date(dt);
}