Gaël: NaN ausgabe ändern

Hallo, ich vollziehe gerade meine ersten Geh versuche mit Javascript. Was mich stört ist wenn ich in einem HTML Formular drei INPUT Eingabefelder habe und noch nicht alle Werte eingegeben wurden, kommt in der Ergebnis Zeile NaN. Ich habe gelesen das dies kein Fehler ist, doch würde ich diese Ausgabe gerne in etwa „noch nicht alle Daten eingegeben“ ändern. Oder sollte ich statt dessen lieber vorher alle Variablen die Abgefragt werden in Zahlen umwandeln, so dass leer Felder in 0 umgewandelt werden. (Ob das NaN unterbinden weis ich allerdings nicht)

function calculate() {
input1 = parseFloat( document.formu.input1.value.replace(/,/ , ".") );
input2 = parseFloat( document.formu.input2.value.replace(/,/ , ".") );
input3 = parseFloat( document.formu.input3.value.replace(/,/ , ".") );
	
document.getElementById("output").innerHTML= (input1 * input2 * input3).toString().replace(/\./ , ",");
}
  1. Tach!

    Was mich stört ist wenn ich in einem HTML Formular drei INPUT Eingabefelder habe und noch nicht alle Werte eingegeben wurden, kommt in der Ergebnis Zeile NaN. Ich habe gelesen das dies kein Fehler ist, doch würde ich diese Ausgabe gerne in etwa „noch nicht alle Daten eingegeben“ ändern.

    Wenn-Dann. Ein ziemlich häufiges Muster beim Programmieren. Die Aufgabe eines Programmierer ist es, all diese Wenn-Dann-Situationen zu erkennen und entsprechenden Code einzubauen, mit diesen Situationen angemessen umzugehen.

    Oder sollte ich statt dessen lieber vorher alle Variablen die Abgefragt werden in Zahlen umwandeln, so dass leer Felder in 0 umgewandelt werden. (Ob das NaN unterbinden weis ich allerdings nicht)

    Wäre es denn für deinen Anwendungsfall sinnvoll, mit 0 zu rechnen? Oder ist es nicht vielmehr so, dass das Ergebnis nicht definiert werden kann, wenn nicht alle Eingabewerte vorliegen? Dann wäre, wenn mindestens eines der drei Felder NaN ist, die Ausgabe entsprechend zu gestalten. Ich würde allerdings das output-Feld leer lassen, und die Fehlermeldung - wenn eine angezeigt werden soll - separat ausgeben, denn die Fehlermeldung ist ja kein Wert, der entstehen soll.

    dedlfix.

  2. Hallo Gaël,

    es gibt das Number-Objekt, und darauf eine Methode isNaN, mit der Du prüfen kannst, ob ein Wert NaN ist.

    Aber was willst Du eigentlich prüfen? Ob das Feld leer ist? Was machst Du, wenn jemand "Hallo" statt "42" eingibt, oder "12 Stück"? Gerade das letzte Beispiel ist böse, denn parseFloat("12 Stück") liefert ganz unschuldig die Zahl 12.

    Du musst deine Eingaben validieren. Dafür ist isNaN der falsche Weg, du solltest statt dessen Folgendes tun:

    Setze das required-Attribut des <input> Elements. Damit ist es ein Pflichtfeld.

    Setze das pattern-Attribut des <input> Elements. Da kannst Du eine Regex eintragen, und der Browser prüft, ob die Eingabe dazu passt. Ein einfaches Pattern wäre "\s*\d+(,\d*)?\s*". Das sind: 0-n Leerstellen, 1-n Ziffern und dann optional ein Nachkommateil mit einem Komma und 0-n Ziffern. Dahinter können wieder Spaces folgen.

    Definiere im CSS eine Visualisierung für ungültige Inputs. Das geht z.B. mit dem Selektor input:not(:valid). Du könntest einem ungültigen Input zum Beispiel einen roten Hintergrund geben, oder ein rotes Outline.

    Prüfe im JavaScript nochmals die Gültigkeit der Eingabe. Dazu wendest Du dich an das form, dort gibt es die Methode checkValidity. Sie liefert true, wenn die Prüfbedingungen aller Eingabefelder zutreffen. Weil Du required und ein pattern gesetzt hast, liefert diese Methode nur true, wenn alle Eingabefelder ausgefüllt sind und dem Pattern entsprechen.

    Das folgende Beispiel zeigt die Bausteine. Die Verdrahtung der calculate-Methode ist auf verschiedene Arten möglich, das überlasse ich dir :) Das form ist aber sinnvoll, weil Du andernfalls die Gültigkeit aller Eingabefelder einzeln prüfen musst (validity.valid Eigenschaft der input Elemente).

    HTML

    <form name="formu" action="#">      <!-- form ohne Action -->
       <label>Eingabe 1: <input type="text" name="input1" required pattern="\s*\d+(,\d*)?\s*"></label>
       <label>Eingabe 2: <input type="text" name="input2" required pattern="\s*\d+(,\d*)?\s*"></label>
       <label>Eingabe 3: <input type="text" name="input3" required pattern="\s*\d+(,\d*)?\s*"></label>
    </form>
    

    CSS

    label { display: block;}
    input:not(:valid) { background-color: #ff8888; }
    

    Script

    function calculate(event) {
       let theForm = document.forms.formu;     // für <form name="formu">
    
       if (!theForm.checkValidity()) {
          document.getElementById("output").innerHTML = "Nicht gültig";
          return;
       }
       
       let val1 = parseFloat(theForm.input1.value);    // Gelingt immer wegen Validity
       let val2 = parseFloat(theForm.input2.value);
       let val3 = parseFloat(theForm.input3.value);
       
       document.getElementById("output").innerHTML = val1 * val2 * val3;
    };
    

    Rolf

    --
    sumpsi - posui - clusi
    1. Tach!

      es gibt das Number-Objekt, und darauf eine Methode isNaN, mit der Du prüfen kannst, ob ein Wert NaN ist.

      isNaN() ist auch eine globale Funktion.

      Aber was willst Du eigentlich prüfen? Ob das Feld leer ist? Was machst Du, wenn jemand "Hallo" statt "42" eingibt, oder "12 Stück"? Gerade das letzte Beispiel ist böse, denn parseFloat("12 Stück") liefert ganz unschuldig die Zahl 12.

      Die Frage ist: Stört das in dem Fall? Muss es unbedingt eine astreine Zahleneingabe sein, oder reicht es, dass der eingegebene Wert irgendwie in eine Zahl konvertiert werden kann? In dem Fall halte ich es für verschmerzbar, dass Javascript nachfolgende Nicht-Ziffern einfach ignoriert.

      Du musst deine Eingaben validieren. Dafür ist isNaN der falsche Weg,

      Das sehe ich in dem Fall nicht so und halte isNaN() in dem Fall für eine geeignete Funktion.

      du solltest statt dessen Folgendes tun:

      Das kann man auch machen - wenn es wirklich darauf ankommt. Und wenn man davon ausgeht, dass der Browser nicht zu alt ist und auf <input type=text> zurückfällt.

      dedlfix.

    2. Hallo Rolf,

      Du musst deine Eingaben validieren. Dafür ist isNaN der falsche Weg, du solltest statt dessen Folgendes tun:

      Setze das required-Attribut des <input> Elements. Damit ist es ein Pflichtfeld.

      Setze das pattern-Attribut des <input> Elements.

      Warum nicht gleich input type="number"? Das vereinfacht doch einiges, z.B. das Nachdenken über eine passende Regexp-Pattern.

      Definiere im CSS eine Visualisierung für ungültige Inputs. Das geht z.B. mit dem Selektor input:not(:valid). Du könntest einem ungültigen Input zum Beispiel einen roten Hintergrund geben, oder ein rotes Outline.

      Prüfe im JavaScript nochmals die Gültigkeit der Eingabe. Dazu wendest Du dich an das form, dort gibt es die Methode checkValidity. Sie liefert true, wenn die Prüfbedingungen aller Eingabefelder zutreffen. Weil Du required und ein pattern gesetzt hast, liefert diese Methode nur true, wenn alle Eingabefelder ausgefüllt sind und dem Pattern entsprechen.

      Viele Grüße
      Robert

      1. Hallo Robert und dedlfix,

        • input type="number" fügt up/down Buttons hinzu. Mich nerven die.
        • pattern und required sind ab IE10 verfügbar. Ältere Browser ignorieren sie. Ok. PE@work.
        • ggf. müsste man das JS so ändern, dass es die Existenz der checkValidity Methode am Form prüft oder polyfillt.
        • Eingaben zu validieren halte ich nie für sinnlos. Wenn ich Zahlen möchte, dann sollen auch Zahlen eingegeben werden.

        Rolf

        --
        sumpsi - posui - clusi
        1. Hallo,

          • input type="number" fügt up/down Buttons hinzu. Mich nerven die.

          kommt drauf an. Mich stören sie nicht, solange die direkte Eingabe nicht verhindert wird.

          • pattern und required sind ab IE10 verfügbar. Ältere Browser ignorieren sie. Ok. PE@work.

          Yo. Wer einen solchen Browser verwendet, wird sich über den Gewinn an Usability freuen.

          • Eingaben zu validieren halte ich nie für sinnlos. Wenn ich Zahlen möchte, dann sollen auch Zahlen eingegeben werden.

          Ja. trotzdem möchte man eine gewisse Fehlertoleranz. Ich denke da beispielsweise an eine semi-intelligente Erkennung des verwendeten Dezimal-Trennzeichens (Punkt vs. Komma).

          So long,
           Martin

          --
          "Wenn man ein Proton aufmacht, sind drei Quarks drin."
          - Joachim Bublath in der Knoff-Hoff-Show
        2. @@Rolf B

          • input type="number" fügt up/down Buttons hinzu. Mich nerven die.

          Dann mach sie weg.

          Vorteile der Verwendung von <input type="number">:

          • bei virtuellen Tastaturen wird ein der Eingabe von Zahlen angemessenes Tastaturlayout dargestellt
          • . und , können gleichermaßen als Dezimaltrennzeichen verwendet werden, ohne dass man da was umwandeln muss

          Nachteile:

          • In manchen Browsern (z.B. Firefox und Safari) können nicht mehr Nachkommastellen angegeben werden als im step-Attribut angegeben. Das kann allerdings auch ein Vorteil sein.

          LLAP 🖖

          --
          „Man kann sich halt nicht sicher sein“, sagt der Mann auf der Straße, „dass in einer Gruppe Flüchtlinge nicht auch Arschlöcher sind.“
          „Stimmt wohl“, sagt das Känguru, „aber immerhin kann man sich sicher sein, dass in einer Gruppe Rassisten nur Arschlöcher sind.“

          —Marc-Uwe Kling
          1. Moin,

            Vorteile der Verwendung von <input type="number">:

            • bei virtuellen Tastaturen wird ein der Eingabe von Zahlen angemessenes Tastaturlayout dargestellt

            Der Smartphone-Nutzer nickt zustimmend …

            Viele Grüße
            Robert

    3. Hallo Rolf B,

      Definiere im CSS eine Visualisierung für ungültige Inputs. Das geht z.B. mit dem Selektor input:not(:valid).

      oder :invalid

      Bis demnächst
      Matthias

      --
      Pantoffeltierchen haben keine Hobbys.
      ¯\_(ツ)_/¯