// ------------------------------------------------
// TELEform HTML+Forms
// JScript Interactive Client-Side Validation 
// Cardiff Software,Inc. (http://www.cardiff.com)
// Copyright(c)1991-2002, All Rights Reserved.
// ------------------------------------------------
// Instant Client-Side Validation

var cNumeric  =1;
var cAlpha    =2;
var cSpecial  =4;
var cStrict   =8;
var CUpper    =256;

//
// BOOL scriptEnabled() 
// checks if the browser can handle scripts (Mozilla/3 or MSIE 3)
//
function scriptEnabled() {
  while(true){
    if (is_nav5up)  return(true);
    if (is_ie4up)   return(true);
    if (is_ie3)   return(true);
    if (is_nav3)  return(true);
    if (is_nav4)  return(true);
    continue;
  }
  return false;
}

//
// -- define object fieldAttr --
//
function fieldAttr(sName,sType,nSet,bReq,bRng,nSize,sTmpl,rFrom,rTo,sNice,sEntryChars){
  if (bReq>1) bReq=0; // range: 0..1
  if (bRng>1) bRng=0; // range: 0..1
  if ((nSet & CUpper) == CUpper) {
    this.bUpper =true;
    nSet &= ~CUpper;
  }
  if (nSet>9) nSet=0; // range: 0..9
  this.sName=sName; // "un-mangled" name of this field
  this.sType=sType; // field type
  this.nSet =nSet;  // allowed char set
  this.bReq =bReq;  // input required?
  this.bRng =bRng;  // input range specified?
  this.nSize=nSize; // max num of char.
  this.sTmpl=sTmpl; // template
  this.rFrom=rFrom; // range from
  this.rTo  =rTo;   // range to
  this.sNice=sNice; // filed name to appear in error msgs
  this.sEntryChars=sEntryChars; // legal character in Entry Field 
} 

//
// -- define global variables --
//
var objs    =new fieldContainer();
var msgs    =new messageTable();
var dts     =new dateTempls();
var bError    =false;   // error detected
var bCheckAll   =false;   // final checking mode afer submit was pressed
var bScript   =scriptEnabled(); // browser supports client scripting
var sAlphaSet ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzƒŠŒšœŸÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ";
var sNumSet   ="0123456789";
var sNuSpSet    ="-.,";   // these are Numeric and Special Characters
var sAllSet   =" \r\n";   // these are Num., Alpha, and Special Chars 
var sDateSeps   ="/.-,:|_ ";
var sStatusMsg    ="";    // message for status bar
var fBlur   =null;    // last blurred field
var fFocusTo    =null;    // focus after validation
var timer   =null;

// VOID clrWndStatus()
// clears the statusbar
//
function clrWndStatus(){
    window.status="";
    return;
}

//  formatMsg(fmt,arg,arg2,...)
//
//  Allows us to have message strings with substitution (%s) so strings can be
//  internationalized better.
//
function formatMsg(){
  var msg   ="";
  if (arguments.length==0) {
    return msg;
  }
  var argnum  =1;
  var fmt   =arguments[0];
  for (i=0;i<fmt.length;i++){
    if (i+1<fmt.length && fmt.substr(i,2)=="%s") {
      if (argnum<arguments.length){
        msg+=arguments[argnum];
        argnum++;
      }
      i++;
    } else {
      msg+=fmt.charAt(i);

    }
  }
  return msg;
} 

//  BOOL msgBox()
//
//  Clear status bar while box is up, event handler may run and change message
//  During submit user can't cancel validation message.
function msgBox(msg){
  window.status="";
  var   ret = true;
  if (bCheckAll){
    alert(msg);
  } else {
    ret = confirm(msg);
  }
  window.status=sStatusMsg;
  return ret;
}

//  focusHack()
//
//  Needed for Netscape 6
//
function focusHack() {
    fFocusTo.focus();
    fFocusTo.select();
    clearTimeout(timer);
}


//  BOOL canFocusInBlur()
//
//  Netscape doesn't like to have focus set in OnBlur or OnFocus events.
//
function canFocusInBlur(){
  return is_ie || is_nav5up;
}

//  BOOL focusable()
//
//  can focus be set to field?
//
function focusable(theField){
  return isDateFld(theField) || isTextFld(theField);
}

//  BOOL isDateFld()
//
function isDateFld(theField){
  return (objs[theField.name].sType=="Date");
}

//  BOOL isTextFld()
//
function isTextFld(theField){
  return (objs[theField.name].sType=="Text");
}

function icompare(s1,s2)
{
  return s1.toUpperCase() == s2.toUpperCase();
}


// FLOAT getFloat(theField)
// check for a valid float entry
// set the global bError variable
// return floating point number
//
function getFloat(theField){
  var   checkOK  =sNumSet+sNuSpSet;
  var   checkStr =theField.value;
  var   decPoints=0;
  var   allNum   ="";
  bError  =false;
  for (var i=0;i<checkStr.length;i++){
    var ch= checkStr.charAt(i);
    for (var j=0;j<checkOK.length;j++)
      if(ch==checkOK.charAt(j))break;
    if(j==checkOK.length) { bError= true; break;}
    if(ch==".") {
      allNum+=".";
      decPoints++;
    } else if(ch!=",") {
              allNum+=ch;
    }
      } // end for
      if(decPoints>1)bError=true;
      if(bError){return(0)};
      var   chkVal=allNum;
      var   prsVal=parseFloat(allNum);
      return(prsVal);
}

//
// VOID msgRequired(theField)
// assemble a message and tell in the statusbar that an input for this field is required 
//
function msgRequired(theField){
  return formatMsg(msgs.sRequired,objs[theField.name].sNice);
}

//
// VOID msgRange(theField)
// assemble a message and tell in the statusbar the allowed inputrange
//
function msgRange(theField){
  if (isDateFld(theField))
    return dateRangeMsg(theField) + " " + msgTempl(theField);

  return formatMsg( msgs.sRange, objs[theField.name].rFrom, objs[theField.name].rTo, objs[theField.name].sNice);
}

function msgTempl(theField){
  if (objs[theField.name].sTmpl.length > 3) {
    return "(" + getTempl(theField) + ")";
  } else {
    return "";
  }
}

function getTempl(theField){
  var templ  = "";
  var start  = objs[theField.name].sTmpl.indexOf(":");
  if (start != -1) {
    start++;
    templ = objs[theField.name].sTmpl.substr(start,objs[theField.name].sTmpl.length - start);
  }

  return templ;
}


//
// BOOL validateRequired(theField)
// tell in a msgbox that an input for this field is required
// return true if condition was met
//
function validateRequired(theField){
      if (theField.value==""){
  if (msgBox(msgRequired(theField)))
    return false;
  }
  return true;
}

//
// BOOL validateRadio(theField)
// tell in a msgbox that an input for those Radiobuttons is required
// return true if condition was met
//
function validateRadio(theField){
  for(var i=0;i<theField.length;i++){
    if (theField[i].checked)
    return true;
    }
  return false;
}

//
// BOOL validateChrSet(theField)
// tell in a msgbox the allowed character set
// 0-none    1-num       2-alpha        3-alphaNum 4-spcl
// 5-numSpcl 6-alphaSpcl 7-alphaNumSpcl 8-strict   9-strictNum
// 10-EntryField
// return true if condition was met
//  
  function validateChrSet(theField){
    var checkStr=theField.value;
    var nSet=objs[theField.name].nSet;
    var bValid=true;
    if((nSet<cNumeric)||(nSet>=(cNumeric+cAlpha+cSpecial+cStrict))){ 
      return(bValid);
    }
    for(var i=0;i<checkStr.length;i++){ //check entered characters 
      var ch=checkStr.charAt(i);
      var itemOf=0;
      var j=0;
      // check to which char.set ch belongs
      // handle multiset characters first
      if(itemOf==0){ // ch itemOf AllSet?
        for(j=0;j<sAllSet.length;j++){
          if(ch==sAllSet.charAt(j)){
            itemOf=cNumeric+cAlpha+cSpecial;
            break;
          }
        }//end for(j)
    }
      if(itemOf==0){ // ch itemOf NuSpSet?
        for(j=0;j<sNuSpSet.length;j++){
          if(ch==sNuSpSet.charAt(j)){
            itemOf=cNumeric+cSpecial;
            break;
          }
        }//end for(j)
    }
      if(itemOf==0){ // ch itemOf NumSet ?
        for(j=0;j<sNumSet.length;j++){
          if(ch==sNumSet.charAt(j)){
            itemOf=cNumeric;
            break;
          }
        }//end for(j)
      }
      if(itemOf==0){ // ch intemOf AlphaSet ?
        for(j=0;j<sAlphaSet.length;j++){
          if(ch==sAlphaSet.charAt(j)){
            itemOf=cAlpha;
            break;
          }
        }//end for(j)
      }
      if((itemOf==0)&&(checkStr.length>0)){
        itemOf=cSpecial;
      }
      if(!(itemOf & nSet)){
        bValid=false;
        break;
      }
      if(!(itemOf & ~(cAlpha | cNumeric)) && objs[theField.name].sEntryChars.length > 0) {
        if (objs[theField.name].sEntryChars.indexOf(ch) == -1) {

          bValid=false;
          nSet+=10;
          break;
  }
      }
    } //end for(i)
    if(!bValid){
      var sUsing = "";
      if (nSet > 10) {
        // Entry field. Validate specific characters.
        var sTmplChars = "";
  var start = 0;
  if (objs[theField.name].sTmpl.length > 3 && objs[theField.name].sTmpl.charAt(1) == "i") {
    for(j=0;j<sNuSpSet.length;j++){
      if(getTempl(theField).indexOf(sNuSpSet.charAt(j)) != -1){
        sTmplChars += sNuSpSet.charAt(j);
      }
    }
        }
        sUsing = " " + "Use characters" + " (" + objs[theField.name].sEntryChars + sTmplChars + ") ";
        nSet -= 10;
        if (nSet == 5 || nSet == 6) {
          nSet = 7;
        }
      }
  var msg = "";
  switch(nSet){
  case 1:  
    msg = formatMsg(msgs.sChrSet1,objs[theField.name].sNice);
    break;
  case 2:  
    msg = formatMsg(msgs.sChrSet2,objs[theField.name].sNice);
    break;
  case 3:  
    msg = formatMsg(msgs.sChrSet3,objs[theField.name].sNice);
    break;
  case 4:  
    msg = formatMsg(msgs.sChrSet4,objs[theField.name].sNice);
    break;
  case 5:  
    msg = formatMsg(msgs.sChrSet5,objs[theField.name].sNice);
    break;
  case 6:
    msg = formatMsg(msgs.sChrSet6,objs[theField.name].sNice);
    break;
  case 7:
    msg = formatMsg(msgs.sChrSet7,objs[theField.name].sNice);
    break;
  default:
    msg = formatMsg(msgs.sNotValid,objs[theField.name].sNice);
  }
  msg += sUsing;
  bValid=!msgBox(msg);

    } else {
      if(cStrict & nSet){
        var dummy=getFloat(theField);
        if(bError){
          bError=false; // reset bError because user gets notified
          bValid=!msgBox(formatMsg(msgs.sNotValid,objs[theField.name].sNice));
        }
      }
    }

    return(bValid);
  }

//
// BOOL validateRange(theField) called by handleBlur()
// assemble a msg. and tell in a msgbox the allowed inputrange
//
function validateRange(theField){
    var ret=true;
    if (isDateFld(theField)){
  return true; // handled in padDate()
    }
    if (theField.value!=""){
      var r0=objs[theField.name].rFrom;
      var r1=objs[theField.name].rTo;
      var v =getFloat(theField); // set bError 
      if (!bError){
        if ((v<r0)||(v>r1)) 
          bError=true;
      }
      if(bError){
        bError=false;  // reset bError because user gets notified
        ret=!msgBox(msgRange(theField));
      }
    }
    return ret;
}


//  VOID handleFocus()
//
//  EVENT-Handler for onFocus()event
//  tell something in the statusbar or clear it
//
function handleFocus(theField){

  if (bCheckAll) return; // submit pressed
  var focusOk=true;
  if (fBlur != null && fBlur != theField) {
    focusOk=checkField(fBlur,theField);
    if (!focusOk && canFocusInBlur() && focusable(fBlur)) {
      // focus was set back to previous field
      return;
    }
    fBlur=null;
  }
  if(objs[theField.name]!=null){
    fBlur=theField;
  }

  if(objs[theField.name]==null)
    return;
  if(objs[theField.name].bRng==1)
    sStatusMsg=msgRange(theField);
  else if(objs[theField.name].sTmpl.length > 0)
    sStatusMsg=msgTempl(theField);    
  else if(objs[theField.name].bReq==1)
    sStatusMsg=msgRequired(theField);
  else
    sStatusMsg="";
  window.status = sStatusMsg;
   
  return;
}

function checkField(theField,newField){
 
  var ret=true;
  if(!bScript)    return ret;
  if(window.closed) return ret;
  
  var bOK=true;
  sStatusMsg="";
 
  if (objs[theField.name].bUpper) {
    theField.value = theField.value.toUpperCase( );
  }
  if (isDateFld(theField)){
    bOK=padDate(theField);
  }
      if(bOK)
    if(objs[theField.name].nSet>0) // show err.msg
      bOK=validateChrSet(theField);
      if(bOK)
          if(objs[theField.name].bRng==1) // show err.msg
            bOK=validateRange(theField);
      if(bOK)
          if(objs[theField.name].bReq==1) // show err.msg
            bOK= validateRequired(theField);
  if (!bOK){
    if (focusable(theField)){
      if (canFocusInBlur()  || bCheckAll) {
        if (newField != null) 
          newField.blur();
        //theField.focus();
        // NS6 workaround
        fFocusTo = theField;
        timer=setTimeout( "focusHack();", 0 ); 
      }
    }
    ret=false;
  } else {
    bError=false;
  }
  return ret;
}

function includeTemplChars(theField)
{
  return objs[theField.name].sTmpl.length < 2 || objs[theField.name].sTmpl.charAt(1)=="i";
}

//  Stript template characters when needed.
//  Currently only implemented for Date types
//
function stripTempl(theField)
{
  if (includeTemplChars(theField))
    return;

  if (isDateFld(theField)){
    var checkStr="";
    for(var i=0;i<theField.value.length;i++){ //check entered characters 
      var ch = theField.value.charAt(i);
      if (sDateSeps.indexOf(ch) == -1)
        checkStr += ch;
    }
          theField.value=checkStr;
  }
}

function DateObj()
{
  this.day    = "";
  this.month  = "";
  this.year   = "";
  this.sSep   = "/";
  this.flds   = new Array();
  this.bValid = false;

  return;
}
  DateObj.prototype.isValid   = function()
  {
    return this.bValid;
  }

  DateObj.prototype.compare   = function(compDate)
  {
    if (this.year > compDate.year)    return  1;
    else if (this.year < compDate.year)   return -1;
    else if (this.month > compDate.month)   return  1;
    else if (this.month < compDate.month)   return -1;
    else if (this.day > compDate.day)   return  1;
    else if (this.day < compDate.day)   return -1;
    else          return  0;
  }

  DateObj.prototype.parseMilMonth   = function(sMon)
  {
    var nRet = 1;
    for (i=0;i< dts.Months.length;i++){
      if (icompare(sMon,dts.Months[i])) {
        nRet = i+1;
        break;
      }
    }
    return nRet.toString();
  }

  DateObj.prototype.getMilMonth   = function(nMon)
  {
    var s = dts.Months[0];
    if (nMon >0 && nMon <=12) s = dts.Months[nMon - 1];
    return s;
  }


  DateObj.prototype.parseTempl  = function(sTmpl)
  {
    var dateFld = 0;
    this.flds[0]  = "";
    for (i=0;i<sTmpl.length;i++){
      var ch = sTmpl.charAt(i);
      // Remember, MMDDYY may be other letters when translated
      if (sDateSeps.indexOf(ch) != -1){
        dateFld++;
        this.flds[dateFld] = "";
        this.sSep = ch;
      } else {
        this.flds[dateFld] += ch;
      }
    }
  }

  DateObj.prototype.parseInput  = function(theField)
  {
    this.parseTempl( getTempl(theField) );
    this.parseDate(theField.value);
  }

  DateObj.prototype.parseDate   = function(sInStr)
  {
    var segs  = new Array();
    var dateFld = 0;
    
    this.day  = "";
    this.month  = "";
    this.year = "";
    segs[0]   = "";
    this.bValid   = false;
    for (var i=0;i<sInStr.length;i++){
      var ch = sInStr.charAt(i);
      if (sDateSeps.indexOf(ch) != -1){
        dateFld++;
        segs[dateFld] = "";
      } else {
        segs[dateFld] += ch;
      }
    }

    if (segs.length == 1 && segs[0].length > 2) {
      //  Whoops, no separators. Try again.
      var segStart = 0;
      for(var i=0;i<this.flds.length;i++) {
        var segLen   = this.flds[i].length;
        segs[i] = sInStr.substr(segStart,segLen);
        segStart += segs[i].length;
      }
    }

    for(var i=0;i<this.flds.length;i++) {
      var seg = (segs.length > i) ? segs[i] : "0";
      if (this.flds[i] == dts.MM) {
        this.month = this.formatFld( seg, 2 );
      } else if (this.flds[i] == dts.MMM) {
        this.month = this.formatFld( this.parseMilMonth(seg), 2 );
      } else if (this.flds[i] == dts.DD) {
        this.day   = this.formatFld( seg, 2 );
      } else if (this.flds[i] == dts.YYYY || this.flds[i] == dts.YY) {
        this.year  = this.formatFld( seg, 4 );
      }
    }

    this.bValid = this.day > 0 && this.day <=32 && this.month > 0 && this.month <= 12 && this.year >= 0;

  }


  DateObj.prototype.format  = function()
  {
    var sDate = "";
    for(var i=0;i<this.flds.length;i++) {
      if (i != 0) {
        sDate += this.sSep;
      }
      if (this.flds[i] == dts.MM) {
        sDate += this.formatFld(this.month,2);
      } else if (this.flds[i] == dts.MMM) {
        sDate += this.getMilMonth(this.month);
      } else if (this.flds[i] == dts.DD) {
        sDate += this.formatFld(this.day,2);
      } else if (this.flds[i] == dts.YY) {
        sDate += this.formatFld(this.year,2);
      } else if (this.flds[i] == dts.YYYY) {
        sDate += this.formatFld(this.year,4);
      }
    }
    return sDate;
  }

  DateObj.prototype.formatFld   = function(inFld,len,bMil)
  {
    var outFld = "";
    if (inFld.length > len) {
      outFld = inFld.substr(inFld.length - len, len);
    } else if (inFld.length < len) {
      if (len == 4 && inFld.length <= 2) {
        outFld += (inFld < "30") ? "20" : "19";
      }
      while (outFld.length + inFld.length < len) {
        outFld += "0";
      }
      outFld += inFld;
    } else {
      outFld = inFld;
    }
    return outFld;
  }


function dateRangeMsg(theField,rngLo,rngHi)
{
  var   sText = "";
  var stdTmpl = dts.YYYY + "-" + dts.MM + "-" + dts.DD;
  if (rngLo == undefined) {
    rngLo = new DateObj;
    rngLo.parseTempl( stdTmpl );
    rngLo.parseDate( objs[theField.name].rFrom );
  }
  if (rngHi == undefined) {
    rngHi = new DateObj;
    rngHi.parseTempl( stdTmpl );
    rngHi.parseDate( objs[theField.name].rTo );
  }

  rngLo.parseTempl( getTempl(theField) );
  rngHi.parseTempl( getTempl(theField) );
  sText = formatMsg( msgs.sRange, rngLo.format(), rngHi.format(), objs[theField.name].sNice);

  return sText;

}

function padDate(theField){
  var bOK = true;
  if (!isDateFld(theField)){
    return bOK;
  }

  if (theField.value.length > 0) {
    var date = new DateObj;
  
    date.parseInput(theField);
    theField.value= date.format();
    if (!date.isValid()) {
      if (msgBox(formatMsg(msgs.sDate,objs[theField.name].sNice) + " " + msgTempl(theField)))
        bOK = false;
    }
    
    if (bOK && objs[theField.name].bRng) {
      var stdTmpl = dts.YYYY + "-" + dts.MM + "-" + dts.DD;
      var rngLo = new DateObj;
      var rngHi = new DateObj;
      rngLo.parseTempl( stdTmpl );
      rngLo.parseDate( objs[theField.name].rFrom );
      rngHi.parseTempl( stdTmpl );
      rngHi.parseDate( objs[theField.name].rTo );
      if (date.compare( rngLo ) < 0 || date.compare( rngHi ) > 0) {

        if(msgBox(dateRangeMsg(theField,rngLo,rngHi))) {
          bOK = false;
        }
      }

    }
  }
  return bOK;
}


//
// BOOL EVENT handler for onSubmit()
// check that all required fields are filled
//
  function checkAll(theForm){
  fBlur     =null;
  bCheckAll =true;
  bError    =false;
  
  if(!bScript)
    return true;

    for(var i in objs){
      if((objs[i].nSet>0)||(objs[i].bReq==1)||(objs[i].bRng==1)){ 
        nFocus= objs[i].sName;  
        switch(objs[i].sType){  
  case "Text":
  case "Date":
    if(checkField(theForm[nFocus],null)){
      if(objs[i].sType=="Date") {
        stripTempl(theForm[nFocus]);
      }
    } else {
      bCheckAll=false;
    }
    break; 
        case "Radio":
          if(!validateRadio((theForm[nFocus]))){
            msgBox(formatMsg(msgs.sChoose,objs[i].sNice));
            bCheckAll=false;
          }
    break;
        case "Entry":
          if(!validateRadio((theForm[nFocus]))){
            msgBox(msgRequired(objs[i]));
            bCheckAll=false;
          }
    break;
      case "Select":
          var nSelIndex=theForm[nFocus].selectedIndex;
          if(nSelIndex<0){
            msgBox(formatMsg(msgs.sSelect,objs[i].sNice));
      bCheckAll=false;
            theForm[nFocus].focus();
            break;
          }
          if(theForm[nFocus].value == ""){
            msgBox(formatMsg(msgs.sOption,objs[i].sNice));
            bCheckAll=false;
            theForm[nFocus].focus();
            break;
          } 
        }   
        if (!bCheckAll) break; // Had error 
      } 
    } //endfor
    return bCheckAll;
  }

