Malleus' Tutorials:
Version: 0.7 ( 14.07.2006 ) |
Produkt | Menge | Aktionen | ||
---|---|---|---|---|
Vom Template "abweichende" Zeilen kann man "vor" dem eigentlichen Template" spezifizieren: Man definiert im "Parent"-Tag das Attribut "repeat" mit dem entsprechenden Index. Das nachfolgende Template generiert dann "repeat-start" neue Reihen.
<form name="myForm"> <table border="1"> <thead> <tr> <th>Produkt</th> <th>Menge</th> </tr> </thead> <tbody> <tr repeat="1"> <td><input type="text" name="myProduct1" value="Das muß man haben!" readonly></td> <td><input type="number" name="myQuantity1" value="1" min="1" required></td> </tr> <tr id="orderTemplate" repeat="template" repeat-start="3"> <td><input type="text" name="myProduct[orderTemplate]" value=""></td> <td><input type="number" name="myQuantity[orderTemplate]" value="1"></td> </tr> </tbody> </table> <p><button type="add" template="orderTemplate">Neue Zeile hinzufügen</button></p> <p><input type="submit"> </form>
Produkt | Menge |
---|---|
<form name="myFormC"> <input type="submit" name="submit1" action="file1.php" method="post" target="window1" > <input type="submit" name="submit2" action="file2.php" method="get" target="window2" > </FORM>
Das früher zwingend erforderliche "action"-Attribut des Formulars kann auch komplett "weggelassen" werden: Ein "Submit" ohne "action"-Attribut verschickt die Daten einfach an sich selbst.
Eine weitere Neuheit bezüglich Formulare ist das Attribute "form", das nun bei allen Formularelementen angegeben werden kann: Es spezifiziert das Formular, zu dem es "gehört". Es ist also nicht mehr so, daß alle Elemente, die sich innerhalb eines "FORM"-Tags befinden, auch automatisch beim "Submit" bzw. "Reset" dieses Formulars übertragen bzw. resettet werden. Auch ist es nun möglich, mehrere, durch Leerzeichen getrennte, "zuständige" Formulare anzugeben.
Beachte hierbei, daß mit "form" die "ID" des entsprechenden Formulars und nicht dessen Namen gemeint ist!
Beispiel: Das "INPUT"-Control mit dem Namen "myTextA1" gehört zu den Formularen "myFormB" und "myFormC", d.h. nur ein Submit eines dieser Formulare übermittelt dessen Wert. Das ganze funktioniert natürlich analog zum "Reset".
Form A:<form id="myFormA"> ( B, C ) <input type="text" name="myTextA1" form="myFormB myFormC"> ( A ) <input type="text" name="myTextA2"><br> <input type="reset" value="reset Form A"> </form> Form B:<form id="myFormB"> <input type="text" name="myTextB1"> <input type="reset" value="reset Form B"> </form> Form C:<form id="myFormC"> <input type="text" name="myTextC2"><br> <input type="reset" value="reset Form C"> </form>
Form A: ( A ) |
<select name="mySelect" size=10 style="width:200px"> <optgroup label="Deutsche Städte"> <option>Berlin</option> <option disabled>München</option> <option>Homburg</option> </optgroup> <optgroup label="Europäische Städte"> <option>Paris</option> <option>Rom</option> <option disabled>London</option> </optgroup> <optgroup label="Sonstige Städte"> <option>Moskau</option> <option>Kairo</option> <option>Sydney</option> </optgroup>
<fieldset disabled> <select name="mySelect"> <option>1</option> <option>2</option> </select> <input type="checkbox" name="myCheckBox" checked> <input type="text" name="myText" value="ÄNDERE MICH!"> </fieldset>
<input type="text" name="myText" autofocus>
<input type="text" name="myText" autocomplete="off">
Das Control gehört zu einem Formular, d.h. "object.form != null"
Das Control hat ein "name" Attribut.
Das Control ist nicht disabled.
Das Control gehört nicht zu einem Template, d.h. es ist kein Kind eines HTML-Elementes mit "repeat='template'".
Achtung: Die vom Template "generierten" Controls zählen hier natürlich nicht darunter.
Das Control ist kein Kind eines "DATALIST"-Tags, da diese Elemente ja nur angezeigt werden, wenn "DATALIST" vom Browser nicht unterstützt wird.
Das Control ist kein Button vom Typ "reset", "add", "remove", "move-up" bzw. "move-down".
Das Control ist kein "OUTPUT" Element.
Das Ergebnis der Validierung wird in einem Attribut validity des Controls gespeichert. Dieses "Objekt" hat dabei die folgende Ausprägungen bzw. Fehlercodes:
Der eingebene Wert "paßt" nicht zum Typ, d.h. die Eingabe eines Textes in ein "number"-Feld.
Ein Minimalwert "min" wurde angegeben und vom Benutzer "unterschritten".
Ein Maximalwert "max" wurde angegeben und vom Benutzer "überschritten".
Eine Schrittweite "step" wurde angegeben und der eingegebene Wert "paßt" nicht, d.h. "step = 5" und "value = 6"
Der eingegebene Text ist länger als in "maxlength" zugelassen.
Der eingegebene Text "matched" nicht mit dem spezifizierten regulären Ausdruck, d.h. "a3bcde" paßt nicht zu "[a-z]+"
Ein Pflichtfeld wurde nicht angebenen.
Der Wert wurde "von Hand" mit Hilfe der Control-Methode setCustomValiditiy("myErrorMessage") als "invalid" gekennzeichnet. Beim Submit wird folgende Meldung ausgegeben:
"Dieser Wert wird von einem Script dieser Seite nicht zugelassen!
myErrorMessage
Dieser Error kann nicht durch Eingabe eines neuen Wertes bzw. Reset des Formulars gelöscht werden! Man muß explicit die Methode "setCustomValiditiy" mit einem Leerstring als Parameter aufrufen!
Wenn kein anderes oben aufgeführtes Flag gesetzt ist, ist dieses Flag "true", d.h. der Wert ist "gültig" und kann übertragen werden.
Wird der "Submit"-Button gedrückt, werden alle zur Form gehörenden Elemente mit gesetzten "willValidate" Property gesucht und validiert. Ist ein Wert nicht valide, wird ein oninvalid Event gefeuert, das vom betreffenden Control abgefangen werden kann. Liefert dessen Eventhandler "false" zurück, wird die "Default"-Fehlermeldung des Browsers unterdrückt.
Treten mehrere Fehler gleichzeitig auf, wird der "Info"-Text nur beim ersten fehlerhaften Control angezeigt.
Beispiel:
function initPage() { document.myForm.myText2. // Zeilenumbruch! setCustomValidity( "aua" ); }; function checkErrorCodes(obj) { with (obj.validity) { if ( valueMissing ) alert( "valueMissing" ); if ( rangeUnderflow ) alert( "rangeUnderflow" ); if ( rangeOverflow ) alert( "rangeOverflow" ); if ( stepMismatch ) alert( "stepMismatch" ); if ( patternMismatch ) alert( "patternMismatch" ); if ( customError ) alert( "customError" ); if ( typeMismatch ) alert("typeMismatch"); if ( tooLong ) alert( "tooLong" ); }; return true; //return false unterdrückt Fehlermeldung! } function clearError() { document.myFormH.myText2.setCustomValidity(""); } | <body onload="initPage()"> <form name="myForm"> <input type="number" name="myNumber" oninvalid="return checkErrorCodes(this)" min="10" max="20" step="5"> <input type="text" name="myText" pattern="[a-z]+" oninvalid="return checkErrorCodes(this)"> <input type="text" name="myText2" oninvalid="return checkErrorCodes(this)"> <input type="text" name="myText3" maxlength="4" value="abcde" oninvalid="return checkErrorCodes(this)"> <input type="button" value="lösche customError" onclick="clearError()"> <input type="submit"/> </form> </body>
|
Mit der neuen "FORM"-Methode checkValidity ist es möglich, das Formular ohne Drücken des "Submit"-Buttons zu validieren.
<input type="number" name="myNumber" min="3" max="7" oninput="check4TypeMismatch(this)" >
function check4TypeMismatch( myControl ) { if ( myControl.value == "" ) { myControl.setCustomValidity( "...wahrscheinlich ein 'TypeMismatch'-Fehler in Opera 9" ); } else { myControl.setCustomValidity( "" ); }; myControl.form.checkValidity(); }
Was passiert hier? Wenn der eingegebene Text keine Zahl ist, setzt Opera 9 den Value des Controls auf "". Fälschlicherweise wird aber intern der "TypeMismatch"-Fehler nicht gesetzt! Aus diesem Grund setze ich das Control mit Hilfe von "setCustomValidity" manuell auf "customError" und aktiviere die Formvalidierung. Ist der neue Value eine Zahl, wird der "customError" wieder gelösct.
Zum Abschluß dieses Kapitels gibt's noch etwas kleines Feines: das "SELECT"-Property selectedOptions. Dieses Array enthält alle ausgewählten "OPTION"-Elemente eine MultiSelectBox, d.h. man muß nicht mehr alle "options" durchlaufen und überprüfen, ob das Attribut "selected" gesetzt ist.function showSelectedOptions() { var option = document.myForm.mySelect.selectedOptions; for ( var i = 0; i > option.length; i++ ) alert( option[ i ].text ); }; |
Bitte mehrere Einträge mit "Strg"+Klick auswählen: |
Jeder der schon einmal abhängige "SELECT"-Boxen mit Javascript gebaut hat, weiß um was für eine Arbeit es sich dabei handelt. Zum Glück ist das jetzt vorbei: Es wurde ein neues Attribut "DATA" für "SELECT"-Tags eingeführt, das diese Arbeit automatisiert. Man kann hierbei unterscheiden, ob die alten "OPTION"-Einträge gelöscht bzw. beibehalten ( type="incremental" ) werden. Auch ist es nun möglich, die Daten als externe Datei auszulagern:
<form name="myForm"> <select name="mySelect" data="data.xml"></select> <input type="button" onclick="add456()" value=" + ( 4,5,6 )"/> <input type="button" onclick="change2ABC()" value=" = ( A, B, C )"/> <input type="button" onclick="loadAndAddDEF()" value=" lade und + ( D, E, F )"/> </form>
function addOptions( obj, newOptions ) { obj.data = 'data:application/xml,' + '<select xmlns="http://www.w3.org/1999/xhtml" type="incremental">' + newOptions + '</select>'; }; function changeOptions( obj, newOptions ) { obj.data = 'data:application/xml,' + '<select xmlns="http://www.w3.org/1999/xhtml">' + newOptions + '</select>'; }; function add456() { addOptions( document.myForm.mySelect, "<option>4</option><option>5</option><option>6</option>" ); }; function change2ABC() { changeOptions( document.myForm.mySelect, "<option>A</option><option>B</option><option>C</option>" ); }; function loadAndAddDEF() { document.myForm.mySelect.data = "data2.xml"; };Datei: data.xml
<select xmlns="http://www.w3.org/1999/xhtml"> <option>1</option><option>2</option><option>3</option> </select>Datei: data2.xml
<select xmlns="http://www.w3.org/1999/xhtml" type="incremental"> <option>D</option><option>E</option><option>F</option> </select>
...und hier kommt noch ein Beispiel, daß sich mit dreifach "abhängigen" Selectboxen befaßt:
A = "<option>Audi</option><option>BMW</option><option>Opel</option>"; A0 = "<option>A3</option><option>A4</option><option>A5</option>"; A1 = "<option>320i</option><option>535i</option><option>635 csi</option>"; A2 = "<option>Ascona</option><option>Signum</option><option>Vectra</option>"; C = "<option>Festplatte</option><option>Monitor</option><option>Grafikkarte</option>"; C0 = "<option>100 GB</option><option>200 GB</option><option>400 GB</option>"; C1 = "<option>17 Zoll</option><option>19 Zoll</option><option>21 Zoll</option>"; C2 = "<option>32 MB</option><option>64 MB</option><option>128 MB</option>"; K = "<option>Hörspiele</option><option>Märchen</option><option>Filme</option>"; K0 = "<option>Benjamin Blümchen</option><option>Bibi Blocksberg</option>"; K1 = "<option>Dornröschen</option><option>Schneewittchen</option><option>Rapunzel</option>"; K2 = "<option>Lars Eisbär</option><option>Lauras Stern</option><option>Ice Age</option>"; function initPage() { oMyForm = document.myForm; oMySelect1 = oMyForm.mySelect1; oMySelect2 = oMyForm.mySelect2; oMySelect3 = oMyForm.mySelect3; createToggle2(); }; function changeSelect( obj, options ) { obj.data = 'data:application/xml,<select xmlns="http://www.w3.org/1999/xhtml">'+options+"</select>"; } function createToggle2() { changeSelect( oMySelect2, eval( oMySelect1.value ) ); window.setTimeout("createToggle3()",100); }; function createToggle3() { changeSelect( oMySelect3, eval( oMySelect1.value + oMySelect2.selectedIndex ) ); };
<body onload="initPage()"> <form name="myForm"> <select name="mySelect1" onchange="createToggle2()"> <option value="A">Autos</option> <option value="C">Computer</option> <option value="K">Kinder</option> </select> <select name="mySelect2" onchange="createToggle3()"></select> <select name="mySelect3"></select> </form> </body>
"FORM"-Tags können "initial" auch mit Hilfe des "DATA"-Attributes befüllt werden. Leider wurde dieses Feature bisher noch nicht von Opera 9 implementiert. Ein "mögliches" Beispiel könnte so aussehen:
<form name="myForm" data="data.xml"> <input type="text" name="myText"> </form> |
<formdata xmlns="http://n.whatwg.org/formdata"> <field name="myText">Hallo</field> </formdata>Datei: data.xml |
Genaure Infos werden "zu gegebener Zeit" nachgereicht" ;-)
Controls bzw. "OPTIONS" oder "OPTIONGROUPS", die "disabled" sind
Formelemente, die nicht disabled sind
Controls mit gesetzten "readonly"-Attribut
Controls, die nicht readonly sind
Markierte "Check / Radio"-Boxen bzw "SELECT"-Boxen mit ausgewählter "OPTION"
Eine Gruppe von "radio"-Buttons von denen noch keiner ausgewählt wurde
Controls mit "gültigem" Wert
Controls mit einem Wert der in einem spezifizierten Bereich liegt
Controls mit einem nicht gültigen Bereichswert
Controls, die "ausgefüllt" werden müssen
Controls, die keine Pflichtfelder sind
<style> :enabled { background-color : green; color : white; font-weight : bold } :disabled { background-color : red; } :checked { color : yellow; background-color : yellow } :in-range { color : green; font-weight : bold } :out-of-range { color : red } :required { border : solid 4px red; } :indeterminate { background-color : blue } </style> |
<input type="text" disabled value="disabled"> <input type="text""> <input type="text" required="required" value="Pflichtfeld"> <input type="number" min="10" max="20" step="5" value="15"> <input type="number" min="10" max="20" step="5" value="5"> <input type="number" min="10" max="20" step="5" value="25"> <input type="number" min="10" max="20" step="5" value="6"> <input type="radio" name="myRadios" value="a"> <input type="radio" name="myRadios" value="b"> <input type="radio" name="myRadios" value="c"> |
Mit Hilfe des Pseudo-Selektors :invalid ist es möglich, das Aussehen der browserspezifischen Fehlermeldung abzuändern. Deren Text ist meines Wissens leider noch nicht änderbar.
:invalid { background-color: yellow; color:red; } |
<input type="number" name="myNumber" min="10" max="20" step="2"> <input type="email" name="myEmail"> <input type="url" name="myUrl"> |
Eine gerade Zahl zwischen 10 und 20 : | eMail : | url mit "http://" : |
Zum Abschluß noch etwas zum Thema "Unerwünschte Attribute": Das "INPUT"-Attribut "size" bzw. "cols" und "rows" bei "TEXTAREAS" sollte man von nun an nicht mehr verwenden,
da der gleiche Effekt auch mit dem css-Style "width" erzielt werden kann.
Das Icon links erscheint nur, wenn man eine Hintergrundfarbe für das "INPUT"-Control angibt.
Bei einer falschen Eingabe wird kein "Typemismatch" gemeldet! Man muß das Feld als "required" kennzeichnen um eine entsprechende Fehlermeldung zu bekommen.
Die beiden Pseudo-Selektoren :checked und :default funktionieren nicht bei einer "SELECT"-Box.
Die Kombination range-Control und DATALIST funktioniert nicht.
Ein "File"-Control meldet keinen "Typemismatch"-Fehler wenn eine nicht zum "accept"-Attribut passende Datei ausgewählt wurde.
Javascript: Der "repetitionIndex" eines generierten Templates ist immer "0".
onformchange feuert nicht bei "SELECT"