String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function() {
  return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function() {
  return this.replace(/\s+$/,"");
}

var formValidator = new FormValidator();
function FormValidator(){
	var self = this;
	this.Validators = new Object();
	this.validate = function(obj){
		var returnVal = true;
		if(typeof(self.Validators[obj.id]) !== 'undefined')
			for(var i = 0; i < self.Validators[obj.id].length; i++){
				if(!self.Validators[obj.id][i].validate(obj))
					return false;
			}
		try{
			returnVal = eval(getValidateFunction(obj.id));
		} catch(e){}
		return returnVal;
	};
	this.addValidator = function(formID,obj) {
		if(typeof(self.Validators[formID]) === 'undefined'){
			self.Validators[formID] = new Array();
		}
		self.Validators[formID][self.Validators[formID].length] = obj;
	};
	function getValidateFunction(id){
		var arr = id.split(':');
		return arr[arr.length - 1] + "_Validate('" + id + "')";
	}
}
function PasswordValidator(fieldID, errorMsg, focus) { 
 var self = this;
 this.fieldID = fieldID;
 this.errorMsg = errorMsg;
 this.validate = function(obj){
   var returnValue = true;
   if(obj[self.fieldID].value.length > 0) {
     var lcPat = new RegExp(PasswordValidator.LOWER_CASE);
     var ucPat = new RegExp(PasswordValidator.UPPER_CASE);
     var nPat = new RegExp(PasswordValidator.NUMERIC);
     var naPat = new RegExp(PasswordValidator.SPECIAL_CHAR);               
     
     var passed = 0;
     if ( obj[self.fieldID].value.match( lcPat ) )
      passed++;
     if ( obj[self.fieldID].value.match( ucPat ) )
      passed++;
     if ( obj[self.fieldID].value.match( nPat ) )
      passed++;
     if ( obj[self.fieldID].value.match( naPat ) )
      passed++;
     
     returnValue = passed >= 3 && obj[self.fieldID].value.trim( ).length >= 8;
     if(!returnValue){
       window.alert(self.errorMsg);
       if(focus){
         obj[self.fieldID].focus();
       }
     }
   }
   return returnValue;
 };
}
PasswordValidator.SPECIAL_CHAR = '^.*[:"\'\\{}\\[\\]\\<\\>\\(\\)\\.,/\\\\\\?\\|~`!@#\\$%\\^&\\*_\\+-=].*$';
PasswordValidator.UPPER_CASE = '^.*[A-Z].*$';
PasswordValidator.LOWER_CASE = '^.*[a-z].*$';
PasswordValidator.NUMERIC = '^.*\\d.*$';


function SSNValidator(fieldID, errorMsg, focus, isMultiField) {
  var self = this;
  var REG = "^[0-9]{3}-[0-9]{2}-[0-9]{4}$";
  this.fieldID = fieldID;
  this.errorMsg = errorMsg;
  this.validate = function (obj) {
    var returnValue = true;
    if (isMultiField) {
      if (obj[self.fieldID + "_ssn1"].value.length > 0 || obj[self.fieldID + "_ssn2"].value.length || obj[self.fieldID + "_ssn3"].value.length) {
        var reg = new RegExp(REG);
        var val = obj[self.fieldID + "_ssn1"].value + "-" + obj[self.fieldID + "_ssn2"].value + "-" + obj[self.fieldID + "_ssn3"].value;
        returnValue = val.match(reg);
        if (!returnValue) {
          alert(self.errorMsg);
          if (focus) {
            obj[self.fieldID + "_ssn1"].focus();
          }
        }
      }
    } else {
      if (obj[self.fieldID].value.length > 0) {
        var reg = new RegExp(REG);
        returnValue = obj[self.fieldID].value.match(reg);
        if (!returnValue) {
          window.alert(self.errorMsg);
          if (focus) {
            obj[self.fieldID].focus();
          }
        }
      }
    }
    return returnValue;
  };
}


function DateValidator(fieldID, type, errorMsg, focus){ 
 var self = this;
 var REG = new Array();
 REG[0] = '^[0-1]?[0-9]?[-/\\.][0-3]?[0-9]?[-/\\.][1-9][0-9]{3}$';
REG[1] = '^[A-Z][a-z]{2} [A-Z][a-z]{2} [0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]{3} [1-9][0-9]{3}$';
REG[2] = '^[1-9][0-9]{13}$';
REG[3] = '^[1-9][0-9]{7}$';

 this.fieldID = fieldID;
 this.type = type;
 this.errorMsg = errorMsg;
 this.validate = function(obj){
   var returnValue = true;
   if(obj[self.fieldID].value.length > 0) {
     var reg = new RegExp(REG[self.type]);
     returnValue = obj[self.fieldID].value.match(reg);
     if(!returnValue){
       window.alert(self.errorMsg);
       if(focus){
         obj[self.fieldID].focus();
       }
     }
   }
   return returnValue;
 };
}
DateValidator.SHORT_DATE_FORMAT = 0;
DateValidator.DATE_TIME_FORMAT = 1;
DateValidator.ANSI_DATE_TIME_FORMAT = 2;
DateValidator.ANSI_DATE_FORMAT = 3;


function ZipCodeValidator(fieldID, errorMsg, focus, isMultiField) {
  var self = this;
  var REG = "^[0-9]{5}(-[0-9]{4})?$";
  this.fieldID = fieldID;
  this.errorMsg = errorMsg;
  this.isMultiField = isMultiField;
  this.validate = function (obj) {
    var returnValue = true;
    if(self.isMultiField){
      if(obj[self.fieldID + '_zip1'].value.length > 0 || obj[self.fieldID + '_zip2'].value.length > 0) {
        var reg = new RegExp(REG);
        var val = obj[self.fieldID + '_zip1'].value + ((obj[self.fieldID + '_zip2'].value.length > 0)? '-' + obj[self.fieldID + '_zip2'].value: '');
        returnValue = val.match(reg);
        if(!returnValue){
          window.alert(self.errorMsg);
          if(focus){
            obj[self.fieldID + '_zip1'].focus();
          }
        }
      }    
    }else{    
      if (obj[self.fieldID].value.length > 0) {
        var reg = new RegExp(REG);
        returnValue = obj[self.fieldID].value.match(reg);
        if (!returnValue) {
          window.alert(self.errorMsg);
          if (focus) {
            obj[self.fieldID].focus();
          }
        }
      }
    }
    return returnValue;
  };
}


function RequiredValidator(fieldID, errorMsg, focus) {
  var self = this;
  var REG = "^[: :]+$";
  this.fieldID = fieldID;
  this.errorMsg = errorMsg;
  this.validate = function (obj) {
    var reg = new RegExp(REG);
    var returnValue = true;
    var selectItems = null;
    var isCB = false;
    if (typeof (obj[self.fieldID].value) == "undefined") {
      selectItems = document.getElementsByName(self.fieldID);
      returnValue = false;
      for (var i = 0; i < selectItems.length; i++) {
        if (selectItems[i].checked) {
          returnValue = true;
        }
      }
    } else {
      if (obj[self.fieldID].tagName == "INPUT" && obj[self.fieldID].type.toLowerCase() == "checkbox") {
        returnValue = obj[self.fieldID].checked;
      } else {
        if(obj[self.fieldID].previousSibling != null 
        && obj[self.fieldID].previousSibling.tagName == "INPUT"
        && obj[self.fieldID].previousSibling.type.toLowerCase() == "checkbox"){
          returnValue = (obj[self.fieldID].value === 'false')? false : true;
          isCB = true;
        } else {
          returnValue = !obj[self.fieldID].value.match(reg) && obj[self.fieldID].value.length > 0;
        }
      }
    }
    if (!returnValue) {
      window.alert(self.errorMsg);
      if (focus && selectItems !== null) {
        selectItems[0].focus();
      } else {
       	if(isCB){
       	  obj[self.fieldID].previousSibling.focus();
       	} else {
       	  obj[self.fieldID].focus();
        }
      }
    }
    return returnValue;
  };
}

function EmailValidator(fieldID, errorMsg, focus) { 
 var self = this;
 var REG = '^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$';
 this.fieldID = fieldID;
 this.errorMsg = errorMsg;
 this.validate = function(obj){
   var returnValue = true;
   if(obj[self.fieldID].value.length > 0) {
     var reg = new RegExp(REG);
     returnValue = obj[self.fieldID].value.match(reg);
     if(!returnValue){
       window.alert(self.errorMsg);
       if(focus){
         obj[self.fieldID].focus();
       }
     }
   }
   return returnValue;
 };
}

function LengthValidator(fieldID, maximum, minimum, errorMsg, focus){ 
 var self = this;
 this.fieldID = fieldID;
 this.errorMsg = errorMsg;
 this.maximum = maximum;
 this.minimum = minimum;
 this.validate = function(obj){
   var returnValue = true;
   if(self.maximum != -1 && obj[self.fieldID].value.length > self.maximum){ 
     returnValue = false;
   }
   if(self.minimum != -1 && obj[self.fieldID].value.length != 0 && obj[self.fieldID].value.length < self.minimum){ 
     returnValue = false;
   }
   if(!returnValue){
     window.alert(self.errorMsg + '\nCurrently ' + obj[self.fieldID].value.length + ' characters have been used.');
     if(focus){
     	obj[self.fieldID].focus();
     }
   }
   return returnValue;
 };
}

function PhoneNumberValidator(fieldID, type, errorMsg, focus, isMultiField){ 
 var self = this;
 var REG = new Array();
 REG[0] = '^((\\+\\d(\\d)?)?(\\(\\d\\{3}?)))? \\d{3}?-\\d{4}$';
REG[1] = '^\\(?[2-9]\\d{2}\\)?(\\s|-)[1-9]\\d{2}-\\d{4}$';

 this.fieldID = fieldID;
 this.type = type;
 this.errorMsg = errorMsg;
 this.isMultiField = isMultiField;
 this.validate = function(obj){
   var returnValue = true;
   if(self.isMultiField){
    if(obj[self.fieldID + '_pn1'].value.length > 0 || obj[self.fieldID + '_pn2'].value.length > 0 || obj[self.fieldID + '_pn3'].value.length > 0) {
      var reg = new RegExp(REG[self.type]);
      var val = obj[self.fieldID + '_pn1'].value + '-' + obj[self.fieldID + '_pn2'].value + '-' + obj[self.fieldID + '_pn3'].value
      returnValue = val.match(reg);
      if(!returnValue){
        window.alert(self.errorMsg);
        if(focus){
          obj[self.fieldID + '_pn1'].focus();
        }
      }
    }
   }else{
    if(obj[self.fieldID].value.length > 0) {
      var reg = new RegExp(REG[self.type]);
      returnValue = obj[self.fieldID].value.match(reg);
      if(!returnValue){
        window.alert(self.errorMsg);
        if(focus){
          obj[self.fieldID].focus();
        }
      }
    }
   }
   return returnValue;
 };
}
PhoneNumberValidator.INTERNATIONAL = 0;
PhoneNumberValidator.US = 1;


function RegexValidator(fieldID,regex,errorMsg, focus) { 
 var self = this;
 this.fieldID = fieldID;
 this.regex = regex;
 this.errorMsg = errorMsg;
 this.validate = function(obj){
   var reg = new RegExp(regex);
   var returnValue = (obj[self.fieldID].value != "")?obj[self.fieldID].value.match(reg):true;
   if(!returnValue){
     window.alert(self.errorMsg);
     if(focus){
       obj[self.fieldID].focus();
     }
   }
   return returnValue;
 };
}

function ComparisonValidator(fieldID, type, errorMsg, focus, fieldID2, value) { 
 var self = this;
 var OPERATORS = new Array();
 OPERATORS[0] = 'NOT_EQUAL';
OPERATORS[1] = 'GREATER_THAN';
OPERATORS[2] = 'EQUAL';
OPERATORS[3] = 'LESS_THAN_EQUAL';
OPERATORS[4] = 'GREATER_THAN_EQUAL';
OPERATORS[5] = 'LESS_THAN';

 this.fieldID = fieldID;
 this.fieldID2 = fieldID2;
 this.value = value; 
 this.type = type;
 this.errorMsg = errorMsg;
 this.validate = function(obj){
   var returnValue = true;
   if(obj[self.fieldID].value.length > 0) {
     var op = OPERATORS[self.type];
     var v1 = obj[self.fieldID].value;
     var v2 = null;
     if(value == null)
       v2 = obj[self.fieldID2].value;
     else 
       v2 = value;
     switch(op){
       case OPERATORS[ComparisonValidator.LESS_THAN]:
         returnValue = v1 < v2;
         break;
       case OPERATORS[ComparisonValidator.LESS_THAN_EQUAL]:
         returnValue = v1 <= v2;
         break;
       case OPERATORS[ComparisonValidator.GREATER_THAN]:
         returnValue = v1 > v2;
         break;
       case OPERATORS[ComparisonValidator.GREATER_THAN_EQUAL]:
         returnValue = v1 >= v2;
         break;
       case OPERATORS[ComparisonValidator.NOT_EQUAL]:
         returnValue = v1 != v2;
         break;
  	   case OPERATORS[ComparisonValidator.EQUAL]:
       default:
         returnValue = v1 == v2;
     }
     if(!returnValue){
       window.alert(self.errorMsg);
       if(focus){
         obj[self.fieldID].focus();
       }
     }
   }
   return returnValue;
 };
}
ComparisonValidator.NOT_EQUAL = 0;
ComparisonValidator.GREATER_THAN = 1;
ComparisonValidator.EQUAL = 2;
ComparisonValidator.LESS_THAN_EQUAL = 3;
ComparisonValidator.GREATER_THAN_EQUAL = 4;
ComparisonValidator.LESS_THAN = 5;


function ConditionalRequiredValidator(fieldID, cond, errorMsg, focus, operator) { 
  var self = this;
  var REG = '^[: :]+$';
  this.fieldID = fieldID;
  this.errorMsg = errorMsg;
  this.cond = cond;
  this.operator = operator;
  this.validate = function(obj){
    var reg = new RegExp(REG);
    var retVal = true;
    var selectItems = null;
  	var allReqMet = ("OR" == self.operator || "XOR" == self.operator)?false:true;
    for(var i=0; i < cond.requirements.length; i++){
    	var req = cond.requirements[i];
		var reqMet = req.inverse;
    	var isRB = typeof(obj[req.id].value) == 'undefined';
    	var isCB = obj[req.id].type == 'checkbox';
		var rbs = (isRB)? document.getElementsByName(req.id): null;
		for(var j=0; j < req.values.length; j++){
			var val = req.values[j].value;
            var numOp = req.values[j].numOp;      
			if(isCB){
				reqMet = obj[req.id].checked != req.inverse;
			} else if(isRB){
				for(var k=0; k < rbs.length; k++){
					var rb = rbs[k];
                    if(numOp != null){
                     switch(numOp){
                     case ConditionalRequiredValidator.EQUAL_TO:
                       if(rb.checked && Number(rb.value) == Number(val)){
                        reqMet = !req.inverse;
                       }                     
                       break;
                     case ConditionalRequiredValidator.NOT_EQUAL_TO:
                       if(rb.checked && Number(rb.value) != Number(val)){
                        reqMet = !req.inverse;
                       }                      
                       break;
                     case ConditionalRequiredValidator.LESS_THAN:
                       if(rb.checked && Number(rb.value) < Number(val)){
                        reqMet = !req.inverse;
                       }                      
                       break;
                     case ConditionalRequiredValidator.GREATER_THAN:
                       if(rb.checked && Number(rb.value) > Number(val)){
                        reqMet = !req.inverse;
                       }                      
                       break;
                     case ConditionalRequiredValidator.LESS_THAN_EQUAL_TO:
                       if(rb.checked && Number(rb.value) <= Number(val)){
                        reqMet = !req.inverse;
                       }                      
                       break;
                     case ConditionalRequiredValidator.GREATER_THAN_EQUAL_TO:                                                                                                           
                       if(rb.checked && Number(rb.value) >= Number(val)){
                        reqMet = !req.inverse;
                       }                      
                       break;
                     }    
                     break;    
                    } else {
                      if(rb.checked && rb.value == val){
						reqMet = !req.inverse;
						break;
	 				  }
                    }
				}	
				if(reqMet != req.inverse){
					break;
				}				
			} else {
                if(numOp != null){
                  switch(numOp){
                   case ConditionalRequiredValidator.EQUAL_TO:
                     if(Number(obj[req.id].value) == Number(val)){
                      reqMet = !req.inverse;
                     }                     
                     break;
                   case ConditionalRequiredValidator.NOT_EQUAL_TO:
                     if(Number(obj[req.id].value) != Number(val)){
                      reqMet = !req.inverse;
                     }                      
                     break;
                   case ConditionalRequiredValidator.LESS_THAN:
                     if(Number(obj[req.id].value) < Number(val)){
                      reqMet = !req.inverse;
                     }                      
                     break;
                   case ConditionalRequiredValidator.GREATER_THAN:
                     if(Number(obj[req.id].value) > Number(val)){
                      reqMet = !req.inverse;
                     }                      
                     break;
                   case ConditionalRequiredValidator.LESS_THAN_EQUAL_TO:
                     if(Number(obj[req.id].value) <= Number(val)){
                      reqMet = !req.inverse;
                     }                      
                     break;
                   case ConditionalRequiredValidator.GREATER_THAN_EQUAL_TO:                                                                                                           
                     if(Number(obj[req.id].value) >= Number(val)){
                      reqMet = !req.inverse;
                     }                      
                     break;
                  }    
                  break;
                } else {      
  				  if(obj[req.id].value == val ){
    			   reqMet = !req.inverse;
    			   break;
                  }
                }
			}
		}
		if("OR" === self.operator){
			allReqMet = allReqMet || reqMet;
		}else if("XOR" === self.operator){
			allReqMet = allReqMet != reqMet;
		}else if("XNOR" === self.operator){
			allReqMet = allReqMet == reqMet;
		}else {
			allReqMet = allReqMet && reqMet;
		}
	}
  	if(allReqMet) {
  		retVal = false;
  		var inputItems = null;
     	if(typeof(obj[self.fieldID].value) == 'undefined' || obj[self.fieldID].type == 'checkbox' ){
       		inputItems = document.getElementsByName(self.fieldID);
	       	for(var i=0; i< inputItems.length; i++) {
	         	if(inputItems[i].checked){
	           		retVal = true;
                }
	       	}
     	} else {
     		retVal = !obj[self.fieldID].value.match(reg) && obj[self.fieldID].value.length > 0;
     	}
     	if(!retVal){
       		window.alert(self.errorMsg);
       		if(focus && inputItems !== null){
         		inputItems[0].focus();
       		}else if(focus){
        		obj[self.fieldID].focus();
            }
     	}
   	}
    return retVal;    
  };
}
ConditionalRequiredValidator.EQUAL_TO = "EQUAL_TO";
ConditionalRequiredValidator.NOT_EQUAL_TO = "NOT_EQUAL_TO";
ConditionalRequiredValidator.LESS_THAN = "LESS_THAN";
ConditionalRequiredValidator.GREATER_THAN = "GREATER_THAN";
ConditionalRequiredValidator.LESS_THAN_EQUAL_TO = "LESS_THAN_EQUAL_TO";
ConditionalRequiredValidator.GREATER_THAN_EQUAL_TO = "GREATER_THAN_EQUAL_TO";

function NumericValidator(fieldID, type, errorMsg, focus){ 
 var self = this;
 var REG = new Array();
 REG[0] = '^[0-9a-fA-F]*\\.?[0-9a-fA-F]+$';
REG[1] = '^[0-8]*\\.?[0-8]+$';
REG[2] = '^[0-9]+$';
REG[3] = '^\\${0,1}((0||[1-9][0-9]*)||([1-9][0-9]{0,2}(,[0-9]{3})*))(\\.[0-9]{1,2}){0,1}$';
REG[4] = '^((100)|[0-9]{0,1}[0-9]{1,1})$';
REG[5] = '^[0-9]*\\.[0-9]+$';
REG[6] = '^[-+]?[0-9]*\\.?[0-9]+$';
REG[7] = '^[0-1]*\\.?[0-1]+$';

 this.fieldID = fieldID;
 this.type = type;
 this.errorMsg = errorMsg;
 this.validate = function(obj){
   var returnValue = true;
   if(obj[self.fieldID].value.length > 0) {
     var reg = new RegExp(REG[self.type]);
     returnValue = obj[self.fieldID].value.match(reg);
     if(!returnValue){
       window.alert(self.errorMsg);
       if(focus){
         obj[self.fieldID].focus();
       }
     }
   }
   return returnValue;
 };
}
NumericValidator.HEXADECIMAL = 0;
NumericValidator.OCTAL = 1;
NumericValidator.INTEGER = 2;
NumericValidator.CURRENCY = 3;
NumericValidator.PERCENTAGE = 4;
NumericValidator.DECIMAL = 5;
NumericValidator.NUMBER = 6;
NumericValidator.BINARY = 7;


