Verfasst von: bletra | 17. November 2009

JavaScript: Formularvalidierung

Die Validierung von Eingabefelder vor dem Abschicken eines Formulars an den Server, ist ein Standardanwendungsgebiet für JavaScript. Für eine Bestellung betrachten wir folgendes Formular (Design von Manuel Bieh):

Im einfachsten Fall gibt es Funktionen, die auf „nicht-leer“ überprüfen, lästige alert-Boxen hochpoppen lassen und bei dem ersten Fehler mit der Validierung aufhören. So hangelt man sich von Fehler zu Fehler, bis man das Formular richtig ausgefüllt hat. Fehlermeldungen sind auch schnell weggeklickt, ohne dass man speichert, was doch gleich zu korrigieren war. Daher gehen wir das Problem mit folgenden Verbesserungen an:

1. Alle Fehler werden gesammelt ausgegeben.

2. Die Fehlermeldungen werden dynamisch in den HTML-Code eingfügt.

3. Zur Validierung werden reguläre Ausdrücke verwendet (gibt es gut bei http://www.regular-expressions.info/).

Der Code orrientiert sich stark an http://www.usability.com.au/resources/wcag2/form7.html

zu 1:

Alle Validierungsfunktionen werden aufgerufen und erst dann wird die Fehlermeldung eingefügt und wahr oder falsch zurückgegeben.

zu 2:

In einem Array werden die Fehler gesammelt. Die Inhalte werden abschließend durch ShowErrors ausgegeben. Ändert sich der Inhalt, dann fangen viele Screenreader an, den Inhalt der Seite von Anfang an vorzulesen. Insgesamt ergeben sich aus der Barrierefreiheit folgende Anforderungen:

  • Alle Fehlermeldungen werden in einem Schritt dem DOM – als ein Kindknoten –  hinzugefügt.
  • Die Überschrift der Fehlermeldung ist ein Link – um in der Linkliste zu erscheinen.
  • Jede Fehlermeldung enthält einen Link zu dem zu korrigierenden Eingabefeld.
  • Ein Klick auf eine konkrete Fehlermeldung setzt den Fokus auf das zugehörige Eingabeelement (JavaScript im onclick).

Konkret brauchen wir einen Container um das ganze Formular, in das wir vor das Formular einen Knoten mit den Fehlermeldungen einsetzen. Zur Vereinfachung verwenden wir die Funktion newElement(tag, attributes, text), die uns ein DOM-Knoten erzeugt – ohne ihn in das Dokument einzufügen.

function newElement(tag, attributes, text) {
  var element = document.createElement(tag);
  if (attributes!= null && attributes!= 'undefined') {
    for (var i in attributes) {
      element.setAttribute(i,attributes[i]);
    }
  }
  if (typeof text == 'string') {
    element.appendChild(document.createTextNode(text));
  }
  return element;
}

Die zu validierenden Felder definieren wir mit den zugehörigen regulären Ausdrücken in einem globalen Array:

var validationConfig = [
      {ref:'name',datamask:/^[a-z]+$/i,msg:'Der Name ist erforderlich.'},
      {ref:'street',datamask:/^[a-z]+$/i,msg:'Die Straße ist erforderlich.'},
      {ref:'plz',datamask:/^[0-9]{5}$/,msg:'Die Postleitzahl muss fünfstellig sein.'},
      {ref:'city',datamask:/^[a-z]+$/i,msg:'Die Stadt ist erforderlich.'},
      {ref:'email',datamask:/^[\w\.-]+@[a-z0-9-\.]+\.[a-z]{2,6}$/i,msg:'Die eingegebene E-Mail Adresse ist nicht gültig.'}
    ];

Die Funktion validate durchläuft dieses Array. Die Indizes fehlerhafter Eingabefelder werden gespeichert. Im Fehlerfall wird ShowErrors aufgerufen und falsch zurück gegeben, so dass das Formular nicht abgeschickt wird.

function validate() {
    var errorIndices = [];
  for (var i in validationConfig) {
    var inputField = document.getElementById(validationConfig[i].ref)
    if (!validationConfig[i].datamask.test(inputField.value)) {
      errorIndices[errorIndices.length] = i;
    }
  }
  if (errorIndices.length > 0) {
    ShowErrors(errorIndices);
    return false;
  }
  return true;
}

Nun müssen die Fehlermeldungen noch geeignet erzeugt und in das Dokument eingefügt werden.

function ShowErrors(errorIndices) {
  var container, errorMsg, el, ol, li, anchor;
  container = document.getElementById('formContainer');
  // we might have to reset the error messages
  if  (document.getElementById('errorMessage')) {
    container.removeChild(document.getElementById('errorMessage'));
    var inputs = document.getElementsByTagName('input');
    for (i = 0;i < inputs.length;i++) {
      if (inputs[i].className == 'error')
        inputs[i].className = '';
    }
  }
  //create error intro
  errorMsg = newElement('div',{id:'errorMessage'});
  el = newElement('h2');
  el.appendChild(newElement('a',{id:'errorName',name:'errorName',href:'#'},'Das Formular kann leider nicht versendet werden, bitte korrigieren Sie folgende Fehler:'));
  errorMsg.appendChild(el);
  ol = newElement('ol');
  //add the errors
  for (var i = 0; i<errorIndices.length; i++) {
    el = newElement('li');
    anchor = newElement('a',{href:'#'+validationConfig[errorIndices[i]].ref},validationConfig[errorIndices[i]].msg);
    anchor.onclick = function(){document.getElementById(this.href.split('#')[1]).focus();return false;};
    el.appendChild(anchor);
    ol.appendChild(el);
    if (document.getElementById(validationConfig[errorIndices[i]].ref))
      document.getElementById(validationConfig[errorIndices[i]].ref).className = 'error';
  }
  errorMsg.appendChild(ol)
  //add everything at once to avoid confusing rereading of some screenreaders.
  container.insertBefore(errorMsg,container.getElementsByTagName('form')[0]);
  document.getElementById('errorName').focus();
}

Erläuterung:

  • Zeile 6:  Entfernt die Knoten mit einleitendem Text und detaillierten Fehlermeldungen.
  • Zeilen 7-11:  Entfernt für alle Eingabefelder das class-Attribut, so dass der Hintergrund beispielsweise nicht mehr rot ist.
  • Zeile 23: Bei Klick auf den Link soll der Fokus auf das Eingabeelement gesetzt werden. Das href-Attribut hat die Form: #id, z.B. für das Feld mit id=“name“ ist href=“#name“. Mit Split erhalten wir das Array („“,  „name“). Wir brauchen das 1. Element und setzten den Fokus darauf. Es wird falsch ausgeführt, um das eigentliche Klick-Event auf den Link zu unterdrücken.

Die Wiederverwendbarkeit und Definition geeigneter Objektschablonen ist Thema des nächsten Artikels.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Kategorien

%d Bloggern gefällt das: