Rheinwerk Computing <openbook>
Rheinwerk Computing - Programming the Net


JavaScript von Christian Wenz
Browserübergreifende Lösungen
JavaScript - Zum Katalog
gp Kapitel 7 Formulare I
  gp 7.1 Überprüfung auf Vollständigkeit
  gp 7.2 Automatische Überprüfung
  gp 7.3 Anwendungsmöglichkeiten für Formulare
  gp 7.4 Fragen & Aufgaben

Kapitel 7 Formulare I

Von allen Plagen, mit denen Gott der Herr unser Wirtschaftsleben heimsucht, ist die Bürokratie die weitaus schlimmste.
– Ephraim Kishon

Es gibt prinzipiell drei Einsatzgebiete für JavaScript: Grafische Effekte (Beispiele gibt es zum ersten Mal im Kapitel »Images I«), Navigationshilfen (zum Beispiel im Kapitel »Fenster II«) und echte Interaktion mit dem Benutzer. Interaktion bedeutet hier, dass der Benutzer etwas tut und die Webseite sich dementsprechend verändert. Sehr oft benutzt man hier HTML-Formulare. Das hat mehrere Gründe. HTML-Schaltflächen eignen sich vorzüglich, um JavaScript-Funktionen auszuführen, und in HTML-Eingabefeldern kann man Daten vom Benutzer abfragen. In diesem Kapitel soll es primär darum gehen, einen HTML-Fragebogen mit JavaScript-Funktionalität zu versehen.


Rheinwerk Computing

7.1 Überprüfung auf Vollständigkeit  downtop

Sie haben das garantiert schon einmal im World Wide Web gesehen: Wenn Sie sich bei einem Freemail-Dienst, einer Online-Community oder MyGalileo registrieren, müssen Sie einige persönliche Angaben machen. Die Betreiber der Website haben natürlich ein großes Interesse daran, dass das Formular vollständig ausgefüllt wird. Das kann serverseitig gelöst werden, was den Vorteil hat, dass die Überprüfung auch mit wirklich jedem Browser funktioniert. Die Nachteile liegen aber gleichzeitig auf der Hand. Nicht immer steht dem Programmierer eine serverseitige Programmiersprachen-Unterstützung zur Verfügung. Der Programmieraufwand ist hierbei recht hoch, denn es soll ja nicht nur eine Fehlermeldung ausgegeben werden, sondern wenn möglich das Formular auch noch mit den zuvor eingegebenen Daten dargestellt werden. Es wäre schon sehr ärgerlich für den Benutzer, wenn er ein Formular fast vollständig ausfüllt und aufgrund einer einzigen Auslassung das komplette Formular noch einmal ausfüllen müsste.

Mit JavaScript kann auch auf der Clientseite die Überprüfung auf Vollständigkeit durchgeführt werden. Damit wird keine neue Seite in den Browser geladen, die Formulardaten bleiben unangetastet, und der Benutzer kann sofort den Fehler korrigieren.

Im Folgenden finden Sie ein HTML-Formular, das ausschließlich aus Pflichtfeldern bestehen soll. Nach dem Anklicken der Absende-Schaltfläche soll die Funktion pruefen() aufgerufen werden, die überprüft, ob das Formular vollständig ausgefüllt wurde, und gegebenenfalls eine Fehlermeldung ausgibt. Diese Funktion wird in diesem Kapitel schrittweise erarbeitet. Vorab jedoch noch ein paar Hinweise, wie diese Funktion in das HTML-Dokument eingebunden wird.

Das <FORM>-Tag hat den Event-Handler onSubmit, der ausgelöst wird, sobald das Formular abgeschickt wird. Wie schon bei anderen Beispielen in diesem Buch kann hier ein altbekannter Trick angewandt werden. Beim Versenden des Formulars kollidieren wieder die HTML-Konsequenzen des Versendens (nämlich das Aufrufen einer anderen Seite) und die mit onSubmit zugeordneten JavaScript-Aktionen. Endet der onSubmit-Event-Handler jedoch auf return false, so wird die HTML-Aktion (das Aufrufen der anderen Seite) nicht ausgeführt; bei return true wird sie ausgeführt. Also hat der <FORM>-Tag in diesem Beispiel folgenden Aufbau:

<FORM ACTION="/cgi-bin/skript" NAME="Fragebogen" 
onSubmit="return pruefen()">

Die Funktion pruefen() gibt nur dann true zurück, wenn das Formular vollständig ausgefüllt worden ist, ansonsten false. Somit ist sichergestellt, dass nur vollständige Formulare verschickt werden – sofern der Browser des Benutzers JavaScript unterstützt und es auch aktiviert hat. Ältere Browser oder solche mit ausgeschaltetem JavaScript ignorieren den Skriptteil komplett und versenden das Formular direkt.

<HTML>
<HEAD>
<TITLE>Formular-Überprüfung</TITLE>
<SCRIPT><!--
function pruefen(){
   // ... kommt noch
   return true
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Anmeldeformular</H3>
<FORM ACTION="/cgi-bin/skript" NAME="Fragebogen" 
onSubmit="return pruefen()">
Vorname: <INPUT TYPE="TEXT" NAME="Vorname"><BR>
Nachname: <INPUT TYPE="TEXT" NAME="Nachname"><BR>
E-Mail-Adresse: <INPUT TYPE="TEXT" NAME="Email"><BR>
<INPUT TYPE="RADIO" NAME="Geschlecht" VALUE="m"> männlich |
<INPUT TYPE="RADIO" NAME="Geschlecht" VALUE="w"> weiblich<BR>
Welche Bücher von Galileo Press besitzen Sie?<BR>
<INPUT TYPE="CHECKBOX" NAME="Flash"> Flash | <INPUT TYPE="CHECKBOX"
  NAME="JavaScript"> JavaScript | <INPUT TYPE="CHECKBOX"
    NAME="InDesign"> InDesign<BR>
Welches der Bücher hat das schönste Cover?
 <SELECT NAME="Cover">
 <OPTION>Bitte wählen</OPTION>
 <OPTION VALUE="Flash">Flash</OPTION>
 <OPTION VALUE="JavaScript">JavaScript</OPTION>
 <OPTION VALUE="InDesign">InDesign</OPTION>
 </SELECT><BR>
<INPUT TYPE="SUBMIT" VALUE="Absenden"> <INPUT TYPE="RESET" VALUE
  "Formular löschen">
</FORM>
</BODY>
</HTML>
Abbildung 7.1  Das (noch) funktionslose Formular
Abbildung


Rheinwerk Computing

7.1.1 Allgemeiner Aufbau  downtop

Alle Formulare werden im Array document.forms[] gespeichert. Auf dieses Formular kann über den Array-Index zugegriffen werden, wobei die Formulare in der Reihenfolge im Array stehen, in der sie im HTML-Dokument vorkommen. Die Nummerierung beginnt beim Index 0. In unserem Beispiel benutzen wir also document.forms[0].

Alternativ dazu kann man auch über das NAME-Attribut des <FORM>-Tags auf das Formular zugreifen, im Beispiel also mit document.Fragebogen. Sollte das NAME-Attribut Spezialzeichen wie etwa das Leerzeichen enthalten (beispielsweise "Mein Fragebogen"), so kann noch mit document. forms["Mein Fragebogen"] darauf zugegriffen werden, allerdings erst ab JavaScript Version 1.1. Im allgemeinen aber sollte man den Array-Index verwenden. Da die meisten HTML-Seiten maximal ein Formular enthalten, reicht ein document.forms[0], und es ist auch nicht sonderlich unleserlich. Bei anderen Arrays, die viele Elemente besitzen (im Kapitel 9, »Images« finden Sie Beispiele), ist dieses Vorgehen sicherlich unpraktikabel.

Das Formular speichert all seine Elemente (also alle HTML-Formularelemente in diesem Formular) im Array elements[]. Auch hier kann man auf die einzelnen Elemente über den Array-Index zugreifen; im obigen Beispiel greift man auf das erste Texteingabefeld mit document.forms[0]. elements[0] zu. Alternativ können Sie auch wieder das NAME-Attribut verwenden, in diesem Fall document.forms[0].Vorname. Die meisten Formularelemente haben eine Eigenschaft value, die in der Regel die Eingabe des Benutzers angibt. Details hierzu finden Sie in den entsprechenden Abschnitten.

Zur Vereinfachung wird folgende Zeile am Anfang der Funktion pruefen() eingeführt:

var f = document.Fragebogen

Hiermit spart man sich ein wenig Tipparbeit; statt document.Fragebogen.elements[0] reicht jetzt f.elements[0].


Rheinwerk Computing

7.1.2 Texteingabefelder  downtop

Unter Texteingabefeldern werden in diesem Zusammenhang Formularfelder verstanden, die folgendermaßen in HTML abgebildet werden:

gp  <INPUT TYPE="TEXT">einzeiliges Texteingabefeld
gp  <INPUT TYPE="PASSWORD">einzeiliges Paßwortfeld
gp  <INPUT TYPE="HIDDEN">unsichtbares Formularfeld
gp  <TEXTAREA>mehrzeiliges Texteingabefeld

In diesem Fall gestaltet sich die Vollständigkeitsabfrage sehr einfach. Wie oben schon ausgeführt, heißt die Eigenschaft, die den Eingabewert im Texteingabefeld enthält, value. Der folgende JavaScript-Code kann also in die Funktion pruefen() eingefügt werden. Er funktioniert folgendermaßen: Ist ein Texteingabefeld nicht ausgefüllt, wird die Funktion mit return false verlassen, was dann zur Folge hat, dass das Formular nicht versandt wird.

if (f.Vorname.value=="")
   return false
if (f.Nachname.value=="")
   return false
if (f.E-Mail.value=="")
   return false

Auf eine Besonderheit bei Texteingabefeldern muss noch hingewiesen werden: Wenn Sie mehrere Texteingabefelder mit identischen NAME-Attributen haben, werden die Werte in einem Array gespeichert. Enthielte das Beispielformular von oben also noch ein Texteingabefeld namens Vorname, so könnte man auf das erste dieser Felder mit f.Vorname[0] zugreifen und auf das zweite Feld mit f.Vorname[1]. Beim Internet Explorer 3 funktioniert das leider nicht, hier müssen Sie über das elements[]-Array auf die Texteingabefelder zugreifen. Aus diesem Grund ein einfacher Tipp: Verwenden Sie stets eindeutige Bezeichnungen für Ihre Formularelemente.


Rheinwerk Computing

7.1.3 Radiobuttons  downtop

Aus einer Gruppe Radiobuttons kann immer nur einer ausgewählt werden. Eine Gruppe von Radiobuttons ist durch ein identisches NAME-Attribut gekennzeichnet. Leider greift man im obigen Beispiel mit f.Geschlecht auf die Gruppe von Radiobuttons mit dem NAME-Attribut Geschlecht zu. Die Eigenschaft value liefert hier nicht das richtige Ergebnis: Es muss auf einen individuellen Radiobutton zugegriffen werden. Das wäre natürlich über das elements[]-Array möglich, aber es gibt einen eleganteren Weg. Analog zu Texteingabefeldern werden gleichnamige Radiobuttons auch in einem Array abgespeichert. Mit der folgenden Schleife werden alle Radiobuttons (in diesem Falle zwei) durchlaufen und es wird überprüft, ob der Button ausgewählt ist (Boolesche Eigenschaft checked). Wenn beide nicht ausgewählt sind, wird pruefen() mit return false verlassen.

var geschlecht_ok = false
for (var i=0; i<f.Geschlecht.length; i++)
   if (f.Geschlecht[i].checked)
      geschlecht_ok = true
if (!geschlecht_ok) return false

Alternativ dazu können Sie eine Variante ohne Schleife benutzen, die etwas kürzer ist:

if (!(f.Geschlecht[0].checked || f.Geschlecht[1].checked))
   return false

Rheinwerk Computing

7.1.4 Checkboxen  downtop

Checkboxen können wie Radiobuttons ausgewählt werden, wobei sich die grafische Darstellung leicht unterscheidet: Checkboxen werden angekreuzt. Da Checkboxen nicht gruppiert sind, also jede Checkbox für sich ausgewählt werden kann (oder auch nicht), ist die Überprüfung auf Ausfüllung nicht weiter schwer. Wieder gibt es eine Boolesche Eigenschaft checked, die angibt, ob eine Checkbox angekreuzt ist oder nicht. Das Formular ist dann unvollständig ausgefüllt, wenn keine der drei Checkboxen angekreuzt worden ist.

if (!f.Flash.checked && !f.JavaScript.checked &&
  !f.InDesign.checked)
   return false

Rheinwerk Computing

7.1.5 Auswahllisten  downtop

Eine HTML-Auswahlliste wird mit dem Tag <SELECT> eingeleitet; es ist sinnvoll, diesem Tag ein aussagekräftiges NAME-Attribut zu geben. Die einzelnen Elemente werden durch den HTML-Tag <OPTION> dargestellt. Dieser Tag hat standardmäßig kein NAME-Attribut; wenn man also dort Informationen unterbringen will, sollte man das VALUE-Attribut besetzen.

In Sachen JavaScript kann auf die Auswahlliste über das NAME-Attribut des <SELECT>-Tags zugegriffen werden. Die einzelnen Optionen sind im Array options[] abgespeichert. Jede Option hat die Boolesche Eigenschaft selected, die angibt, ob die entsprechende Option gerade ausgewählt ist. Mit der Eigenschaft value kann auf das VALUE-Attribut der Option zugegriffen werden.

Im Fragebogen-Beispiel kommt es darauf an, dass nicht die erste Option ausgewählt wird, denn die heißt "Bitte wählen". Ein erster Versuch der Abfrage lautet also folgendermaßen:

if (f.Cover.options[0].selected)
   return false

Wenn festgestellt werden soll, welche der Optionen gerade ausgewählt ist, könnte man auf die Idee kommen, das options[]-Array mit einer Schleife zu durchlaufen, um so den Index der ausgewählten Option herauszubekommen:

for (var i=0; i<f.Cover.options.length; i++)
   if (f.Cover.options[i].selected)
      var Auswahl = i
if (Auswahl==0)
   return false

Diese Arbeit kann man sich jedoch sparen: Auswahllisten haben die Eigenschaft selectedIndex, die den Array-Index der ausgewählten Option angibt. Die Abfrage kann also folgendermaßen vereinfacht werden:

if (f.Cover.selectedIndex==0)
   return false

Es gibt auch Auswahllisten, bei denen mehr als eine Option ausgewählt werden kann. Diese sind in HTML mit <SELECT MULTIPLE> abgebildet. In diesem Fall enthält selectedIndex den Index der obersten ausgewählten Option.


Rheinwerk Computing

7.1.6 Fehlermeldung ausgeben  downtop

Hier wird noch einmal der vollständige Code für die Vollständigkeitsüberprüfung des Formulars wiedergegeben. Es wurden Kommandos hinzugefügt, die eine Warnmeldung ausgeben, sofern das Formular unvollständig ausgefüllt worden ist.

function pruefen(){
var f = document.forms[0]
   var fehler = "" //enthält die Bezeichnungen
                   //der nichtausgefüllten Felder
   // *** Überprüfung auf vollständige Ausfüllung
   if (f.Vorname.value=="")
      fehler += "Vorname "
   if (f.Nachname.value=="")
      fehler += "Nachname "
   if (f.E-Mail.value=="")
      fehler += "E-Mail "
   if (!(f.Geschlecht[0].checked||f.Geschlecht[1].checked))
      fehler += "Geschlecht "
   if (!f.Flash.checked && !f.JavaScript.checked &&
     !f.InDesign.checked)
      fehler += "Lieblingsbuch "
   if (f.Cover.selectedIndex==0)
      fehler += "Cover "
   // *** Gegebenenfalls Fehlermeldung
   if (fehler != ""){
      var fehlertext = "Die folgenden Felder wurden nicht
        vollständig ausgefüllt:\n"
      fehlertext += fehler
      alert(fehlertext)
      return false
   }
   return true
}
Abbildung 7.2  Hinweis auf nicht ausgefüllte Felder
Abbildung


Rheinwerk Computing

7.1.7 Konstruktive Vorschläge  downtop

Anstatt bei Texteingabefeldern eine Fehlermeldung auszugeben, kann man auch die Methode window.prompt() benutzen, um den Benutzer direkt zu einer Texteingabe zu zwingen. Im Kapitel »Fenster I« wurde window.prompt() schon erläutert. Man muss in diesem Beispiel noch zusätzlich beachten, dass man die value-Eigenschaft der Texteingabefelder auch auf den eingegebenen Wert setzt, damit diese Daten auch an das serverseitige Skript übergeben werden können.

Die Funktion pruefen() muss also folgendermaßen abgeändert werden:

function pruefen(){
   var f = document.forms[0]
   var fehler = "" //enthält die Bezeichnungen
                   //der nichtausgefüllten Felder
   // *** Überprüfung auf vollständige Ausfüllung
   while (f.Vorname.value==""){
      var vorname = prompt("Bitte geben Sie Ihren Vornamen ein!")
      if (vorname)
         f.Vorname.value = vorname
   }
   while (f.Nachname.value==""){
      var nachname = prompt("Bitte geben Sie Ihren Nachnamen ein!")
      if (nachname)
         f.Nachname.value = nachname
   }
   while (f.Email.value==""){
      var email = prompt("Bitte geben Sie Ihre E-Mail-Adresse ein!")
      if (email)
         f.Email.value = email
   }
   if (!(f.Geschlecht[0].checked||f.Geschlecht[1].checked))       fehler += "Geschlecht "    if (!f.Flash.checked && !f.JavaScript.checked &&      !f.InDesign.checked)       fehler += "Lieblingsbuch "    if (f.Cover.selectedIndex==0)       fehler += "Cover "    // *** Gegebenenfalls Fehlermeldung    if (fehler != ""){       var fehlertext = "Die folgenden Felder wurden nicht         vollständig ausgefüllt:\n"       fehlertext += fehler       alert(fehlertext)       return false    }    return true }
Abbildung 7.3  Nicht ausgefüllte Texteingabefelder können direkt korrigiert werden.
Abbildung

Der Benutzer steckt in einer Endlosschleife fest und wird gezwungen, die Angaben zu machen, ansonsten geht es nicht weiter. So ein Abfragefenster wirkt allerdings relativ aufdringlich, und wenn ein Benutzer partout nichts angeben will, dann macht er eben Falschangaben. Sie werden mit diesen Mitteln niemanden dazu bringen, die Wahrheit zu sagen, wenn er nichts über sich preisgeben will. Vergisst aber jemand, ein Mussfeld auszufüllen, bieten Sie ihm eine bequeme Möglichkeit an, dies nachzuholen.

Testen Sie Ihren Code sehr gründlich. Folgender Tippfehler führt dazu, dass der Benutzer in einer Endlosschleife festsitzt, die er nicht mehr verlassen kann:

while (f.Email.value==""){
   var email = prompt("Bitte geben Sie Ihre Email-Adresse ein!")
   if (email)
      f.Nachname.value = email
   }

Dieser Fehler schleicht sich bei der Verwendung von Copy&Paste sehr schnell ein, und er ruiniert das Skript. Nicht das Email-Feld wird aktualisiert, sondern das Nachname-Feld. Außerdem bleibt das Email-Feld immer leer, egal was der Benutzer in das Abfragefenster eingibt. Es geht also an dieser Stelle nicht weiter, und der Benutzer kommt so schnell nicht wieder auf Ihre Seiten.


Rheinwerk Computing

7.2 Automatische Überprüfung  downtop

gp  Das Skript zur Vollständigkeitsüberprüfung muss für jedes Formular neu geschrieben werden. Zwar können Sie Elemente wiederverwenden, aber etwas zusätzliche Arbeit ist immer nötig. Seit JavaScript Version 1.1 ist es aber möglich, die Überprüfung auch zu automatisieren. Jedes Formularelement besitzt nämlich die Eigenschaft type, die den Typ des Elements – beispielsweise Texteingabefeld, Radiobutton oder Checkbox – angibt. Man kann also den Ansatz verfolgen, in einer Schleife alle Formularelemente durchzugehen und zu überprüfen, ob sie ausgefüllt sind. Die Fehlermeldungen sind dann vielleicht nicht mehr so individuell wie im vorherigen Beispiel, aber Sie ersparen sich eine Menge Tipp- und Denkarbeit.

Im Folgenden sehen Sie das Grundgerüst für die JavaScript 1.1-fähige Version der Funktion pruefen(). Wie Sie schon wissen, wird bei gleichlautenden Funktionsnamen die letzte Funktion ausgeführt. Ältere Browser führen eine eingeschränkte, andere Funktion pruefen() aus, die lediglich durch return true für das Versenden des Formulars sorgt.

<SCRIPT LANGUAGE="JavaScript"><!--
function pruefen(){
   return true
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
function pruefen(f){ //Formular wird als Parameter übergeben
   var fehler = "" //Variable für die Fehlermeldung
   var i //Enthält das jeweilige Formularelement
   for (var j=0; i<f.elements.length; j++){
      i = f.elements[i]
      //kommt noch...
   }
   return true
}
//--></SCRIPT>

Rheinwerk Computing

7.2.1 Texteingabefelder  downtop

Der Wert der type-Eigenschaft eines Texteingabefelds ist bei einem einzeiligen Texteingabefeld "text", "password" bei einem Passwortfeld sowie "textarea" bei einem mehrzeiligen Eingabefeld. In diesem Fall wird die value-Eigenschaft des Formularelements (zur Erinnerung: Es steht in der Variablen i) überprüft. Falls keine Eingabe gemacht erfolgt ist, wird das NAME-Attribut des Eingabefelds (es steht in der Eigenschaft name) dem Fehlerstring hinzugefügt, um wenigstens eine einigermaßen aussagekräftige Fehlermeldung ausgeben zu können.

if (i.type=="text"||i.type=="password"||i.type=="textarea")
   if (i.value=="")
      fehler += i.name + "\n"

Rheinwerk Computing

7.2.2 Radiobuttons  downtop

Für Radiobuttons (erkennbar an der type-Eigenschaft "radio") muss man sich eine besondere Strategie überlegen. Jeder Radiobutton ist ein eigenes Formularelement und muss nicht unbedingt ausgewählt sein. Auf die folgende Art und Weise kommt man dennoch zum Ziel:

gp  Wenn Sie feststellen, dass das aktuell betrachtete Formularelement ein Radiobutton ist, wird das NAME-Attribut ausgelesen (Eigenschaft name). Dann wird das dazugehörige Array von Radiobuttons durchsucht, ob zumindest einer davon ausgewählt ist. Falls nicht, wird der Fehlerstring um das NAME-Attribut der Gruppe Radiobuttons erweitert.
gp  Jeder Radiobutton wird als einzelnes Formularelement behandelt. Ist also von einer Gruppe aus fünf Radiobuttons keiner ausgewählt, werden bei der Überprüfung der fünf Radiobuttons insgesamt fünfmal Mängel gefunden – es würde also fünf Fehlermeldungen geben. Aus diesem Grund wird eine weitere Variable, radiocheck, eingeführt (und zwar außerhalb der for-Schleife), in der die NAME-Attribute bereits geprüfter Radio-Buttons, durch Leerzeichen getrennt, eingetragen werden. Bevor ein Radiobutton überprüft wird, muss zuerst nachgeschaut werden, ob schon einmal ein anderer Radiobutton aus dieser Gruppe betrachtet worden ist. Daraus folgt auch eine Einschränkung für das Skript: Die NAME-Attribute der Radiobuttons dürfen keine Leerzeichen enthalten – aber das sollte sich von selbst verstehen, ich verweise auf die Einleitung.

if (i.type=="radio"){
   if (radiocheck.indexOf(i.name+ " "<0){
      radiocheck += i.name + " "
      eval("var radiogroup = f."+i.name)
      var ok = false
      for (var j=0; j<radiogroup.length; j++)
         if (radiogroup[j].checked)
            ok = true
      if (!ok)
         fehler += i.name + "\n"
   }
}


Rheinwerk Computing

7.2.3 Checkboxen  downtop

Bei Checkboxen ist eine allgemeine Überprüfung schlecht möglich. Es ist dem Benutzer ja freigestellt, ob er eine Checkbox ankreuzt oder nicht. Jede Checkbox ist im Grunde genommen eine Ja/Nein-Frage, und somit bedeutet kein Kreuz auch eine Antwort, nämlich Nein. Aus diesem Grund werden Checkboxen (die type-Eigenschaft heißt übrigens "checkbox") nicht überprüft.


Rheinwerk Computing

7.2.4 Auswahllisten  downtop

Auswahllisten erkennt man daran, dass die type-Eigenschaft des Formularelements entweder den Wert "select-one" oder den Wert "select-multiple" hat, je nachdem, ob der HTML-Parameter MULTIPLE gesetzt worden ist oder nicht. Die Eigenschaft selectedIndex muss überprüft werden. Sie muss ungleich 0 sein. Wir nehmen einfach einmal an, dass die oberste Option einer Auswahlliste immer »Bitte wählen Sie« oder ähnlich lautet.

if (i.type=="select-one" || i.type=="select-multiple")
   if (i.selectedIndex == 0)
      fehler += i.name + "\n"

Rheinwerk Computing

7.2.5 Zusammenfassung  downtop

gp  Im folgenden finden Sie noch einmal den gesamten Code für dieses Beispiel. Mit ihm sind Sie in der Lage, mit JavaScript Version 1.1 jedes Formular auf vollständige Ausfüllung hin zu überprüfen. In der Praxis kommt es aber oft vor, dass nicht alle Felder Pflichtfelder sind. Viele Benutzer sind auch sehr zurückhaltend, wenn sie allzu persönliche Daten wie etwa Geburtsdatum, E-Mail-Adresse, Telefonnummer oder gar ihr Einkommen angeben müssen. Überlegen Sie sich also ganz genau, ob Sie wirklich alle Daten benötigen.
<HTML>
<HEAD>
<TITLE>Formularüberprüfung mit JS 1.1</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function pruefen(){
   return true
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
function pruefen(f){
   var fehler = "" //Variable für die Fehlermeldung
   var radiocheck = "" //Variable für überprüfte Radiobutton
     Gruppen
   i //Enthält das jeweilige Formularelement
   for (var j=0; j<f.elements.length; j++){
      var i = f.elements[j]
      //Texteingabefelder
      if (i.type=="text"||i.type=="password"||i.type=="textarea")
         if (i.value=="")
            fehler += i.name + "\n"
      //Radiobuttons
      if (i.type=="radio"){
         if (radiocheck.indexOf(i.name+ " "<0)){
            radiocheck += i.name + " "
            eval("var radiogroup = f."+i.name)
            var ok = false
            for (var j=0; j<radiogroup.length; j++)
               if (radiogroup[j].checked)
                  ok = true
            if (!ok)
               fehler += i.name + "\n"
         }
      }

      //Auswahllisten
      if (i.type=="select-one" || i.type=="select-multiple")
         if (i.selectedIndex == 0)
            fehler += i.name + "\n"
   }
   //Fehlermeldung
   if (fehler != ""){
      alert("Bitte füllen Sie die folgenden Felder aus:\n" + fehler)
      return false
   }
   return true
}
//--></SCRIPT>
</HEAD>
<BODY>
<FORM onSubmit="return pruefen(this)">
... Formularfelder kommen hierhin ...
</FORM>
</BODY>
</HTML>

Rheinwerk Computing

7.3 Anwendungsmöglichkeiten für Formulare  downtop

Neben einer einfachen Vollständigkeitsüberprüfung von Benutzereingaben können Formulare auch noch anderweitig verwendet werden. In diesem Abschnitt werden einige Anwendungsmöglichkeiten vorgestellt, die Sie vielleicht schon in ähnlicher Form im World Wide Web gesehen haben. Sie können sie direkt auf Ihrer Website einsetzen.


Rheinwerk Computing

7.3.1 Währungsrechner  downtop

Der Kurs D-Mark/Euro ist ja leider nicht exakt 1:2, so dass ein Umrechner ein praktisches Hilfsmittel ist. Das Skript wird folgendermaßen aufgebaut:

gp  In einem Texteingabefeld gibt der Benutzer den Betrag in einer Währung ein.
gp  In welche Richtung umgerechnet werden soll, also D-Mark in Euro oder umgekehrt, wird mit Radiobuttons ausgewählt.
gp  Die Umrechnung wird gestartet, indem eine Schaltfläche gedrückt wird.
gp  Der umgerechnete Betrag wird in einem neuen Texteingabefeld angezeigt.

Die größte Schwierigkeit besteht darin, die Eingaben des Benutzers eventuell umzuformen. JavaScript verwendet das amerikanische Zahlenformat, und das kennt nur einen Dezimalpunkt, kein Dezimalkomma. Also wird das erste Komma durch einen Punkt ersetzt. Die Umwandlung der Zeichenkette in eine Dezimalzahl geschieht automatisch durch die Multiplikation bzw. Division durch den amtlichen Umrechnungskurs. Andernfalls könnten Sie die Funktionen eval() oder parseFloat() verwenden.

<HTML>
<HEAD>
<TITLE>Euro-Rechner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function umrechnen(f){  //f ist eine Referenz
                        //auf das Formular
   var betrag = f.betrag.value
   if (betrag.indexOf(",")!=-1)
      betrag = betrag.substring(0, betrag.indexOf(",")) + "." +
        betrag.substring(betrag.indexOf(","), betrag.length)
   if (f.umrechnung[0].checked)
      f.ausgabe.value = betrag / 1.95583 
   else
      f.ausgabe.value = 1.95583 * betrag
}
//--></SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="TEXT" NAME="betrag"><BR>
<INPUT TYPE="RADIO" NAME="umrechnung" VALUE="DMEUR"> DM nach
  Euro | <INPUT TYPE="RADIO" NAME="umrechnung" VALUE="EURDM">
    Euro nach DM<BR>
<INPUT TYPE="BUTTON" VALUE="Umrechnen!" onClick="umrechnen
  (this.form)"> <INPUT TYPE="TEXT" NAME="ausgabe">
</FORM>
</BODY>
</HTML>

Beachten Sie bei obigem Code den Aufruf umrechnen(this.form). Innerhalb jedes Event-Handlers eines Formularelements bezieht sich this auf das entsprechende Formularelement. Nun haben alle Formularelemente praktischerweise eine Eigenschaft form, die eine Referenz auf das dazugehörige Formular darstellt. Man kann also mit this.form das Formular als Parameter direkt an die Funktion übergeben.

Abbildung 7.4  Der Währungsrechner in Aktion
Abbildung


Rheinwerk Computing

7.3.2 Währungsrechner Teil 2  downtop

Der Währungsrechner lässt sich mit relativ wenig Aufwand so erweitern, dass auch der Euro-Kurs anderer Währungen ermittelt werden kann. Insbesondere bei international ausgerichteten Webseiten ist das ein netter Service. Die Idee dahinter ist die Folgende: Die verschiedenen Währungen stehen alle in einer Auswahlliste. Die beiden Radiobuttons sind mit »nach Euro« und »von Euro« beschriftet. Nach einem Klick auf die Schaltfläche wird zunächst das Umtauschverhältnis zwischen Euro und der ausgewählten Währung ermittelt. Dieser Faktor ist in einem Array abgespeichert worden, sodass der Wert von selectedIndex der Auswahlliste direkt als Arrayindex verwendet werden kann. Je nachdem, welcher Radiobutton angeklickt worden ist, wird der eingegebene Betrag entweder durch den Umrechnungsfaktor geteilt oder damit multipliziert.

<HTML>
<HEAD>
<TITLE>Euro-Rechner Teil 2</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function MakeArray(n){
   this.length = n
   return this
}
var kurs = new MakeArray(3)
kurs[0] = 1.95583
kurs[1] = 6.55957
kurs[2] = 1937.98450
function umrechnen(f){  //f ist eine Referenz
                        //auf das Formular
   var betrag = f.betrag.value
   if (betrag.indexOf(",")!=-1)
      betrag = betrag.substring(0, betrag.indexOf(",")) + "." +
        betrag.substring(betrag.indexOf(","), betrag.length)
  var faktor = kurs[f.Waehrung.selectedIndex]
   if (f.umrechnung[0].checked)
      f.ausgabe.value = betrag / faktor 
   else
      f.ausgabe.value = faktor * betrag
}
//--></SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="TEXT" NAME="betrag">
<SELECT NAME="Waehrung">
<OPTION>DM</OPTION>
<OPTION>Franc</OPTION>
<OPTION>Lira</OPTION></SELECT>
<BR>
<INPUT TYPE="RADIO" NAME="umrechnung" VALUE="nachEUR"> nach Euro
 | <INPUT TYPE="RADIO" NAME="umrechnung" VALUE="vonEUR"> von Euro<BR>
<INPUT TYPE="BUTTON" VALUE="Umrechnen!" onClick="umrechnen(this.
  form)"> <INPUT TYPE="TEXT" NAME="ausgabe">
</FORM>
</BODY>
</HTML>
gp  Natürlich können Sie das Beispiel auch umschreiben, sodass Sie zwischen zwei verschiedenen Währungen umrechnen können, mit dem Euro als Referenzwährung. Wenn Sie andere Währungen mit aufnehmen, beispielsweise den US-Dollar, müssen Sie den Kurs möglichst häufig aktualisieren, da der sich permanent ändert.

Rheinwerk Computing

7.3.3 Formularfelder für die Textausgabe nutzen  downtop

Wenn man Nachrichten für den Benutzer ausgeben will, ist ein Fenster via window.alert() etwas aufdringlich, und auch das Schreiben in die Statuszeile hat so seine Nachteile. Ein Texteingabefeld eignet sich hierfür jedoch wunderbar. Zwar sind auch hier die gestalterischen Möglichkeiten eingeschränkt, aber man muss die Nachteile gegeneinander abwägen. Wie der Lese- und Schreibzugriff auf Texteingabefelder vonstatten geht, haben Sie vorher in diesem Kapitel gesehen, das ist also kein Problem mehr.

gp  Etwas ärgerlich ist es jedoch, wenn der Benutzer denkt, er müsse in dieses Texteingabefeld etwas schreiben. Aus diesem Grund wäre es wünschenswert, wenn man das Feld mit einem Schreibschutz (für den Benutzer) versehen könnte. Der Internet Explorer (ab Version 4) bietet dafür ein eigenes HTML-Attribut an, aber im Sinne einer allgemeinverträglichen Lösung muss man sich mit JavaScript behelfen.

Texteingabefelder kennen den Event-Handler onFocus, der genau dann aktiv wird, wenn der Fokus auf dem Texteingabefeld landet (in der Regel sieht man, dass hineingeklickt wird und der Cursor blinkt). Das Gegenteil vom Erhalten des Fokus heißt auf englisch »to blur«, und jedes Texteingabefeld besitzt eine Methode namens blur(), die den Fokus entfernt. Durch folgende Zeile wird der Fokus also genau dann von einem Feld weggenommen, wenn es angeklickt wird. Der Benutzer ist also nicht in der Lage, dem Feld permanent den Fokus zu geben und Eingaben zu tätigen.

<INPUT TYPE="TEXT" onFocus="this.blur()">
gp  Beachten Sie unbedingt die Reihenfolge! Das folgende Kommando würde dafür sorgen, dass ein Feld immer den Fokus erhält, und somit eine weitere Navigation oder Benutzung der Website verhindern. Dem Benutzer würde kaum etwas anderes übrigbleiben, als seinen Browser zu schließen.
<INPUT TYPE="TEXT" onBlur="this.focus()">

Seien Sie ebenfalls vorsichtig, wenn Sie modale Fenster in Verbindung mit onFocus verwenden. Wenn sich ein modales Fenster öffnet, verliert das Texteingabefeld natürlich den Fokus. Es erhält ihn aber wieder, sobald das modale Fenster wieder geschlossen wird. Der folgende Code zwingt den Benutzer wahrscheinlich dazu, den Browser über das System »abzuschießen«, da sich immer wieder ein modales Fenster öffnet:

<INPUT TYPE="TEXT" onFocus="windows.alert('Die Geister, die
  ich rief...')">

Rheinwerk Computing

7.3.4 Navigation mit Auswahllisten  downtop

Links benötigen viel Platz. Eine Auswahlliste ist da sehr sparsam, kann hinter dem sparsamen Äußeren jedoch eine Menge Inhalt verbergen. So ist es schon auf vielen Webseiten üblich, in einer Auswahlliste mehrere Navigationsziele anzugeben. Sobald Sie einen Punkt in der Auswahlliste anklicken, wird die entsprechende Seite aufgerufen.

gp  Dazu benötigt man einen Event-Handler, der dann aktiv wird, wenn sich die aktuelle Auswahl der Auswahlliste ändert. Dieser Event-Handler heißt onChange und wird im Prinzip von allen Browsern unterstützt. Eine Ausnahme ist die Windows-Version vom Netscape Navigator 2, bei der der Event-Handler erst ausgeführt wird, wenn der Benutzer irgendeinen anderen Teil der Webseite anklickt – beispielsweise einen leeren Bereich der Seite. Aus diesem Grund sollte man für Benutzer dieses Browsers eine weitere Schaltfläche anbieten. Zwar würde es genügen, wenn man diese Schaltfläche mit keiner Aktion hinterlegt – wie gesagt, ein Klick irgendwo andershin genügt –, aber es gibt Berichte, dass auch das mitunter den onSelect-Event-Handler nicht aktiviert. Aus diesem Grund sollte diese Schaltfläche ebenfalls den erforderlichen JavaScript-Code ausführen.
gp  Im unteren Beispiel wird wieder eine Referenz auf das aktuelle Formular an die JavaScript-Funktion übergeben. Die URLs werden in einem Array gespeichert. Um zum Netscape Navigator 2 kompatibel zu sein, wird dieses Array mit der bekannten MakeArray()-Funktion generiert.
<HTML>
<HEAD>
<TITLE>Navigation mit JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function MakeArray(n){
   this.length = n
   return this
}
var urls = new MakeArray(4)
urls[0] = "" //leere URL für oberste Option
urls[1] = "http://www.netscape.com/de"
urls[2] = "http://www.microsoft.com/germany"
urls[3] = "http://www.opera.com"
function laden(f){
   if (f.auswahl.selectedIndex>0)
      location.href = urls[f.auswahl.selectedIndex]
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Navigation mit JavaScript</H3>
<FORM>
<SELECT NAME="auswahl" onChange="laden(this.form)">
 <OPTION>Bitte wählen</OPTION>
 <OPTION>Netscape</OPTION>
 <OPTION>Microsoft</OPTION>
 <OPTION>Opera</OPTION>
</SELECT>
<INPUT TYPE="BUTTON" VALUE="Laden" onClick="laden(this.form)">
</FORM>
</BODY>
</HTML>

Rheinwerk Computing

7.4 Fragen & Aufgaben  toptop

1. Schreiben Sie ein Skript, das eine Laufschrift in einem schreibgeschützten Texteingabefeld realisiert.
2. Erweitern Sie die Laufschrift aus der vorherigen Aufgabe zu einem News-Ticker. Eine bestimmte Anzahl von Hinweistexten wird nacheinander als Laufschrift angezeigt. Wenn der Benutzer in das Texteingabefeld klickt (Event-Handler: onClick), wird die zum Text gehörige URL geladen.
3. Die universelle Formularüberprüfung scheitert, wenn das name-Attribut der Gruppe aus Radiobuttons Sonderzeichen enthält (z. B. Leerzeichen, Bindestrich). Ändern Sie das Listing so ab, dass dieser Fehler nicht mehr auftritt!
4. In der Praxis ist nicht jedes Formularfeld ein Pflichtfeld. Wie könnte man in einem Formular ein Pflichtfeld kennzeichnen, aber die Vollständigkeitsüberprüfung trotzdem mit einer universell einsetzbaren Funktion erledigen?
5. Ändern Sie das Navigationsbeispiel mit der Auswahlbox ab, so dass die Ziel-URLs nicht in einem Array gespeichert werden, sondern im VALUE-Attribut des <OPTION>-Tags.
  

JavaScript

jQuery

Einstieg in JavaScript

Responsive Webdesign

Suchmaschi-
nen-Optimie-
rung




Copyright © Rheinwerk Verlag GmbH 2001 - 2002
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken und speichern. Ansonsten unterliegt das <openbook> denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.
Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung der Rheinwerk Verlag GmbH. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: >> Zum Feedback-Formular


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, fon: 0228.42150.0, fax 0228.42150.77, service@rheinwerk-verlag.de