function ArrayList(){
   this.item = new Array();
   this.length = 0;
}

// global ArrayList
var arrayList = new ArrayList();

ArrayList.prototype.add = function(obj){
  this.item[this.length++] = obj;
}

function Control(name,prompttext){
  this.name = name;
  this.prompttext = prompttext;
}

function Textbox(prompttext,name,required,datatype,size,maxlength){
   this.base = Control;
   this.required = required;
   this.base(name,prompttext);
   this.datatype = datatype;
}

Textbox.prototype = new Control;
Textbox.prototype.toString = function(){ return 'Textbox';}
Textbox.prototype.isValid = function(){
  var bValid = true;
  var obj = eval('document.' + frm + '.' + this.name + ';');

  if (this.required || (!this.required && obj.value.length>0)){
	if (!isBlank(obj.value)){
	    switch (this.datatype.toString()){
		   case 'alpha':
		     if (!isAlpha(obj.value)) bValid = false;
		     break;
		   case 'numeric':
		     if (!isNumeric(obj.value)) bValid = false;
		     break;
		   case 'alphanumeric':
		     if (!isAlphaNumeric(obj.value)) bValid = false;
		     break;
		   case 'any':
		     break;
		   case 'lsdate':
		     if (!this.datatype.isValidDate(obj.value)) bValid=false;
		     break;
		}
	} else bValid = false;
  }
  return bValid;
}
Textbox.prototype.inRange = function(){
  var bValid = true; // assume true
  var obj = eval('document.' + frm + '.' + this.name);
  if (this.required || (!this.required && obj.value.length>0)){
	if (!isBlank(obj.value)){
	    switch (this.datatype.toString()){
		   case 'alpha':
		   case 'alphanumeric':
		   case 'any':
		     // string type, check permitted length
			 if (obj.value.length<this.datatype.minlength) bValid = false;
			 if (obj.value.length>this.datatype.maxlength) bValid = false;
			 break;
		   case 'numeric':
			 if (obj.value<this.datatype.minvalue) bValid = false;
			 if (obj.value>this.datatype.maxvalue) bValid = false;
			 break;		
		   case 'lsdate':
		     if (!this.datatype.inRange(obj.value)) bValid = false;
		     break;   
		}
	} //else bValid = false;
  }
  return bValid;
}

/* now define the textboxes datatype objects */
function nonnumeric(minlength,maxlength,type){
  this.minlength = minlength;
  this.maxlength = maxlength;
  this.type = type;
}
nonnumeric.prototype.toString = function() { return this.type;}

function numeric(minvalue,maxvalue,type){
  this.minvalue = minvalue;
  this.maxvalue = maxvalue;
  this.type = type;
}
numeric.prototype.toString = function() { return this.type;}

function lsdate(format,separator,mindate,maxdate){
  this.format = format;
  this.separator = separator;
  this.mindate = mindate;
  this.maxdate = maxdate;
  this.type = 'lsdate';
}
lsdate.prototype.toString = function(){ return this.type;}
lsdate.prototype.isValidDate = function(dteCheck){
  var bValid = true;
  var tmp = dteCheck.split(this.separator);
  if (tmp.length!=3) return false;
  switch (this.format){
     case 'dd-mmm-yyyy':
	 case 'dd/mmm/yyyy':
	 case 'dd-mm-yyyy':
	 case 'dd/mm/yyyy':
	   bValid = isValidDate(tmp[0],tmp[1],tmp[2]);
	   break;
	 case 'mm/dd/yyyy':
	 case 'mm-dd-yyyy':
	   bValid = isValidDate(tmp[1],tmp[0],tmp[2]);
	   break;
	 case 'yyyy/mm/dd':
	 case 'yyyy-mm-dd':
	   bValid = isValidDate(tmp[2],tmp[1],tmp[0]);
	   break; 
  }
   return bValid;
}
lsdate.prototype.inRange = function(value){
  var bValid = true;
  var valueDate = convertToJSDate(this.format,this.separator,value)
  if (this.mindate && this.isValidDate(this.mindate)){
    var minDate = convertToJSDate(this.format,this.separator,this.mindate);
	if (valueDate<minDate) bValid = false;
  }
  if (this.maxdate && this.isValidDate(this.maxdate)){
    var maxDate = convertToJSDate(this.format,this.separator,this.maxdate);
	if (valueDate>maxDate) bValid = false;
  }
  return bValid;  
}

function convertToJSDate(format,separator,value){
  // assumes they have been checked for validity first
  var tmp = value.split(separator);
  var JSDate;
  switch (format){
     case 'dd-mmm-yyyy':
	 case 'dd/mmm/yyyy':
	   JSDate = new Date(tmp[2],monthNumFromName(tmp[1]),tmp[0]);
	   break;
	 case 'dd-mm-yyyy':
	 case 'dd/mm/yyyy':
	   JSDate = new Date(tmp[2],tmp[1]-1,tmp[0]);
	   break;
	 case 'mm-dd-yyyy':
	 case 'mm/dd/yyyy':
	   JSDate = new Date(tmp[2]-1,tmp[0],tmp[1]);
	   break;
	 case 'yyyy-mm-dd':
	 case 'yyyy/mm/dd':
	   JSDate = new Date(tmp[0],tmp[1]-1,tmp[2]);
	   break;
  }
  return JSDate;
}

var monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
function monthNumFromName(month){
  for (var i=0;i<monthNames.length;i++){
     if (monthNames[i].substring(0,3).toLowerCase()==month.toLowerCase()) return (i+1);
  }
  return 0;
}
function isValidDate(day,month,year){
  var bValid = true;
  if (isAlpha(month)){ // text month
    month = monthNumFromName(month);
	if (month==0) return false;
  }
  // got this far so could be numeric or converted to numeric
    if (isNumeric(month)){
	  if (month>0 && month<13){
	    if (isNumeric(year) && year<9999){
		  if (!(isNumeric(day) && day>0 && day<=daysInMonth(month-1,year))) bValid = false;
		} else bValid = false;
	  } else bValid = false;
    } else bValid = false;

  return bValid;
}

function daysInMonth(month,year){
  var monthDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  if (month!=1) return monthDays[month];
  else {return isLeapYear(year) ? 29:28;}
}
function isLeapYear(year){
  if (year%4==0 && ((year%100!=0) || (year%400==0))) return true; else return false;
}

function Textarea(prompttext,name,required){
   this.base = Control;
   this.required = required
   this.base(name,prompttext);
}
Textarea.prototype = new Control;
Textarea.prototype.toString = function() { return 'Textarea';}
Textarea.prototype.isValid = function(){
  if (this.required){
    var obj = eval('document.' + frm + '.' + this.name);
	if (isBlank(obj.value)) return false;
	else return true;
  } else return true; //trivial case
}
function Radio(prompttext,name,required){
   this.base = Control;
   this.required = required
   this.base(name,prompttext);
}
Radio.prototype = new Control;
Radio.prototype.toString = function(){ return 'Radio';}
Radio.prototype.isValid = function(){
  if (this.required){
    var obj = eval('document.' + frm + '.' + this.name);
    var bSelected = false;
    for (var i=0;i<obj.length;i++){
	  if (obj[i].checked) {
	    bSelected = true;
		break;
	  }
	}
	return bSelected;
  } else return true;
}

function Checkbox(prompttext,name,minchecked,maxchecked){
   this.base = Control;
   this.base(name,prompttext);
   this.minchecked = minchecked;
   this.maxchecked = maxchecked;
}
Checkbox.prototype = new Control;
Checkbox.prototype.toString = function(){ return 'Checkbox';}
Checkbox.prototype.isValid = function(){
  if (this.minchecked || this.maxchecked){
    var obj = eval('document.' + frm);
	var numSelected = 0;
    for (var i=0;i<obj.elements.length;i++){
	  var sName = obj.elements[i].name
	  if (sName.substring(0,sName.indexOf("_")) == this.name) {
		if(obj.elements[i].checked) {
		    numSelected++;
		}
	  }
	}
	if (numSelected < this.minchecked || numSelected > this.maxchecked) return false
	else return true;
  } else return true;  // trivial case
}

function Combo(prompttext,name,minselected,maxselected){
  this.base = Control;
  this.base(name,prompttext);
  this.minselected = minselected;
  this.maxselected = maxselected;
}
Combo.prototype = new Control;
Combo.prototype.toString = function(){ return 'Combo';}
Combo.prototype.isValid = function(){
  if (this.minselected || this.maxselected){
    var obj = eval('document.' + frm + '.' + this.name + '');
	var numSelected = 0;
    for (var i=0;i<obj.options.length;i++){
	  if (obj.options[i].selected && obj.options[i].value!='') {
	    numSelected++;
	  }
	}
	if (numSelected < this.minselected || numSelected > this.maxselected) return false
	else return true;
  } else return true;  // trivial case
}

function validate(f){
  var errStr = '';
  for (var i=0;i<arrayList.length;i++){

    bOK = true;
	switch (arrayList.item[i].toString()){ 
	  case 'Textbox':
  	     if (!arrayList.item[i].isValid()){
		   var bOK = false;
		   if (arrayList.item[i].datatype.toString()=='lsdate'){
		     errStr += '\n' + arrayList.item[i].prompttext + ' is not valid or does not match required format';
		   } else {
		     errStr += '\n' + arrayList.item[i].prompttext + ' should be ' + arrayList.item[i].datatype + ' characters';
		   }
		 } else {
		  if (!arrayList.item[i].inRange()){
		  var bOK = false;
	      switch (arrayList.item[i].datatype.toString()){
		   case 'numeric':     
		     if (arrayList.item[i].datatype.minvalue!=Number.NEGATIVE_INFINITY) errStr += '\n' + arrayList.item[i].prompttext + ' must be at least ' + arrayList.item[i].datatype.minvalue;
		     if (arrayList.item[i].datatype.maxvalue!=Number.POSITIVE_INFINITY) errStr += '\n' + arrayList.item[i].prompttext + ' must be at most ' + arrayList.item[i].datatype.maxvalue;
			 break;
		   case 'alpha':
		   case 'alphanumeric':	
		   case 'any':	
		     if (arrayList.item[i].datatype.minlength!=Number.NEGATIVE_INFINITY) errStr += '\n' + arrayList.item[i].prompttext + ' must be at least ' + arrayList.item[i].datatype.minlength + ' characters long';
		     if (arrayList.item[i].datatype.maxlength!=Number.POSITIVE_INFINITY) errStr += '\n' + arrayList.item[i].prompttext + ' must be at most ' + arrayList.item[i].datatype.maxlength + ' characters long';
			 break;
		   case 'lsdate':
		     if (arrayList.item[i].datatype.mindate) errStr += '\n' + arrayList.item[i].prompttext + ' should be on or after ' + arrayList.item[i].datatype.mindate;
		     if (arrayList.item[i].datatype.maxdate) errStr += '\n' + arrayList.item[i].prompttext + ' should be on or before ' + arrayList.item[i].datatype.maxdate;
		     break;
		  } 
		 }
	    }
	    break;
	  case 'Radio':
	    if (!arrayList.item[i].isValid()){
		   errStr += '\n' + arrayList.item[i].prompttext + ' should be selected';
		   var bOK = false;
		}
	    break;
	  case 'Checkbox':
	    if (!arrayList.item[i].isValid()){
		   errStr += '\n' + arrayList.item[i].prompttext + ' must have at least ' + arrayList.item[i].minchecked + ' and at most ' + arrayList.item[i].maxchecked + ' items selected';
		   var bOK = false;
		}	
		break;  
	  case 'Combo':

	    if (!arrayList.item[i].isValid()){
	  	   errStr += '\n' + arrayList.item[i].prompttext;
		   if (arrayList.item[i].minselected==1 && arrayList.item[i].minselected==1) errStr += ' must be selected';
		   if (arrayList.item[i].minselected==arrayList.item[i].maxselected) errStr += ' - must choose ' + arrayList.item[i].minselected + ' value(s)';
		   else errStr += ' (must choose between ' + arrayList.item[i].minselected + ' and ' + arrayList.item[i].maxselected + ' values)';
		   var bOK = false;
		}
		break;
	  case 'Textarea':
	    if (!arrayList.item[i].isValid()){
		  errStr += '\n' + arrayList.item[i].prompttext  + ' may not be left blank';
		  var bOK = false;
		}
	    break;
	}
	/* comment out these two lines if you don't want the warning icons to appear */
	 if (!bOK) eval('document.' + arrayList.item[i].name + '.src = \'/cw/images/warning.gif\'');
	 else eval('document.' + arrayList.item[i].name + '.src = \'/cw/images/transparent.gif\'');
  }
  if (errStr) {
     errStr = 'The form may not be submitted because of the following:\n' + errStr + '\n\nPlease correct and resubmit';
     alert(errStr);
  } else{
    return true //uncomment to allow it to actually post
    alert('Form is ok, here you would return true to submit');
  }
  return false;
} 

function isBlank(s){
  for (var k=0;k<s.length;k++){
    var c = s.charAt(k);
	if ((c != ' ') && (c != '\n') && (c != '\t')) {
	  return false;
	}
  }
  return true;
}

function isAlpha(s){
  var okchrs = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ- ';
  return charTest(s,okchrs);
}

function isNumeric(s){
  var okchrs = '.0123456789,';
  return charTest(s,okchrs);
}

function isAlphaNumeric(s){
  var okchrs = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.- \t\n';
  return charTest(s,okchrs);
}

function charTest(s,okchrs,etext){
  for (var k=0;k<s.length;k++){
    var c = s.charAt(k).toUpperCase();
	if (okchrs.indexOf(c)==-1) {
	   return false;
	} 
  }
  return true;
}



