Inputkontroll Regexp
Børre Stenseth
Moduler>JavaScript>Inputkontroll

Inputkontroll

Hva
Kontroll, validering av brukerinput

En fornuftig bruk av JavaScript er kontroll eller validering av det brukeren skriver inn i inputfelter (text, textarea) før det sendes til tjeneren. Typiske kontroller kan være:

  1. Kontroll av om et felt er utfylt. Dette er som regel greitt å finne ut av.
  2. Kontroll av om et felt har riktig syntaks. Bare siffere, bare bokstaver, riktig antall siffere eller bokstaver. Dette skaper heller ikke store problemer.
  3. Riktig format i henhold til en mer presis syntaksbeskrivelse, f.eks. en dato. Dette kan være mer komplisert men bruk av regulære utttrykk kan hjelpe oss langt på vei. Javascript støtter dette.(mer om dette nedenfor)
  4. At feltene er fornuftige i forhold til hverande. Dette kan være enkelt, men det kan også bli kanske komplisert og tungvindt å løse i JavaScript.
  5. At dataene er lovlige gitt en bestemt situasjon. Dette avhenger helt av situasjonen. "lovlig" i denne sammenheng kan bety så mangt. F.eks. Kan det være greitt å teste om en dato har rett format, men det kan hende vi må konsultere en database eller en annen datakilde for å sjekke om den angitte datoen i f.eks. en bestillingssituasjon er ledig eller effektiv.

Det er trolig en god leveregel å finne en fornuftig balanse mellom det som med rimelighet kan skrives i JavaScript på klienten og det som med fordel kan løses på tjeneren. Vi kan kanskje si at det er rinmelig å foreta syntakskontroller på klienten og logiske kontroller på tjeneren.

Vi må også tenke gjennom hvordan og når vi skal gi tilbakemelding til brukeren om at noe er galt eller mangelfullt. Begivenhetsstyrt DOM-programmering er nøkkelen til dette.

Et enkelt eksempel

Vi begynner med et enkelt eksempel som ikke stiller store krav til selve kontrollen, valideringen. Hensikten er å se litt på organisering og rekkefølge. Vi tar for oss en situasjon der brukeren inviteres til å angi en 4-siffret tallkode og en tekst med 3 bokstaver.

Registrer dine data
Tall:(4 siffer)
Tekst:(3 bokstaver)

Strategien er at vi skriver og kaller tre funksjoner slik:

  • controlnumber(). Denne kalles når sifferfeltet mister fokus, begivenheten onblur. Denne setter opp en feilmelding og returnerer false dersom noe er galt i sifferfeltet, ellers true.
  • controlalfa(). Denne kalles når bokstavfeltet mister fokus, begivenheten onblur. Denne setter opp en feilmelding og returnerer false dersom noe er galt i bokstavfeltet, ellers true.
  • controlboth(). Denne kalles når vi trykker på Registrer-knappen, begivenheten onsubmit, og kaller de to andre funksjonene. Denne returnerer false dersom en av de to andre returnerer false, ellers true.
function controlnumber()
{
  inputelt=document.getElementById('number');
  errorelt=document.getElementById('numbererror');
  if ((inputelt.value==null) || (inputelt.value.length!=4))
  {
    errorelt.innerHTML='4 siffere';
    return false;
  }
  var legals = "0123456789";
  var T=inputelt.value;
  for (i = 0; i != T.length; i++)
    if (legals.indexOf(T.charAt(i)) == -1)
    {
      errorelt.innerHTML='bare siffere';
      return false;
    }
  errorelt.innerHTML='';
  return true;
}

function controlalfa()
{
  inputelt=document.getElementById('alfa');
  errorelt=document.getElementById('alfaerror');
  if ((inputelt.value==null) || (inputelt.value.length!=3))
  {
    errorelt.innerHTML='3 bokstaver';
    return false;
  }
  var legals = "abcdefghijklmopqrstuvwxyzæøå";
  var T=inputelt.value;
  T=T.toLowerCase()
  for (i = 0; i != T.length; i++)
    if (legals.indexOf(T.charAt(i)) == -1)
    {
      errorelt.innerHTML='bare bokstaver';
      return false;
    }
  errorelt.innerHTML='';
  return true;
}
function controlboth(){
  if (!controlalfa())
    return false;
  if (!controlnumber())
    return false;
  return true;
}

Den aktuelle HTML-koden er som nedenfor. Det kan virke litt overdrevet med table, men hensikten er å ordne de tre komponentene inledningstekst, selve inputfeltet og feilmeldingen.

<fieldset>
<legend>Registrer dine data</legend>
<form onsubmit="javascript:return controlboth();"
      action="http://www.it.hiof.no/~borres/cgi-bin/forms/scriptvalidate1.py"
      method="post">
 <table class="normal">
 <tr>
  <td>Tall:(4 siffer)</td>
  <td><input id="number" name="siffere" onblur="controlnumber()"
      type="text" value="" maxlength="4" size="10"/></td>
  <td id="numbererror" style="color:red">  </td>
 </tr>
 <tr>
  <td>Tekst:(3 bokstaver)</td>
  <td><input id="alfa" name="bokstaver" onblur="controlalfa()"
      type="text" value="" maxlength="3" size="10"/></td>
  <td id="alfaerror" style="color:red">  </td>
 </tr>
 <tr>
  <td>  </td>
  <td><input type="submit" value="Registrer"/></td>
  <td>  </td>
 </tr>
 </table>
</form>
</fieldset>

Merk onsubmit i form-elementet. Dersom controlboth() returnerer false dreper vi submitforsøket.

Et eksempel til

Vi lager et eksempel til der vi bruker regulæruttrykk for å validere input.

Registrer dato
Dato:(åååå:mm:dd)

Den aktuelle JavaScript-funksjonen ser slik ut:

function controldato()
{
  inputelt=document.getElementById('dato');
  errorelt=document.getElementById('datoerror');
  if ((inputelt.value==null) || (inputelt.value.length!=10))
  {
    errorelt.innerHTML='galt format';
    return false;
  }
  var T=inputelt.value;
  var regex=/(19|20)\d\d[:](0[1-9]|1[012])[:](0[1-9]|[12][0-9]|3[01])/;
  if (regex.test(T))
  {
    errorelt.innerHTML='';
    return true;
  }
  errorelt.innerHTML='galt format';
  return false;
}

Vi ser at vi har brukt regulære uttrykk, regex-objektet, til å teste formatet. Vi kunne gjort dette med ren string-programmering (split, lengde kontroll osv), men den løsningen som er valgt er vesentlig smidigere.

Den aktuelle HTML-koden er etter mønster av forrige eksempel slik:

  <fieldset>
  <legend>Registrer dato</legend>
  <form onsubmit="javascript:return controldato();"
        action="http://www.it.hiof.no/~borres/cgi-bin/forms/scriptvalidate2.py"
        method="post">
   <table class="normal">

   <tr>
    <td>Dato:(åååå:mm:dd)</td>
    <td><input id="dato" name="dato" onblur="controldato()"
        code="text" value="" maxlength="10" size="11"/></td>
    <td id="datoerror" style="color:red"></td>
   </tr>

   <tr>
    <td></td>
    <td><input code="submit" value="Registrer"/></td>
    <td></td>
   </tr>

   </table>
  </form>
  </fieldset>

Nå har vi laget en ren syntakskontroll av datoformatet.

var regex=/(19|20)\d\d[:](0[1-9]|1[012])[:](0[1-9]|[12][0-9]|3[01])/;

Løsningen har noen svakheter. F.eks. vil 2006:02:31 passere syntakskontrollen selv om det er en dato som ikke finnes. På den annen side vil 1889:02:01 feile siden regulæruttrykket vårt bare aksepterer datoer på 1900 og 2000 tallet.

La oss anta at vi bare er intresserte i datoer på 1900 og 2000 tallet.

Det andre problemet, altså å fange opp problemer av typen 2001:02:31, kan vi løse på flere måter. Vi kan utvide regex-uttrykket og fange det opp der eller vi kan skrive string-kode. Vi prøver det siste, og lage følgende funksjoner:

function controldatox()
{
  inputelt=document.getElementById('datox');
  errorelt=document.getElementById('datoerrorx');
  if ((inputelt.value==null) || (inputelt.value.length!=10))
  {
    errorelt.innerHTML='galt format';
    return false;
  }
  var T=inputelt.value;
  var regex=/(19|20)\d\d[:]\d\d[:]\d\d/;
  if (regex.test(T))
  {
    if(checkdato(T))
    {
      errorelt.innerHTML='';
      return true;
    }
    else
    {
      errorelt.innerHTML='datoen eksisterer ikke';
      return false;
    }
  }
  errorelt.innerHTML='galt format eller galt årstall';
  return false;
}
function checkdato(s){
  var strArray=s.split(":");
  y=parseInt(strArray[0]);
  m=parseInt(strArray[1]);
  d=parseInt(strArray[2]);
  if ((m==1)||(m==3)||(m==5)||(m==7)||(m==8)||(m==10)||(m== 12))
  {
      return (d <= 31);
  }
  else if ((m==4)||(m==6)||(m==9)||(m==11))
  {
      return (d <= 30);
  }
  else if (m == 2)
  {
      if (d <= 28)
          return true;
      if (d > 29)
          return false;
      // d==29
      if ((y % 4 == 0) && (y % 100 != 0))
          return true;
      return false;
  }
  else
    return false
}

Test denne:

Registrer dato
Dato:(åååå:mm:dd)

Et mer komplisert eksempel

Utgangspunktet er at brukeren ønsker å endre sitt passord. Det gjøres ikke annet enn lengdekontroll på brukernavnet og det gamle passordet.

Change Your password

Old password and username

Username
Current password

New passwords must consist of a mix of upper and lower size letters, characters and numbers according to the following rules
  1. The password must contain at least 8 characters
  2. The first 8 characters must satisfy at least three out of four of the following subrules:
    1. At least one character is lowercase (a-z)
    2. At least one character, except the first, is uppercase (A-Z)
    3. At least one character, except the eigth, is a digit (0-9)
    4. At least one character, except the eigth, is a special character (|!"#¤%/()=?*,;.:)
  3. The password must not contain language specific characters such as æøåÆØÅïÔ etc.
New password
Confirm password

For security reasons the data sent from this page should be encrypted when transfered to the server. This is not the case in this demo.

_javascriptet
Referanser
  1. RegulæruttrykkRegular-Expressions.infowww.regular-expressions.info/14-03-2010
  1. Regular expression generatortxt2re.com/14-10-2010

Pythonskriptene som gir respons

  • scriptvalidate1
  • scriptvalidate2
Vedlikehold

B.Stenseth, mai 2006

(Velkommen) Moduler>JavaScript>Inputkontroll (Popup)