MaxiG: Real time Rechner (AJAX/JS)

Hey zusammen,

ich habe ein "Problem".

Ich würde gerne in real time mit zwei Zahlen rechnen lassen.

Der User soll zwei Felder zur Verfügung haben. Dort sind zwei Mindestwerte bereits eingetragen.

Wenn er nun in Feld 1 beispielsweise 10 eingibt soll sich Feld automatisch mit einer hinterlegten Variable, beispielsweise 1,5, neu berechnen.

Das gleiche soll auch andersherum funktionieren, also wenn er in Feld 2 eine Zahl eingibt soll mit der hinterlegten Variable gerechnet werden und der Wert in Feld 2 eingetragen werden.

Bei den Größen geht es um Maße eines Produkts, es ändert sich also immer proportional, deshalb auch die Vorgabe der Variable.

Super wäre es natürlich, wenn man im Backend auch einer Ober- und Untergrenze festlegen kann, damit die Eingaben begrenzt werden - evtl. dann auch den Min./Max.-Wert mit entsprechendem Hinweis.

Bisher habe ich nur ein paar Zeilen, die zwar in Echtzeit rechnen, aber den Rest bekomme ich nicht so recht hin 😂

Eventuell kann mir ja jemand helfen 😀.

<html> <head> <title>Rechner</title> </head> <script type="text/javascript"> <!-- function calculate () { var wert1 = document.getElementById('feld1').value; var wert2 = document.getElementById('feld2').value; var erg1 = wert1 * wert2; document.getElementById('erg1').innerHTML = erg1; } </script> <body> <input type='text' id='feld1' onKeyUp='calculate()'> x <input type='text' id='feld2' onKeyUp='calculate()' value='2'> = <span id='erg1'></span> </body> </html>

Vielen Dank im Voraus 😀

LG

  1. @@MaxiG

    <html>

    Hier fehlt die Angabe der Sprache: <html lang="de">.

    Im head sollten noch die Angabe der verwendeten Zeichencodierung und die Viewportangabe stehen. ☞ Grundgerüst

    <script type="text/javascript"> <!--

    type="text/javascript" kannst du weglassen.

    <!-- solltest du weglassen! (Zumal bei dir auch das Ende des Kommentars fehlt.)

     

    var wert1 = document.getElementById('feld1').value; var wert2 = document.getElementById('feld2').value; var erg1 = wert1 * wert2;

    Was haben deine Debug-Versuche ergeben? Du hast keine unternommen?

    Lass dir mal die Werte ausgeben, z.B. mit console.log(wert1, wert2).

    Wenn du dann noch nicht siehst, was da los ist, deren Typen: console.log(typeof wert1, typeof wert2).

    Was kommt also als erg1 raus?

     

    <input type='text' id='feld1' onKeyUp='calculate()'> x <input type='text' id='feld2' onKeyUp='calculate()' value='2'> = <span id='erg1'></span>

    Die Eingabefelder sollten vom Typ "number" sein. (Dann kannst du auch Minimal- und Maximalwerte dafür angeben.)

    Die Eingabefelder müssen eine Beschriftung (label) haben! Ansonsten wissen bspw. blinde Nutzer nicht, was sie eingeben müssen. Ein einigen Spezialfällen (wovon das einer sein könnte) kann man das Label visuell verstecken.

    Das Ausgabefeld wäre gern ein output-Element (kein span) – auch mit Label.

    Und das Malzeichen sieht so aus: × (nicht ein x für ein × vormachen).

    LLAP 🖖

    PS: Mit AJAX hat das alles nichts zu tun.

    -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
    1. Tach!

      var wert1 = document.getElementById('feld1').value; var wert2 = document.getElementById('feld2').value; var erg1 = wert1 * wert2;

      Was haben deine Debug-Versuche ergeben? Du hast keine unternommen?

      Lass dir mal die Werte ausgeben, z.B. mit console.log(wert1, wert2).

      Wenn du dann noch nicht siehst, was da los ist, deren Typen: console.log(typeof wert1, typeof wert2).

      Die Typen sind nur die halbe Wahrheit. Javascript kann problemlos mit Strings rechnen - solange sich darin eine für Javascript gültige Zahl befindet.

      Was kommt also als erg1 raus?

      Zum Beispiel: "42" * "23" ergibt 966. Kommas allerdings sind kein Bestandteil von Zahlen und ein String mit Ziffern und Komma dazwischen ergibt NaN im numerischen Umfeld.

      Die Eingabefelder sollten vom Typ "number" sein. (Dann kannst du auch Minimal- und Maximalwerte dafür angeben.)

      Der Typ heißt number, Anführungszeichen sind kein Bestandteil des Typnamens sondern sind Begrenzer des Attributwertes (und in dem Fall sogar syntaktisch korrekt weglassbar).</präzisierung> Wenn wir schon immer auf den Unterschied zwischen Tag und Element hinweisen, müssen wir auch den Rest beachten.

      dedlfix.

  2. Hey zusammen,

    ich habe ein "Problem".

    Welches? Bitte beschreiben und zwar verständlich. Danke!

  3. Hallo MaxiG,

    deine fachliche Konzeption ist unklar.

    Du schreibst, dass Du zwei Eingabefelder möchtest, und wenn man im Feld X einen Wert ändert, soll gerechnet werden und dann Feld X mit diesem Wert überschrieben werden. Sicherlich ist das nicht das, was Du meinst, denn eine solche Anwendung wäre unbedienbar (ich will 12 eingeben, tippe die 1, du rechnest und machst eine 3 draus bevor ich die 2 eintippen konnte).

    Dein gezeigter Code ist ganz anders. Du hast zwei Eingabefelder, und bei jeder Änderung in einem der beiden Felder berechnest Du einen neuen Wert und setzt ihn in ein span Element ein. Das ist sinnvoller. Allerdings ist in diesem Code keine Rede mehr von Variablen, deren Wert in die Berechnung eingehen soll.

    Zur Umsetzung:

    • du solltest Dich nicht auf das keyup Event registrieren. Für den von Dir beabsichtigten Zweck ist das input-Event vorgesehen. Es feuert auch dann, wenn der Anwender mit Cut+Paste einen Wert ins Feld einsetzt. Das ist bei keyup nicht der Fall.
    • wenn Du Zahlen mit Dezimalstellen erwartest, dann kannst Du zum einen nicht input type="number" verwenden - das kann nur ganze Zahlen. Und zum anderen musst Du Dir über die Zahlendarstellung klar werden. Standardmäßig verwendet JavaScript einen Dezimalpunkt und interpretiert das Komma als ungültiges Zeichen, d.h. der Wert von "1,234" wäre 1. Du musst also folgendes überlegen:
      • soll das Zeichen "," als Dezimaltrennzeichen dienen?
      • soll das Zeichen "." als Dezimaltrennzeichen dienen?
      • willst Du auch ein Tausendertrennzeichen akzeptieren können?

      Diese so harmlose Frage ist ein hochkomplexes Thema, weil jeder Anwender ein anderes Gefühl dafür hat, was richtig ist und was falsch. Was bedeutet 1.234? Eintausendzweihundertvierunddreißig? Eins Punkt zwei drei vier, im Sinne von \frac{1234}{1000}? Ist 1,234.56 eine richtige Eingabe? Ist 1.234,56 richtig? Was ist mit dem Schweizerischen 1'234.561?

      Die einfachste Lösung ist, sowohl Punkt als auch Komma als Dezimaltrennzeichen zu akzeptieren und die Anwender per Hinweis auf der Maske aufzufordern, keine Tausendertrennzeichen zu verwenden.

      Eine gewisse Absicherung der Eingabe kannst Du über das pattern-Attribut des input-Elements bekommen. Damit kannst Du einen regulären Ausdruck angeben, den die Eingabe erfüllen muss. Der ist nicht ganz trivial, denn du musst ja Eingaben wie "123", "123.", ".123" und "123.456" akzeptieren, aber "." nicht. Mein Pattern für solche Fälle ist "(?![.,]$)\d([.,]\d)?". Input-Patterns werden recht gut unterstützt. Mit dem Pattern kannst Du im JavaScript die Gültigkeit abfragen. Alte Browser, die pattern nicht kennen, lassen dann falsche Eingaben durch und die Rechnung ergibt ggf. Blödsinn. Aber bei richtigen Eingaben kommt auch das richtige heraus. Es ist deine Entscheidung, wie streng du das nehmen willst.

    var eingabe1 = document.getElementById('feld1').value.replace(',', '.'); var wert1 = parseFloat(eingabe1); if (wert1 < minimum || wert1 > maximum) { // Bereichsfehler, man sollte eine Fehlermeldung anzeigen eingabe1.setCustomValidity("Wert muss im Bereich ... bis ... liegen"); } if (eingabe1.validity && !eingabe1.validity.valid) { // fehler, man könnte hier bspw. einfach das Script verlassen. return; }

    setCustomValidity ist Teil des Constraint Validation API, das vom IE11 noch nicht vollständig unterstützt wird. Wenn Du Dich mit diesem API nicht herumschlagen willst, verwende für Fehlermeldungen bei Falscheingaben einfach ein weiteres Ausgabefeld. Aber: Eingabeüberprüfungen sind wichtig. Auf die kann man nicht eben mal so verzichten. Leider besteht ein großer Teil von Programmen, die Benutzerdaten empfangen, daraus.

    Für weitere Ratschläge müsstest Du deine fachliche Anforderung konkretisieren. Wieviele Eingabefelder hast Du? Wieviele Ausgabefelder? Was genau soll bei einer Eingabe in ein Eingabefeld passieren (ich gebe in Feld 1 eine Ziffer ein. Daraufhin wird .... berechnet. Das Ergebnis wird in Feld ... geschrieben)

    Wenn Du Werte für deine Berechnung brauchst, die der Benutzer nicht eingibt, dann müsstest du sagen können, wo die herkommen.

    Rolf

    1. Nein, Gunnar, nicht 1’234.56.

    -- sumpsi - posui - clusi
    1. @@Rolf B

      wenn Du Zahlen mit Dezimalstellen erwartest, dann kannst Du zum einen nicht input type="number" verwenden - das kann nur ganze Zahlen.

      Hier irrst du. Das step-Attribut existiert.

      LLAP 🖖

      -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
    2. Tach!

      • wenn Du Zahlen mit Dezimalstellen erwartest, dann kannst Du zum einen nicht input type="number" verwenden - das kann nur ganze Zahlen.

      Das Attribut step existiert und wenn man dem zum Beispiel 0.01 gibt, kann man zwei Nachkommastellen eingeben.

      d.h. der Wert von "1,234" wäre 1.

      Der ist NaN bei einem einfachem Typecast zu Number (z.B: "1,234" * 1). Aber parseFloat() nimmt alles bis zum ersten Nicht-Ziffer-Zeichen.

      Eine gewisse Absicherung der Eingabe kannst Du über das pattern-Attribut des input-Elements bekommen.

      Nah, lieber nicht so umständlich. Dann lieber type="text" und wenn parseFloat() was draus lesen kann, ist es gut, sonst Pech gehabt.

      dedlfix.

      1. @@dedlfix

        Nah, lieber nicht so umständlich. Dann lieber type="text" und wenn parseFloat() was draus lesen kann, ist es gut, sonst Pech gehabt.

        Dann lieber type="number" und bei der Eingabe , in . verwandeln.

        LLAP 🖖

        -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
    3. Idee: 1 Formular mit 2 Eingabefeldern. Das Submit-Event abfangen und bei der Gelegenheit feststellen, welches Eingabefeld den Fokus hat. Damit steht fest von welchem Feld die Berechnung ausgeht und in welches Feld das Ergebnis muss. MFG

    4. zum anderen musst Du Dir über die Zahlendarstellung klar werden. Standardmäßig verwendet JavaScript einen Dezimalpunkt und interpretiert das Komma als ungültiges Zeichen, d.h. der Wert von "1,234" wäre 1.

      Wenn man input type="number" verwendet, was wie gesagt sinnvoll ist, muss man das nicht. Der Browser akzeptiert dann Eingaben in der jeweiligen Locale. Z.B. ein deutschsprachiges Betriebssystem, ein deutschsprachiger Browser akzeptiert "1,234" und erkennt es als 1,234.

      Die einfachste Lösung ist, sowohl Punkt als auch Komma als Dezimaltrennzeichen zu akzeptieren und die Anwender per Hinweis auf der Maske aufzufordern, keine Tausendertrennzeichen zu verwenden.

      Die einfachste Lösung wäre, das dem Browser zu überlassen. Der kennt das eingestellte Locale und akzeptiert entsprechende Eingaben.

      Wie die Browser mit dem jeweils »falschen« Dezimaltrenner umgehen, ist unterschiedlich. Manche akzeptieren das Zeichen als Dezimaltrenner, manche unterdrücken deren Eingabe, in manchen wird dadurch die Eingabe invalide.

      In all diesen Fällen würde ich nichts tun, nur wie gewohnt dafür sorgen, dass das invalide Feld ersichtlich wird. (Dann sollte auch kein setCustomValidity nötig sein.)

      var eingabe1 = document.getElementById('feld1').value.replace(',', '.'); var wert1 = parseFloat(eingabe1);

      Worum so umständlich? Es gibt dafür valueAsNumber:

      https://codepen.io/anon/pen/jjbBEZ?editors=1010

      Urmel

  4. Hey zusammen, zunähst mal vielen Dank für die ganzen Hilfestellungen und entschuldigt die fehlenden Infos - meine HTML-Zeit ist schon etwas her und dann kommt dazu, dass dies mein erste Post mit einer expliziten Code-Frage ist 😂. Ein paar Dinge habe ich nun bereits angepasst - habe dennoch hier mal kurz eine kleine Ansicht zusammengepfuscht anhand derer evtl. etwas verständlicher ist, was gewünscht ist.

    Wie ihr seht sind in Feld 1 und Feld 2 Werte vorgegeben - das Feld erg1 im Code war lediglich eine Überprüfung der Rechnung.

    Also, um auf das Bild einzugehen. Der User öffnet die Seite und sieht den Text "Bitte geben Sie Ihr gewünschtes Maß an". Darunter dann lediglich 2 Felder mit beispielsweise den beiden zahlen 10 & 16 vorausgefüllt, wobei hier der Faktor 1,5 angesetzt ist.

    Der User kann nun sowohl in Feld 1 als auch in Feld 2 Eingaben vornehmen, bedeutet also: - bei einer Eingabe in Feld 1 wird Feld 2 live mit dem Faktor *1,5 berechnet und der alte Wert überschrieben - bei einer Eingabe in Feld 2 wird Feld 1 live mit dem Faktor /1,5 berechnet und der alte Wert überschrieben

    Gut wäre es, wie geschrieben, wenn sowohl Punkte als auch Kommas als Trennzeichen erkannt werden - in die Tausend werden die Werte nicht gehen, von daher fällt das flach. Nachkommastellen soll es lediglich eine geben 😀

    1. Hallo MaxiG,

      https://jsfiddle.net/Rolf_b/9gybe7tu/

      Begrenzung der möglichen Werte nach oben und unten sei als leichte Übung dem Leser überlassen. (Prof-Sprech für „hab ich grad keinen Bock drauf“).

      Bei Fragen zu den verwendeten Techniken kannst Du Dich gerne melden, und sicherlich werden noch von anderen diverse Vorschläge kommen.

      Rolf

      -- sumpsi - posui - clusi
      1. @@Rolf B

        https://jsfiddle.net/Rolf_b/9gybe7tu/

        … und sicherlich werden noch von anderen diverse Vorschläge kommen.

        Sicherlich. 😏

        Math.round(getFieldValue(eBreite) * faktor * 10) / 10 ist hier nicht sinnvoll; getFieldValue(eBreite).toFixed(1) leistet dasselbe – mit besser lesbarem Code. (Am Ende wird’s ja sowieso ein String als Wert des value-Attributs.) Dasselbe für eHöhe.

        eBreite, eHöhe?? Was soll das e da im Bezeichner? Und warum sind die Variablen deutsch benamst, die Funktionen aber englisch?

        LLAP 🖖

        -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
        1. @@Gunnar Bittersmann

          eBreite, eHöhe?? Was soll das e da im Bezeichner? Und warum sind die Variablen deutsch benamst, die Funktionen aber englisch?

          German Naming Convention

          LLAP 🖖

          -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
        2. Hallo Gunnar,

          .toFixed - verdammt, ich habe Math nach einer "runde auf 1 Dezimalstelle" Funktion durchflöht und war total sauer, dass es die nicht gab.

          Das e-Prefix ist ungarisch für Element. Und ja, ich hätte wohl eWidth, eHeight etc. verwenden sollen. Aber mein Code ist öfter mal denglisch (leseComponent) beziehungsweise englutsch (getBreite).

          Diese "german notation" nenne ich für mich gerne COBOL-Stil. Programmieren mit Anspruch auf den Pulitzer-Preis.

          Rolf

          -- sumpsi - posui - clusi
          1. Hi,

            ... durchflöht

            das habe ich ja noch nie gehört. Nice. ;-)

            Das e-Prefix ist ungarisch für Element.

            Oh. Ich hatte vermutet, es soll für Eingabe stehen. Die ungarische Notation hat IMO den Nachteil, dass die Präfixe den Datentyp angeben. Viel hilfreicher finde ich ein Präfix, das auf den Verwendungszweck z.B. einer Variablen hinweist.

            Aber mein Code ist öfter mal denglisch (leseComponent) beziehungsweise englutsch (getBreite).

            Diese Durchmischung sieht man oft - gefällt mir deswegen aber nicht besser.

            Programmieren mit Anspruch auf den Pulitzer-Preis.

            Ein Kollege von mir heißt mit Nachnamen Puljić - der hat vor ein paar Jahren von der Truppe mal den Puljićer-Preis als Anerkennung bekommen. :-)

            Ciao,
             Martin

            -- Ein Tag, an dem du nicht wenigstens einmal gelacht hast, ist ein verlorener Tag.
            1. Tach!

              Die ungarische Notation hat IMO den Nachteil, dass die Präfixe den Datentyp angeben. Viel hilfreicher finde ich ein Präfix, das auf den Verwendungszweck z.B. einer Variablen hinweist.

              Die Information zum Typ war damals wichtig, als man noch auf dem Papier programmiert hat. Heutzutage hält man den Mauszeiger auf den Code und bekommt diese und weitere Information von der IDE angezeigt. Springen zur Deklaration und Suchen/Hervorheben, wo der Name überall vorkommt, sind weitere Mittel, die der vorangestellten Typinformation den Rang abgelaufen haben.

              dedlfix.

          2. @@Rolf B

            .toFixed - verdammt, ich habe Math nach einer "runde auf 1 Dezimalstelle" Funktion durchflöht und war total sauer, dass es die nicht gab.

            Weiß auch nicht, warum man bei Math.round() keinen Parameter für die Genauigkeit angeben kann.

            Das e-Prefix ist ungarisch für Element. Und ja, ich hätte wohl eWidth, eHeight etc. verwenden sollen.

            Nein.

            Bei mir hießen die widthInputElement und heightInputElement. Noch Fragen? Eben.

            LLAP 🖖

            -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
    2. Hallo,

      beispielsweise den beiden zahlen 10 & 16 vorausgefüllt, wobei hier der Faktor 1,5 angesetzt ist.

      Ohne das gerechnet zu haben, hätte ich hier einen Faktor von ca. 1.6 erwartet....

      Gruß
      Kalk

    3. Der User kann nun sowohl in Feld 1 als auch in Feld 2 Eingaben vornehmen, bedeutet also: - bei einer Eingabe in Feld 1 wird Feld 2 live mit dem Faktor *1,5 berechnet und der alte Wert überschrieben - bei einer Eingabe in Feld 2 wird Feld 1 live mit dem Faktor /1,5 berechnet und der alte Wert überschrieben

      Das ist dann wohl eher ein Problem der Benutzerführung. Also dem Benutzer diese Anwendung so zu erklären daß er sie versteht und so zu designen daß ein Benutzer intuitiv damit umgehen kann. Und das wird schwierig. MFG

      1. @@pl

        Das ist dann wohl eher ein Problem der Benutzerführung. Also dem Benutzer diese Anwendung so zu erklären daß er sie versteht und so zu designen daß ein Benutzer intuitiv damit umgehen kann. Und das wird schwierig.

        Wird es das?

        Photoshop-Benutzer können damit umgehen:

        Einstellung von Bildbreite und -höhe, beides gekoppelt

        LLAP 🖖

        -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
        1. @@pl

          Das ist dann wohl eher ein Problem der Benutzerführung. Also dem Benutzer diese Anwendung so zu erklären daß er sie versteht und so zu designen daß ein Benutzer intuitiv damit umgehen kann. Und das wird schwierig.

          Wird es das?

          Ja. Weil: Ein Benutzer erwartet intuitiv, daß mit dem Wert gerechnet wird den er grad eben eingegeben hat in das Eingabefeld wo auch sein Cursor drinsteht. Ein Benutzer erwartet nicht, daß die Anwendung mit einem Wert rechnet der sich in einem anderen Eingabefeld befindet.

          MFG

          1. Du hast das Kettensymbol zwischen den beiden Eingabefeldern gesehen?

          2. @@pl

            Ein Benutzer erwartet intuitiv, daß mit dem Wert gerechnet wird den er grad eben eingegeben hat in das Eingabefeld wo auch sein Cursor drinsteht. Ein Benutzer erwartet nicht, daß die Anwendung mit einem Wert rechnet der sich in einem anderen Eingabefeld befindet.

            Allgemein hast du damit recht.

            In Spezialfällen ist es aber für Nutzer nachvollziehbar, dass zwei Werte voneinander abhängen. Bildbreite und -höhe dürfte solch ein Fall sein.

            LLAP 🖖

            -- „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann