Byte GameMaker Magazin

Magazin für Hobby-Spieleentwicklung

Interaktives Formular mit JavaScript

Lesedauer 8 Minuten

In der Webentwicklung brauchen wir oft Formulare. Die meisten funktionieren sehr simpel, doch manchmal will der Benutzer schon bei der Eingabe ein Ergebnis sehen. Hierfür ist JavaScript nahezu perfekt. Im heutigen Beispiel gehen wir es etwas komplexer an und machen uns ein Formular, in dem Werte umgerechnet werden.

Was wir vorhaben, findest Du hier. Wir rechnen Längenmaße und Temperaturen um. Natürlich kannst Du dies um Flächen, Volumen und Massen erweitern oder ganz andere Dinge damit machen.

HTML Grundgerüst

Wie eigentlich immer, starten wir auch dieses Mal mit einem HTML-Grundgerüst.

In Zeile 6 sehen wir, dass ein JavaScript mit dem Dateinamen umrechnung.js im Ordner js geladen wird. Das kannst Du gleich anlegen. Der Rest des HTMLs kommt zwischen die Body-Tags.

Formular

Wir erstellen nun zwei Formulare, jeweils mit einer <h3> Überschrift davor. Die Formulare schließen eine Tabelle ein. Man kann es auch ohne Tabelle machen, aber so lässt es sich recht geschickt formatieren. Auf CSS und entsprechende Klassen habe ich dieses Mal verzichtet.

Wichtig sind zunächst die IDs der Formulare und Inputfelder.

Was passiert hier?

Wir haben zwei Formulare, die identisch funktionieren. Deshalb schauen wir uns nur das erste genauer an.

Hier beginnt das Formular mit der ID lange.

Eingabefeld

Wir haben ein Eingabefeld vom Typ number. Das ist ganz wichtig, denn dadurch kann man in vorgegebenen Schritten (steps) hoch oder runter gehen. Außerdem erhält man auf dem Smartphone ein hübsches Tastenfeld, wenn man es anklickt. Besonders wichtig ist oninput=calcLengthen(). Das bedeutet, dass immer, wenn etwas eingegeben wird, das Script calcLengthen() gestartet wird. Als Platzhalter und Titel nennen wir es “Ausgangswert”, die ID lautet l1.

Tabindex bestimmt die Reihenfolge, wohin die Selektion springt, sobald die Tabulatortaste gedrückt wird. Ich halte das vor allem bei großen Formularen für wichtig.

Dimensionsauswahl

Bei den Längen haben wir sechs Auswahlmöglichkeiten. Wir könne sogar Kilometer in Mikrometer umwandeln. Wichtig ist hier onchange=calcLengthen(). Außerdem steht bei Dezimeter selected als Vorauswahl.

Das Gute am Formular ist, dass wir keine Buttons brauchen. Alles passiert während der Benutzung.

JavaScript Vorwissen

Wenn Du mit dem oben verlinkten Beispiel ein wenig herumgespielt hast, sind Dir vielleicht drei Dinge aufgefallen.

  1. Es wird erst ein Ergebnis angezeigt, wenn eine Zahl im Feld eingegeben wurde.
  2. Größere Zahlen werden formatiert.
  3. Bei hohen Stellen wird das Resultat ungenau.

1 und 2 sind Features, 3 ist ein Problem.

JavaScript rechnet falsch

JavaScript ist eine praktische Programmiersprache, aber mit Mathe hat es ein Problem. Das geht aber nicht nur JavaScript so. Alle Sprachen, die Fließkommazahlen nach IEEE 754 implementieren, weisen Rundungsfehler auf. Wir verwenden den Datentyp Number. Das ist ein 64-Bit-Floating-Point-Datentyp. Jede Zahl wird in einer binären Exponential-Repräsentation abgebildet. Für Ganzzahl-Werte bedeutet dies, dass eine gesicherte Darstellung bis 15 Ziffern möglich ist, bevor Rundungsfehler auftreten. Um das Problem zu beheben, gibt es im Internet einige Bibliotheken, auf die ich bei diesem Beispiel bewusst verzichte, um es einfach zu halten. Es reicht an dieser Stelle, wenn Du weißt, dass es dieses Problem gibt.

Zahl Formatieren

Da wir später auf diese Funktionen zugreifen, stelle ich zunächst die “Hilfsfunktionen” vor. Eine kleine Funktion ist für die Formatierung der Zahl zuständig. In einem Formular kann es sehr oft auftreten, weshalb wir es auslagern. Außerdem kann es sein, dass wir irgendwann die Formatierung ändern. Dann haben wir nur eine Anlaufstelle.

Im Prinzip besteht die Funktion nur aus einer Zeile. Die Methode toLocaleString() gibt eine Zeichenkette mit einer sprachabhängigen Darstellung zurück. Mit den neuen Argumenten locales und options können Anwendungen die Sprache angeben, deren Formatierungskonventionen verwendet werden sollen, und das Verhalten der Funktion anpassen. Was die Zeile macht, ist die Formatierung der Zahlen auf 20 Stellen, indem es Punkte zur besseren Lesbarkeit einfügt. Ursprünglich gedacht war die Methode zur Formatierung von Zeitangaben.

Die Funktion kann man natürlich umschreiben. Etwa, dass es bei Tausendern die Zahl abschneidet und hinten “k” steht. Also 2k statt 2000.

Funktion der Umwandlung

Hier gibt es mehrere Möglichkeiten. Prinzipiell kann man diese Funktion auch in der Hauptfunktion (weiter unten) unterbringen. Ich habe mich aber für eine Auslagerung entschieden, weil mir die Handhabung, wenn man es bspw. um Flächen und Volumen ergänzt, einfacher erschien.

Das Logische Problem besteht darin, dass wir sechs Längenangaben haben, die man frei kombinieren kann. Das macht 30 Kombinationen, wenn man die Gleichen nicht berücksichtigt. Zwischen zwei Schritten gibt es aber immer einen Faktor, weshalb ich mich für folgende Funktion entschied:

Wirkt auf den ersten Blick komisch. Den Startpunkt habe ich bei Millimeter angesetzt. Von mm auf cm ist es 10, von mm auf dm 100 usw. Logischer erscheint auf den ersten Blick, Mikrometer als 1 zu nehmen, aber wenn wir es mit Flächen oder gar Volumen zu tun haben, laufen wir viel eher in das o. g. Rundungsproblem. Was hier aber genau passiert, verstehen wir besser, wenn wir die nächste Funktion anschauen.

Längenmaße umrechnen

Das ist die Funktion, die wir im Formular aufrufen. 

Damit holen wir uns den Wert aus dem Eingabefeld. Die Funktion parseFloat() parst ein Argument (und konvertiert es bei Bedarf zuerst in einen String) und gibt eine Fließkommazahl zurück. parseFloat parst Nicht-String-Objekte, wenn es eine toString- oder valueOf-Methode hat. Der zurückgegebene Wert ist derselbe, als ob parseFloat auf dem Ergebnis dieser Methoden aufgerufen worden wäre.

Das ist eines der Features. Wir schauen, ob das Feld leer ist. Die folgenden Anweisungen werden nur ausgeführt, wenn sich darin eine Zahl befindet. Die Funktion isNaN() ermittelt, ob ein Wert NaN ist oder nicht. Ob es das ist, erfahren wir von parseFloat.

Doch wann kommt das überhaupt vor? Schließlich haben wir den Typ number und rufen die Funktion nur auf, wenn eine Zahl eingegeben wird. Wirklich? Nein! Wir rufen sie auch auf, wenn jemand die Länge ändert, bspw. von Meter auf Millimeter. Wenn dann nichts im Feld steht, wird als Resultat NaN angezeigt. Das steht für “Not-A-Number” und sieht sehr unschön aus.

Wir schauen, welche Längen gewählt wurden und deklarieren außerdem die Variablen fac1, fac2 und result. Zur Erinnerung: Die let-Anweisung deklariert eine lokale Variable im Blockbereich und initialisiert sie optional mit einem Wert.

Nun holen wir uns unsere Faktoren aus der Funktion dimensionLengthen. Da wir sie zweimal aufrufen, hat sich die Auslagerung bereits gelohnt.

Nun rechnen wir. Der Eingegebene Wert wird durch Faktor 2 geteilt und mit Faktor 1 multipliziert. Das ist alles.

Wir schreiben das Ergebnis in das Feld mit der ID l2.

Beispiel

Noch einmal im Detail an einem konkreten Beispiel, um zu verstehen, was passiert.

Nehmen wir an, der User gibt als Wert 12 ein und will Meter in Millimeter umwandeln.

Faktor 1 ist Meter. dimension1 ist im Auswahlfeld “le2”. Mit fac1 = dimensionLengthen(dimension1) wollen wir wissen, was für einen Faktor “le2” nun hat. Die Funktion dimensionLengthen wird aufgerufen und die Switch gibt aus, dass “le2” 1000 ist. Also bekommt fac1 den Wert 1000 zugewiesen. Das Gleiche passiert mit fac2. dimension2 beinhaltet “le5” und “le5” ist 1. Somit haben wir unsere beiden Faktoren, nämlich 1000 und 1.

Das Resultat errechnen sich nun wie folgt: 12 / 1 * 1000. Wir erhalten als Ergebnis 12.000.

Temperaturen berechnen

Bei Temperaturen ist es nicht ganz so einfach, weil die Berechnungen immer anders sind. Von Celsius auf Kelvin wird anders gerechnet als von Celsius auf Fahrenheit. In so einem Fall bleibt uns nichts anderes übrig, als die Kombinationen einzeln zu berechnen.

Im Kern geht es so, wie bei den oberen Funktionen, nur haben wir statt einer Switch einzelne ifs. Da wir kelvin mehrmals brauchen, wurde es als Konstante definiert. Und eine Besonderheit gibt es noch.

Wenn die zwei Angaben identisch sind, wird nichts berechnet. 

Im Prinzip war es das auch schon.

Anmerkung

Vielleicht ist es Dir aufgefallen, falls Du die Tutorials hier alle liest, dass die Anzahl der Kombinationen in diesem Fall identisch ist der Berechnung von Ligen bzw. einem Ligaturnier. Die Formel lautet x2-x. So ergeben sich sechs Kombinationen bei den Temperaturen, wenn man zwei Auswahlfelder mit je drei Werten hat. Das ist zur Kontrolle, ob man etwas übersehen hat, sehr hilfreich.

Abonnieren
Benachrichtige mich bei
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x