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 + '.' + this.name);

	var numSelected = 0;

    for (var i=0;i<obj.length;i++){

	  if (obj[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 + ' ei vastaa määriteltyä formaattia';

		   } else {

//		     errStr += '\n' + arrayList.item[i].prompttext + ' pitää olla ' + arrayList.item[i].datatype + ' merkkejä';

		     errStr += '\n' + arrayList.item[i].prompttext + ' täytyy olla ';

		     switch(arrayList.item[i].datatype.toString()) {

		       case 'any':

		         errStr += 'täytetty';

			 break;

		       case 'alpha':

		         errStr += 'vain aakkosia';

			 break;

		       case 'numeric':

		         errStr += 'vain numeroita';

		         break;

		     }

		   }

		 } 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 + ' pitää olla vähintään ' + arrayList.item[i].datatype.minvalue;

		     if (arrayList.item[i].datatype.maxvalue!=Number.POSITIVE_INFINITY) errStr += '\n' + arrayList.item[i].prompttext + ' pitää olla korkeintaan ' + 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 + ' pitää olla vähintaan ' + arrayList.item[i].datatype.minlength + ' merkkiä pitkä';

		     if (arrayList.item[i].datatype.maxlength!=Number.POSITIVE_INFINITY) errStr += '\n' + arrayList.item[i].prompttext + ' saa olla korkeintaan ' + arrayList.item[i].datatype.maxlength + ' merkkiä pitkä';

			 break;

		   case 'lsdate':

		     if (arrayList.item[i].datatype.mindate) errStr += '\n' + arrayList.item[i].prompttext + ' pitää olla vähintään ' + arrayList.item[i].datatype.mindate;

		     if (arrayList.item[i].datatype.maxdate) errStr += '\n' + arrayList.item[i].prompttext + ' saa olla korkeintaan ' + arrayList.item[i].datatype.maxdate;

		     break;

		  } 

		 }

	    }

	    break;

	  case 'Radio':

	    if (!arrayList.item[i].isValid()){

		   errStr += '\n' + arrayList.item[i].prompttext + ' pitää olla valittu';

		   var bOK = false;

		}

	    break;

	  case 'Checkbox':

	    if (!arrayList.item[i].isValid()){

		   errStr += '\n' + arrayList.item[i].prompttext + ' pitää olla vähintään ' + arrayList.item[i].minchecked + ' ja korkeintaan ' + arrayList.item[i].maxchecked + ' kohdetta valittu';

		   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 += ' pitää olla valittu';

		   if (arrayList.item[i].minselected==arrayList.item[i].maxselected) errStr += ' - pitää valita ' + arrayList.item[i].minselected + ' value(s)';

		   else errStr += ' (pitää valita väliltä ' + 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  + ' pitää olla täytetty';

		  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 = \'imgs/warning.gif\'');

	 else eval('document.' + arrayList.item[i].name + '.src = \'imgs/transparent.gif\'');

  }

  if (errStr) {

     errStr = '\nLomaketta ei voitu lähettää koska:\n' + errStr + '\n\nOle hyva ja korjaa lomakkeen tiedot';

     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 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÅ1234567890.- \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;

}





