/* validateform.js
* by Frank Koenen. v1.0 Feb-2001
* Copyright (c) 2001 Monet Technologies. All Rights Reserved.
* You may use this code on a public Web site only if this entire
* copyright notice appears unchanged and you publicly display
* a link to http://www.monet.com/.
*
* Contact fkoenen@virtualmonet.com for all other uses.
* ---------------------------------------------------------------------------------------------
* displays an alert window with error conditions, sets 'document.returnValue' to true or false.
* ---------------------------------------------------------------------------------------------
*  Summary of javascript calls:
* 
*  Function: creditcard
*  Purpose:
*   Check valid credit cards entries:
*   1234-123456-12345   for American Express
*   1234-1234-1234-1234 for Discover/MC/Visa
* 
*  Also allows space and dots or all numbers with no seperators.
* --------------------------------------------------------------------
*  Function: isfloat
*  Purpose:
*   check and format the input into a floating point value.
*
*   The number of decimal places requested is the argument to the call.
*
*  Example:
*   isfloat.2
* --------------------------------------------------------------------
*  Function: datecheck
*  Purpose:
*   check a date format. some formatting of the date may occur, you may want to
*   pre process with 'notnull' and postprocess with 'capfirst'
*
*  current supported format checks:
*   1  === Mon-DD-YYYY (also accepts Mon-D-YYYY, but formats back to Mon-DD-YYYY)
*   1n === same checkas 1, but allows 'never' as an input as well.
*
*  Example:
*   datecheck.1
* --------------------------------------------------------------------
*  Function: capfirst
*  Purpose:
*   Convert the first character of every word to capital letter. If ".L"
*   follows the call, all other characters in the string are converted to lower case.
*
*  Example:
*   capfirst.L
* --------------------------------------------------------------------
*  Function: emailaddress
*  Purpose:
*   Javascript to check syntax of email address. If no email given, and varags "N"
*  specified, no check.
*  Example:
*    emailaddress.N      (field can be null without error)
*  or
*    emailaddress
* --------------------------------------------------------------------
*  Function: inrange
*  Purpose:
*   Check field is numerically within a range specified.
* 
*  Example call:
*     inrange.low-high
*     inrange.4-999
* --------------------------------------------------------------------
*  Function: isalpha
*  Purpose:
*   Checks that "field" only contains a-zA-Z values. the following characters
*   can be added to the call following a "." character to:
*    S: allows spaces too.
*    D: allows dots too.
*    A: allows apostrophes too.
*    C: allows commas too.
*    U: allows underscores too.
* 
*  Example call:
*     isalpha.D
*     isalpha.SD
*     isalpha.DUS
* --------------------------------------------------------------------
*  Function: isalphanumeric
*  Purpose:
*   Checks that "field" only contains a-zA-Z0-9 values. the following characters
*   can be added to the call following a "." character to:
*    S: allows spaces too.
*    D: allows dots too.
*    A: allows apostrophes too.
*    C: allows commas too.
*    @: allows the @ char too.
*    d: allows the - (dash) char too.
*    U: allows the _ (underscore) char too.
* 
*  Example call:
*     isalphanumeric
*     isalphanumeric.DSA
*     isalphanumeric.S
*     isalphanumeric.SdU
* --------------------------------------------------------------------
*  Function: default
*  Purpose:
*  provides a client-side default for a field left empty by the visitor.
*  is subtley different than a server side default, helps to handle the
*  null value situation. This check does not cause an error notice, for
*  that, the third argument of the set is ignored, but must still be passed.
* 
*  Example call:
*   'default.default value goes here'
* or 
*   'default.default+value+goes+here'
* --------------------------------------------------------------------
*  Function: maxlength
*  Purpose:
*   Checks a maximum length of "field". The length to check against is
*  sent via the "jscall.X" value.
* --------------------------------------------------------------------
*  Function: minlength
*  Purpose:
*   Checks a minimum length of "field". The length to check against is
*  sent via the "jscall.X" value. If jscall ends with "N", Null is okay
*  too.
* 
*  Example call:
*   minlength.n
*   minlength.2
*   minlength.2N
* --------------------------------------------------------------------
*  Function: minmax
*  Purpose:
*   Check field length between min/max number of characters.
*  Example:
*   minmax.min-max
*   minman.2-20
* --------------------------------------------------------------------
*  Function: notnull
*  Purpose:
*  checks that field contains a value.
* --------------------------------------------------------------------
*  Function: nullradioselect
*  Purpose:
*   Javascript to check that at least one radio button is selected.
* --------------------------------------------------------------------
*  Function: nullselection
*  Purpose:
*   Ensure a selection is picked of a "<SELECT " tag. By rule, always the
*   first element of a selection box is invalid, this is the check to perform.
* --------------------------------------------------------------------
*  Function: override
*  Purpose:
*   Used with an "<INPUT type=submit" tag to bypass the Javascript onSubmit checks,
*   letting the server-side perform any procedure defining, for example, a cancel operation.
*   For this function to work properly, the "onClick='document.override=1'" must be added to the
*   <INPUT tag. It only makes sense to have the "override" operation be the
*   first of any javascript checks to perform.
* --------------------------------------------------------------------
*  Function: phone
*  Purpose:
*   Check phone number syntax. To perform various 
*  formats, the particular check is identified via the "jscall.XYZ"
*  value.
* 
*  Where "X" may be one of:
*    1 == United States syntax
*    2 == European syntax
* 
*  Where "Y" refers to the form for the phone number:
*    N == not required
*    R == required
* 
*  Where "Z" refers to the area code and may be one of:
*    A == must have area code
*    a == are code is optional
* 
*  United States syntax is in the formats:
*        123-123-1234
*            123-1234
* 
*  Also allows space and dots or all numbers with no seperators.
* --------------------------------------------------------------------
*  Function: state
*  Purpose:
*  Check that a valid state was entered. Takes the first four characters
*  and checks them against the array of valid states, then abbreviates it.
*  field.value is replaced with 2-character state abbrev.
* --------------------------------------------------------------------
*  Function: touppercase
*  Purpose:
*  Makes the value in the form field Uppercase. 
* --------------------------------------------------------------------
*  Function: zip
*  Purpose:
*  Javascript to check for a valid US zip code with or without a speed zipcode.
* --------------------------------------------------------------------
*  Function: validurl
*  Purpose:
*  Checks that "field" only contains a-zA-Z0-9 values and a ".", used to check
*  "URL" entries.
* --------------------------------------------------------------------
*  Function: confirm
*  Purpose:
*  Confirms that user input in another field is identical to itself. (password -
*  confirm password) 
* 
*  Example call, the name of the input field to compare against follows the
*  "confirm." string in "jscall".
*   confirm.document.formname.object  (no layers)
*   confirm.T1.doc.formname.object   (with layers)
* --------------------------------------------------------------------
*  Function: ilt (also: ilteq, igt, and igteq)
*  Purpose:
*  perform a mathematical INTEGER compare of own value against another, error if >=(ilt),
*  >(ilteq), <=(igt) or <(igteq).
* 
*  Example call, the name of the opposite input field to compare against follows the
*  "ilt." string in "jscall".
*   ilt.document.formname.object  (no layers)
*   ilt.T1.doc.formname.object   (with layers)
*
* Note: field.value will be reset to an integer value, a float will converted to integer.
* --------------------------------------------------------------------
*/
function validateform(){
// configuration toggles.
var confalert=0; // send alert message., 1 to disable.
var start=0;
if(validateform.arguments.length>0){
 if(validateform.arguments[0].length>0){
  if(validateform.arguments[0].indexOf('C.')==0){
   var conf=validateform.arguments[0].substr(2);
   if(conf==1)confalert=1; // turn off alerts, just return true/false.
   start=1; // slice and shift were not compatible, lame hack to skip this element.
  }
 }
}
var i,jscall,field,errors='';
var tmpa,tmpb,tmpc,tmpe;
for(i=start;i<(validateform.arguments.length-2);i+=3){
field=eval(validateform.arguments[i]);jscall=validateform.arguments[i+1];shortname=validateform.arguments[i+2];
if(field.value)field.value=field.value.replace(/ +$/g,'');
if(jscall.indexOf('notnull')==0){tmpa=field.value.replace(/ */g,'');if(tmpa.length<1)errors+='- '+shortname+' is required.\n';}
else if(jscall.indexOf('capfirst')==0){if(jscall.indexOf('capfirst.L')==0)tmp=field.value.toLowerCase();else tmp=field.value;tmpj=tmp.substring(0,1);tmp=tmpj.toUpperCase()+tmp.substring(1);if(tmp.indexOf(' ')>0){var tmpa=tmp.substr(0,tmp.indexOf(' '));var tmpb=tmp.match(/\s\w*/g);tmp='';for(var tmpi=0;tmpi<tmpb.length;tmpi++){tmpj=tmpb[tmpi].substring(1,2);var tmpc=tmpj.toUpperCase();var tmpd=tmpb[tmpi].substring(2);tmp+=' '+tmpc+tmpd;}tmp=tmpa+tmp;} field.value=tmp;}
else if(jscall.indexOf('creditcard')==0){if(field.value.length>0){tmpa=field.value.split(/\-| |\./,4);tmpb=tmpa.length; if(tmpb!=1&&tmpb!=3&&tmpb!=4)errors+= '- '+shortname+' must be a valid credit card.\n'; else if(tmpb==1 && (field.value.length != 15 && field.value.length != 16))errors+='- '+shortname+' must be a valid credit card.\n'; else if(tmpb==3 && field.value.length != 17)errors+='- '+shortname+' must be a valid credit card.\n'; else if(tmpb==4 && field.value.length != 19)errors+='- '+shortname+' must be a valid credit card.\n'; else if(tmpb>=3){tmpa[0].concat(tmpa[1]);tmpa[0].concat(tmpa[2]);} if(tmpb==4)tmpa[0].concat(tmpa[3]); for(tmpi=0;tmpi<tmpa[0].length;tmpi++)if(!(((tmpa[0].charAt(tmpi)>='0')&&(tmpa[0].charAt(tmpi)<='9')))){errors+='- '+shortname+' can only contain numeric values.\n';break;}}}
else if(jscall.indexOf('emailaddress')==0){if(!(jscall.indexOf('.N')>0&&field.value.length==0)){if(field.value.length==0)errors+='- '+shortname+' is required.\n';else if(field.value.indexOf('@')<1||field.value.indexOf('@')==(field.value.length-1)||field.value.indexOf('\.')<0)errors+='- '+shortname+' must contain an e-mail address.\n';else field.value=field.value.replace(/ */g,'');}}
else if(jscall.indexOf('inrange')==0){if(field.value.length>0){tmpa=jscall.match(/^(\w+)\.([0-9]+)-([0-9]+)/);if(isNaN(field.value)) errors+='- '+shortname+' must be within range '+tmpa[2]+'-'+tmpa[3]+'.\n';else if((field.value*1)<tmpa[2]||(field.value*1)>tmpa[3])errors+='- '+shortname+' must be within range '+tmpa[2]+'-'+tmpa[3]+'.\n';}}
else if(jscall.indexOf('isalphanumeric')==0){for(tmpi=0;tmpi<field.value.length;tmpi++){if(!(((field.value.charAt(tmpi)>='a')&&(field.value.charAt(tmpi)<='z'))||((field.value.charAt(tmpi)>='A')&&(field.value.charAt(tmpi)<='Z'))||((field.value.charAt(tmpi)>='0')&&(field.value.charAt(tmpi)<='9')))&&!(jscall.indexOf('S')>11&&field.value.charAt(tmpi)==' ')&&!(jscall.indexOf('U')>11&&field.value.charAt(tmpi)=='_')&&!(jscall.indexOf('@')>11&&field.value.charAt(tmpi)=='@')&&!(jscall.indexOf('d')>11&&field.value.charAt(tmpi)=='-')&&!(jscall.indexOf('D')>11&&field.value.charAt(tmpi)=='.')&&!(jscall.indexOf('C')>11&&field.value.charAt(tmpi)==',')&&!(jscall.indexOf('A')>11&&field.value.charAt(tmpi)=='\'')){errors+='- '+shortname+' may contain only letters and numbers.\n';break;}}}
else if(jscall.indexOf('isalpha')==0){for(tmpi=0;tmpi<field.value.length;tmpi++){if(!(((field.value.charAt(tmpi)>='a')&&(field.value.charAt(tmpi)<='z'))||((field.value.charAt(tmpi)>='A')&&(field.value.charAt(tmpi)<='Z')))&&!(jscall.indexOf('U')>11&&field.value.charAt(tmpi)=='_')&&!(jscall.indexOf('S')>6&&field.value.charAt(tmpi)==' ')&&!(jscall.indexOf('D')>6&&field.value.charAt(tmpi)=='.')&&!(jscall.indexOf('C')>6&&field.value.charAt(tmpi)==',')&&!(jscall.indexOf('A')>6&&field.value.charAt(tmpi)=='\'')){errors+='- '+shortname+' may contain only letters.\n';break;}}}
else if(jscall.indexOf('maxlength')==0){if(field.value.length>jscall.substring(jscall.indexOf('.')+1,jscall.length))errors+='- '+shortname+' must be less than '+jscall.substring(jscall.indexOf('.')+1,jscall.length)+' characters.\n';}
else if(jscall.indexOf('minlength')==0){if(!(field.value.length==0&&jscall.charAt(jscall.length-1)=='N')){jscall=jscall.replace(/N$/g,'');if(field.value.length<jscall.substring(jscall.indexOf('.')+1,jscall.length))errors+= '- '+shortname+' must contain at least '+jscall.substring(jscall.indexOf('.')+1,jscall.length)+' characters.\n';}}
else if(jscall.indexOf('minmax')==0){tmpa=jscall.match(/^(\w+)\.([0-9]+)-([0-9]+)/);if(field.value.length<tmpa[2]||field.value.length>tmpa[3])errors+='- '+shortname+' must be at least '+tmpa[2]+' characters and no more than '+tmpa[3]+' characters.\n';}
else if(jscall.indexOf('nullradioselect')==0){tmpp=false;for(tmpj=0;tmpj<field.length;tmpj++){if(field[tmpj].checked==true){tmpp=true;break;}}if(!tmpp)errors+='- '+shortname+' must have at least one choice selected.\n';}
else if(jscall.indexOf('nullselection')==0){if(field.selectedIndex==0)errors+='- '+shortname+' must be selected.\n';}
else if(jscall.indexOf('override')==0){if(document.override==1)return 0;}
else if(jscall.indexOf('phone')==0){if(jscall.indexOf('.1')>0){if (!(jscall.indexOf('.1N')>0&&field.value.length==0)){field.value=field.value.replace(/ */g,'');field.value=field.value.replace(/-*/g,'');field.value=field.value.replace(/\.*/g,'');if(field.value.length==0)errors+='- '+shortname+' is required.\n';else{for(tmpi=0;tmpi<field.value.length;tmpi++)if(!(((field.value.charAt(tmpi)>='0')&&(field.value.charAt(tmpi)<='9')))){errors+='- '+shortname+' can only contain numeric values.\n';break;}if(field.value.length==7&&jscall.indexOf('A')==jscall.length-1){errors+='- '+shortname+' requires area code.\n';}else if(field.value.length!=7&&field.value.length!=10){errors+='- '+shortname+' must be a valid phone number.\n';}}}}else{errors+='- European syntax checking not completed.\n'};}
else if(jscall.indexOf('state')==0){if(field.value.length>0){tmps=new Array(['AL','AL'],['AK','ALAS'],['AZ','ARI'],['AR','ARK'],['CA','CA'],['CO','CO'],['CT','CON'],['DE','DE'],['DC','DC'],['FL','FL'],['GA','GE'],['HI','HA'],['ID','ID'],['IL','IL'],['IN','IN'],['IA','IO'],['KS','KA'],['KY','KE'],['LA','LO'],['ME','MAI'],['MD','MAR'],['MA','MAS'],['MI','MIC'],['MN','MIN'],['MS','MISSI'],['MO','MISSO'],['MT','MON'],['NE','NEB'],['NV','NEV'],['NH','NEW H'],['NJ','NEW J'],['NM','NEW M'],['NY','NEW Y'],['NC','NORTH C'],['ND','NORTH D'],['OH','OH'],['OK','OK'],['OR','OR'],['PR','PU'],['PA','PE'],['RI','RH'],['SC','SOUTH C'],['SD','SOUTH D'],['TN','TEN'],['TX','TEX'],['UT','UT'],['VT','VE'],['VA','VI'],['WA','WA'],['WV','WE'],['WI','WI'],['WY','WY']);tmpv='';tmpa=field.value.toUpperCase();for(tmpi=0;tmpi<tmps.length;tmpi++){if(tmpa.indexOf(tmps[tmpi][1])==0||tmps[tmpi][0]==tmpa){tmpv=tmps[tmpi][0];break;}}if(tmpv=='')errors+='- '+shortname+' must be a valid state abbreviation. (Example: CA).\n';else field.value=tmpv;}}
else if(jscall.indexOf('touppercase')==0){if(field.value.length>0){tmpa='';tmpa=field.value.toUpperCase();field.value=tmpa;}}
else if(jscall.indexOf('zip')==0){if(field.value.length==0||field.value==0)errors+='- '+shortname+' must be 5 digits.\n';else{tmps='';tmpd=field.value.indexOf('-');if(tmpd>0){tmpz=field.value.substring(0,tmpd);tmps=field.value.substring(tmpd+1,field.value.length);if(!(tmpz>=1&&tmpz<=99999)){errors+='- '+shortname+' must be 5 digits.\n';}if(!(tmps>=1&&tmps<=9999)){errors+='- Speed zip must be 4 digits.\n';}}else{if(!(field.value>=1&&field.value<=99999))errors+='- '+shortname+' must be 5 digits.\n';tmpz=field.value;}while(tmpz.length<5){tmpz='0'+tmpz;}field.value=tmpz;if(tmps.length>0){while(tmps.length<4){tmps='0'+tmps;}field.value+='-'+tmps;}}}
else if(jscall.indexOf('validurl')==0){for(tmpi=0;tmpi<field.value.length;tmpi++){if(!(((field.value.charAt(tmpi)>='a')&&(field.value.charAt(tmpi)<='z'))||((field.value.charAt(tmpi)>='A')&&(field.value.charAt(tmpi)<='Z'))||((field.value.charAt(tmpi)>='0')&&(field.value.charAt(tmpi)<='9'))||(field.value.charAt(tmpi)=='.'))){errors+='- '+shortname+' may contain only letters and numbers.\n';break;}}}
else if(jscall.indexOf('confirm.')==0){var tmpO=eval(jscall.substring(8));if(field.value!=tmpO.value)errors+='- '+shortname+', password mismatch.\n';}
else if(jscall.indexOf('ilt.')==0){var tmpO=eval(jscall.substring(4));tmpa=parseInt(tmpO.value,10);tmpb=parseInt(field.value,10);if(tmpb>=tmpa)errors+='- '+shortname+', too large.\n';if(!isNaN(tmpb))field.value=tmpb;}
else if(jscall.indexOf('ilteq.')==0){var tmpO=eval(jscall.substring(6));tmpa=parseInt(tmpO.value,10);tmpb=parseInt(field.value,10);if(tmpb>tmpa)errors+='- '+shortname+', too large.\n';if(!isNaN(tmpb))field.value=tmpb;}
else if(jscall.indexOf('igt.')==0){var tmpO=eval(jscall.substring(4));tmpa=parseInt(tmpO.value,10);tmpb=parseInt(field.value,10);if(tmpb<=tmpa)errors+='- '+shortname+', too small.\n';if(!isNaN(tmpb))field.value=tmpb;}
else if(jscall.indexOf('igteq.')==0){var tmpO=eval(jscall.substring(6));tmpa=parseInt(tmpO.value,10);tmpb=parseInt(field.value,10);if(tmpb<tmpa)errors+='- '+shortname+', too small.\n';if(!isNaN(tmpb))field.value=tmpb;}
else if(jscall.indexOf('default.')==0){if(field.value.length==0){tmpa=jscall.substring(8);field.value=unescape(tmpa);}}
else if(jscall.indexOf('datecheck.')==0){if(field.value.length>0){var tmpa=jscall.substr(10);if(tmpa==1||tmpa=='1n'){tmpc='12';if(!(field.value.toLowerCase()=='never'&&tmpa=='1n')){tmpa=field.value.substr(0,3);tmpa=tmpa.toUpperCase();tmpb=field.value.substr((field.value.length-4),4);tmpc=field.value.substr(4,field.value.length-9);tmpd='JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC';if(!(tmpd.indexOf(tmpa)>=0&&!isNaN(tmpc)&&!isNaN(tmpb)&&tmpb.length==4&&tmpc>0&&tmpb>0)){errors+='- '+shortname+' must be a date in the format Mon-DD-YYYY.\n';}else if(tmpc.length<2){tmpc='0'+tmpc;field.value=tmpa+'-'+tmpc+'-'+tmpb;}}}}}
else if(jscall.indexOf('isfloat')==0){if(field.value.length>0){if(jscall.indexOf('.')>0)var tmpa=jscall.substr(8); else var tmpa=2;var tmpb='';for(var tmpi=0;tmpi<tmpa;tmpi++)tmpb+='0';if(!isNaN(field.value)){if(field.value.indexOf('.')<0)field.value=field.value+'.'+tmpb;else{var tmpd=field.value.substr(0,field.value.indexOf('.'));var tmpc=field.value.substr(field.value.indexOf('.')+1) + tmpb;tmpc=tmpc.substr(0,tmpb.length);field.value=tmpd+'.'+tmpc;}}else{errors+='- '+shortname+' must be numeric floating point value.\n';}}}
}if(errors&&confalert!=1)alert('The following error(s) occured:\n'+errors);
document.returnValue=(errors=='');
if(confalert==1)return(errors=='');
}

