/* validateform.js
* Copyright 2005-2009 by Frank Koenen, Finkle Enterprises, LLC. All Rights Reserved.
*
* ---------------------------------------------------------------------------------------------
* 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: trim
*  Purpose:
*   strip off leading/trailing writespace from value.
*
*  Example:
*   trim
* --------------------------------------------------------------------
*  Function: lowercase
*  Purpose:
*   convert input field value into lower case
*
*  Example:
*   lowercase
* --------------------------------------------------------------------
*  Function: uppercase
*  Purpose:
*   convert input field value into upper case
*
*  Example:
*   uppercase
* --------------------------------------------------------------------
*  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.
*    s: allows the / (slash) char too.
*    b: allows the \ (back-slash) 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
*    A == both 1 and 2 are ok.
* 
*  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: (applies to #1 syntax)
*    A == must have area code
*    a == are code is optional
* 
*  United States syntax is in the formats:
*        123-123-1234
*            123-1234
*
*  European syntax:
*        52 833 217 62 69
* 
*  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: validipaddr
*  Purpose:
*  Checks that "field" only values 0-255 and dots, in a 4 octet value.
*  example: 10.10.10.10
* --------------------------------------------------------------------
*  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('trim')==0){field.value=field.value.replace(/^\s*/,'');field.value=field.value.replace(/\s*$/,'');}
else if(jscall.indexOf('lowercase')==0){field.value=field.value.toLowerCase();}
else if(jscall.indexOf('uppercase')==0){field.value=field.value.toUpperCase();}
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.substr(14).indexOf('b')>0&&field.value.charAt(tmpi)=='\\')&&!(jscall.substr(14).indexOf('s')>0&&field.value.charAt(tmpi)=='/')&&!(jscall.substr(14).indexOf('S')>0&&field.value.charAt(tmpi)==' ')&&!(jscall.substr(14).indexOf('U')>0&&field.value.charAt(tmpi)=='_')&&!(jscall.substr(14).indexOf('@')>0&&field.value.charAt(tmpi)=='@')&&!(jscall.substr(14).indexOf('d')>0&&field.value.charAt(tmpi)=='-')&&!(jscall.substr(14).indexOf('D')>0&&field.value.charAt(tmpi)=='.')&&!(jscall.substr(14).indexOf('C')>0&&field.value.charAt(tmpi)==',')&&!(jscall.substr(14).indexOf('A')>0&&field.value.charAt(tmpi)=='\'')){errors+='- '+shortname+' contains an invalid character.\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+' contains an invalid character.\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(!validateform_validphone(field.value,jscall.substring(6,7),jscall.substring(7,8),jscall.substring(8,9)))errors+='- '+shortname+' must be a valid phone number.\n';else field.value=validateform_validphone(field.value,'SET');}
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('validipaddr')==0){if(validateform_validipaddr(field.value) != true && field.value.length > 0){errors+='- '+shortname+' is not a valid IP Address.\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=='');
}

function validateform_validipaddr(i){
 var r=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
 if(r.test(i)){var p=i.split(".");if(parseInt(parseFloat(p[0]))==0){return false;}for(var i=0;i<p.length;i++){if(parseInt(parseFloat(p[i]))>255){return false;}}return true;}else{return false;}
}

function validateform_validphone( value , X , Y , Z ) {
 if(X=='SET'){ // TODO: this should return the international format for the number: +1 aaa 123 1234  US, and others.
  value=value.replace(/ */g,'');
  value=value.replace(/-*/g,'');
  value=value.replace(/\.*/g,'');
  return(value);
 }
 var eee=value;
 if(Y=='R'&&value.length==0)return(false);
 eee=eee.replace(/ */g,'');
 eee=eee.replace(/-*/g,'');
 eee=eee.replace(/\.*/g,'');
 if(eee.length==0) return( (Y=='R')?false:true ); // must have value (or not is okay)
 if(X=='1'||X=='A'){ // US
  for(i=0;i<eee.length;i++)if(!(((eee.charAt(i)>='0')&&(eee.charAt(i)<='9'))))return(false); // must be only numbers
  if(Z=='A'&&eee.length==10)return(true);
  if(Z=='a'&&(eee.length==7||eee.length==10))return(true);
  if(X!='A')return(false);
 }
 // TODO:
 // germany: phone: +49 7071 29 70336 or +49 7071 29 5114 (14/15 chars)
 // uk: phone: +44(0)7810 774672 
 // turkey: phone: 0090 532 3210411 (14 chars)
 // mexico: phone: 52 833 217 62 69 (this one i coded below, need to do the others above) (12 chars)
 // SEE: http://www.numberingplans.com/index.php?goto=guide&topic=E123 (E.123: Notation for national and international telephone numbers)
 // For the international numbering plan, the world has been devided into 9 area's. The general rule is that within each global region each country code starts with the same digit. Below you can find the general international numbering plan. Click on the digit to see the geographical map and all related country codes.
 // http://www.numberingplans.com/index.php?goto=guide&topic=international
 // +0  Not used, reserved
 // +1  North America, Caribbean
 // +2  African continent
 // +3  Europe
 // +4  Europe
 // +5  Central and South America
 // +6  Oceania, South Pacific
 // +7  Former USSR
 // +8  East Asia
 // +9  Middle East, South-West Asia
 if(X=='2'||X=='A'){ // European
  for(i=0;i<value.length;i++)if(!(((value.charAt(i)>='0')&&(value.charAt(i)<='9'))))return(false); // must be only numbers, first char. can be +, and can contain '(' and ')' chars.
  if(value.length==12||value.length==14)return(true);
  if(X!='A')return(false);
 }
 return(false);
}

