ms...@podiuminternational.org wrote:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Hallo an alle! Mein erstes Posting hier!
Hallo. Beachte dazu bitte die Hinweise am Ende meines Postings.
> Ich möchte ein Formular validieren. Leider schaffe ich es nicht zwei
> verschiedene checkboxen zu validieren. Alles andere, Text-Felder, Radio,
> Select-Felder funktioniert. Zur Illustration habe ich ein Beispiel
> zusammengestellt. Die entscheidenden Zeilen sind:
>
> for ( var i = 0; i < requiredCheckbox.length; i++ ) {
> element = requiredCheckbox[i];
> if ( form[element].checked )
>
> in denen wohl ein Denkfehler liegt.
Wie kommst Du darauf? (ernstgemeinte Frage)
> <!DOCTYPE html>
> <html>
> <head>
> <meta charset="utf-8">
> <title>Check Radio and Checkbox by Javascript</title>
Es gibt kein “Javascript”. Es gibt eine Programmiersprache namens
“JavaScript”. Diese ist eine von vielen Implementierungen eines Standards
für Programmiersprachen, namens “ECMAScript”. Firefox & Co. unterstützen
Mozilla JavaScript. Internet Explorer & Co. unterstützen Microsoft JScript.
Chrome & Co. unterstützen Google V8 JavaScript. Safari unterstützt Apple
JavaScriptCore. Opera unterstützt Opera ECMAScript. Konqueror unterstützt
KDE JavaScript. Und so weiter. Diese Programmiersprachen sind zwar sehr
ähnlich – und alle hier on-topic, aber es sind *verschiedene*
Programmiersprachen.
Zusätzlich gibt es noch von den jeweiligen Umgebungen unterstützte
Programmierschnittstellen (APIs), die nicht zu eiber dieser
Programmiersprachen gehören. Zum Beispiel das Document Object Model (DOM),
mit dem man Formulare validieren kann.
Das solltest Du von Anfang an lernen, sauber voneinander zu trennen.
<
http://PointedEars.de/es-matrix>
> <script type="text/javascript">
> function validateForm ( form ) {
> requiredSelect = new Array( "fruit_color", "vegetable_color" );
> requiredCheckbox = new Array( "apple", "tomato" );
^
Du hast vergessen, ”requiredSelect” und “requiredCheckbox” als Variablen zu
deklarieren:
var requiredSelect = new Array( "fruit_color", "vegetable_color" );
var requiredCheckbox = new Array( "apple", "tomato" );
Ohne Deklaration sind Bezeichner, denen Werte zugewiesen werden, keine
Variablen (sondern Eigenschaften) und sie sind global; oder die Zuweisung
selbst führt zu einem Laufzeitfehler. Nicht machen.
Zum Deinem Codestil:
Nach der öffnenden Klammer einer Argumentliste und vor der schliessenden
Klammer sollte kein Leerraum stehen. Ausserdem lässt sich die
Initialisierung von Arrays in allen genannten Implementierungen heutzutage
einfacher und weniger fehlerträchtig schreiben:
var requiredSelect = ["fruit_color", "vegetable_color"];
var requiredCheckbox = ["apple", "tomato"];
Schliesslich sind die Variablenbezeichner nicht gut gewählt. Offensichtlich
können es mehrere select-Elemente und Kontrollkästchen sein, also sollte es
auch “requiredSelects” und “requiredCheckboxes” heissen.
> return requireCheckboxes ( form, requiredCheckbox ) &&
> requireSelects ( form, requiredSelect ) &&
> checkProblems ();
> }
>
> function requireSelects ( form, requiredSelect ) {
Besser lesbar:
function requireSelects (form, requiredSelect)
{
Es gibt Funktionsdeklarationen (siehe oben) und es gibt Funktionsausdrücke:
var requireSelects = function (form, requiredSelect) {
// …
};
Indem Du die geschweifte Klammer bei Deklarationen auf die nächste Zeile
schreibst, lassen sich diese leichter von Ausdrücken unterscheiden. Das ist
wichtig, denn Funktionsdeklarationen sind von Anfang an effektiv, während
Funktionsausdrücke erst während des Programms Wirkung zeigen. Die
Reihenfolge einer Funktionsdeklaration in einem Kontext spielt keine Rolle;
die eines Funktionsausdrucks jedoch schon. (Gleiches gilt übrigens für
Variablendeklaration und Variableninitialisierung.)
Der Funktionsbezeichner ist hier wieder nicht gut gewählt. Du willst in der
Funktion select-Elemente *überprüfen* (check), _nicht_ erfordern (require).
> for ( var i = 0; i < requiredSelect.length; i++ ) {
Besser lesbar und effizienter:
for (var i = 0, len = requiredSelect.length; i < len; ++i)
{
// …
}
Die Länge des Arrays, d. h. die Anzahl seiner Elemente, ändert sich nämlich
in der Schleife nicht (also genügt es, sie einmal – im
Initialisierungsteil – abzufragen) und Dich interessiert der alte Wert von
“i” nicht (also genügt Prä-Inkrement statt Post-Inkrement).
> element = requiredSelect[i];
Nicht deklarierte Variable.
> if ( form[element].selectedIndex <= 0 ) {
> alert( "Please select a value for " + element + "." );
if (form[element].selectedIndex <= 0)
{
window.alert(…);
}
Das ist sauberer, und so erkennst Du gleich den Unterschied zwischen
Programmiersprache und DOM (“window” referenziert ein DOM-Objekt, “alert”
ist der Name einer seiner Methoden).
(Beachte auch dass, “<=” nur dann richtig ist, wenn das select-Element auch
dann nicht validieren soll, wenn man den ersten Eintrag (Index 0) ausgewählt
hat. Andernfalls ist “<” richtig.)
> […]
> function checkProblems () {
> for ( element in validate ) {
Ein Debugger wie Firebug (<
http://getfirebug.com/>) oder einer der in den
meisten anderen Browsern eingebaute Debugger (F12-Taste) hätte Dir an dieser
Stelle mitgeteilt, dass der Bezeichner “validate” nicht existiert (die
Referenz kann also nicht aufgelöst werden, und es wird eine
“ReferenceError”-Exception ausgelöst, ein Laufzeitfehler).
*Deshalb* funktioniert Deine Formularvalidierung nicht, denn checkProblems()
wird in validateForm() aufgerufen, wenn requireCheckboxes() und
requireSelects() beide Werte liefern, die zu “true” (wahr) konvertiert
werden können; das macht der “&&”-Operator (logisches UND).
Eine for-in-Schleife eignet sich nur für native Objekte, und unter diesen
nicht für Array-Instanzen. Denn for-in iteriert über die *aufzählbaren*
*Eigenschaften* von Objekten in *beliebiger* Reihenfolge.
Es könnte also sein, dass hier für “validate” vorher
var validate = {
foo: true,
bar: false
};
erwartet wird (“validate” speicherte anschliessend eine Referenz auf eine
Object-Instanz).
Das Problem: Es erben alle neuen Objekte (O.B.d.A.) Eigenschaften von
anderen Objekten über eine eindimensionale Datenstruktur, die “Prototyp-
Kette” genannt wird (ein Objekt ist der Prototyp eines anderen –
prototypbasierte Vererbung). Zum Beispiel
[Object-Instanz: {…} oder new Object()] → Object.prototype
oder
[Array-Instanz: […] oder new Array()] → Array.prototype → Object.prototype
Diese geerbten Eigenschaften können auch aufzählbar sein, und dann iteriert
for-in *auch* über diese. Das will man in der Regel nicht und muss das
deshalb ausschliessen:
for (element in validate)
{
if (validate.hasOwnProperty(element))
{
// …
}
}
Einfacher ist es aber, nur über die Eigenschaften zu iterieren, die einen
auch interessieren. Bei Object-Instanzen seit ECMAScript Edition 5:
var propertyNames = Object.getOwnPropertyNames(validate);
for (var i = 0, len = propertyNames.length; i < len; ++i)
{
var element = propertyNames[i];
}
Bei Arrays “a” ohne Lücken (Arrays mit Lücken heissen “sparse arrays”)
trivialerweise mit
for (var i = 0, len = a.length; i < len; ++i)
{
var element = a[i];
}
oder (rückwärts)
for (var i = a.length; i--;)
{
var element = a[i];
}
Letzteres garantiert dann auch eine Reihenfolge, die überall gleich ist,
denn sie wird vom Index “i” und damit dem Entwickler bestimmt; nicht von der
ECMAScript-Implementierung.
> <form id="form" method="post" action="" onsubmit="return validateForm(
> this )">
Dein form-Element braucht hier keine ID (id-Attribut), denn Du lieferst mit
“this” bereits die Referenz zum entsprechenden Elementobjekt.
Auch wird hier deutlich, weshalb exzessiver Leerraum eher schlechter lesbar
ist.
> <p>
Es handelt sich hier nicht um einen Absatz (Paragraph), sondern um einen
Abschnitt (DIVision). Der richtige Element-Typ ist hier also “div”, sofern
nicht ein anderer Struktur-Typ von HTML5 besser passt.
<
http://html5doctor.com/resources/#flowchart>
> I eat apples:<br />
> <label>Yes!</label>
> <input type="checkbox" id="apple" name="apple" />
Besser:
<label for="apple">Yes!</label>
<input type="checkbox" id="apple" name="apple" />
Nur dann ergibt eine ID für die Checkbox hier Sinn. Benutzerfreundlicher
wäre allerdings:
<input type="checkbox" id="apple" name="apple" />
<label for="apple">I eat apples</label>
Siehe auch <
http://www.edition-w3.de/TR/1999/REC-
html401-19991224/interact/forms.html#h-17.9.1>
> <input type="submit" />
Dein Submit-Button sollte noch einen Wert (value-Attribut) haben, sonst
erscheint möglicherweise darauf gar kein Text.
> <input type="reset" />
Nicht machen: <
http://www.nngroup.com/articles/reset-and-cancel-buttons/>
Und zum Schluss:
Normalerweise lese und beantworte ich Artikel _nicht_, die so wie Deiner
über Google Groups hereinkommen. Es kommt einfach zuviel Müll (Spam)
darüber ins Usenet und Google interessieren Beschwerden von Netznutzern
darüber anscheinend nicht. (Stattdessen bieten sie *nur* *ihren* Nutzern
die Möglichkeit, den Spam auszublenden. Das löst aber das Spam-Problem
nicht und es löst es für alle anderen Netznutzer nicht; siehe
<
http://de.wikipedia.org/wiki/Usenet>.)
Du solltest daher einen Newsreader installieren und benutzen lernen, zum
Beispiel <
http://getthunderbird.com/> oder <
http://userbase.kde.org/KNode>.
Ausserdem solltest Du für das nächste Mal
<
http://dcljs.de/> ff.
und
<
http://www.tty1.net/smart-questions_de.html>
sorgfältig lesen und anschliessend anwenden. Es ist nämlich eigentlich
_nicht_ akzeptabel, in einer (technischen) Newsgroup
- ohne vollen (und richtigen) Namen (Vor- und Nachname) zu posten.
Internet ist das Ding mit den Kabeln; Usenet ist das Ding mit den
Menschen. Hier kommunizieren Leute miteinander, nicht E-Mail-Adressen.
- sich nicht vor dem Posten selbständig zu informieren und zu versuchen,
damit das Problem selbst zu lösen. (Eigene Lösungsversuche zeigen)
- keine Frage zu stellen. (Fragezeichen fehlt)
- keine Problembeschreibung mitzuliefern (“Geht nicht” ist *keine*
Problembeschreibung: <
http://glasgoogle.de/>)
- Viele Zeilen Quelltext ohne weiteren Kommentar und ohne URL eines
Testfalls abzukippen.
Ich habe hier nur eine Ausnahme gemacht, weil Du hier neu bist und
anscheinend ein Anfänger bei diesem Thema bist.
HTH
--
PointedEars
Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.