Umgang mit Gleitkommazahlen und Dezimaltrennzeichen mit HTML5-Eingabetypnummer

127

Ich baue eine Web-App, die hauptsächlich für mobile Browser ist. Ich verwende Eingabefelder mit Nummerntyp, daher rufen (die meisten) mobilen Browser zur besseren Benutzererfahrung nur die Zifferntastatur auf. Diese Web-App wird hauptsächlich in Regionen verwendet, in denen das Dezimaltrennzeichen ein Komma und kein Punkt ist. Daher muss ich beide Dezimaltrennzeichen verarbeiten.

Wie kann man dieses ganze Durcheinander mit Punkt und Komma abdecken?

Meine Ergebnisse:

Desktop Chrome

  • Eingabetyp = Nummer
  • Der Benutzer gibt "4,55" in das Eingabefeld ein
  • $("#my_input").val(); gibt "455" zurück
  • Ich kann nicht den richtigen Wert von der Eingabe erhalten

Desktop Firefox

  • Eingabetyp = Nummer
  • Der Benutzer gibt "4,55" in das Eingabefeld ein
  • $("#my_input").val(); gibt "4,55" zurück
  • Das ist in Ordnung, ich kann Komma durch Punkt ersetzen und den richtigen Float erhalten

Android-Browser

  • Eingabetyp = Nummer
  • Der Benutzer gibt "4,55" in das Eingabefeld ein
  • Wenn die Eingabe den Fokus verliert, wird der Wert auf "4" gekürzt.
  • Verwirrend für den Benutzer

Windows Phone 8

  • Eingabetyp = Nummer
  • Der Benutzer gibt "4,55" in das Eingabefeld ein
  • $("#my_input").val(); gibt "4,55" zurück
  • Das ist in Ordnung, ich kann Komma durch Punkt ersetzen und den richtigen Float erhalten

Was sind die "Best Practices" in solchen Situationen, in denen der Benutzer möglicherweise Komma oder Punkt als Dezimaltrennzeichen verwendet und ich den HTML-Eingabetyp als Zahl beibehalten möchte, um eine bessere Benutzererfahrung zu erzielen?

Kann ich Komma "on the fly" in Punkt umwandeln, um Schlüsselereignisse zu binden? Funktioniert es mit Zahleneingaben?

BEARBEITEN

Derzeit habe ich keine Lösung, wie man den Gleitkommawert (als Zeichenfolge oder Zahl) von der Eingabe erhält, deren Typ auf Zahl gesetzt ist. Wenn der Endbenutzer "4,55" eingibt, gibt Chrome immer "455" zurück, Firefox gibt "4,55" zurück, was in Ordnung ist.

Es ist auch ziemlich ärgerlich, dass in Android (getesteter 4.2-Emulator) die eingegebene Zahl auf "4" gekürzt wird, wenn ich "4,55" in das Eingabefeld eingebe und den Fokus auf eine andere Stelle ändere.

Devha
quelle
Ich vermute, die Hauptursache für einige Ihrer Probleme ist, dass die Browser auf ein US-Gebietsschema eingestellt sind, das den Punkt als Dezimaltrennzeichen verwendet. Es scheint, als würden Chrome und Android dadurch auf unterschiedliche Weise verwirrt - Chrome behandelt das Komma als Zifferntrennzeichen, konvertiert dann die Eingabe in eine Zahl, konvertiert sie dann erneut in eine Zeichenfolge .val()und Android macht etwas Seltsames. Können Sie überprüfen, ob sie sich gleich verhalten, wenn Sie die Systemsprache auf einen geeigneten Wert einstellen?
Millimoose
1
Nvm hat dies als Antwort gepostet
kjetilh
Siehe auch hier: stackoverflow.com/a/24423879/196210
Revious
Die Situation ist noch schlimmer als dargestellt: Sie erhalten einen Dezimalpunkt oder ein Komma auf dem WP-Nummernblock, abhängig von der Sprache, in der Sie Ihre Tastatur ausgewählt haben. Es gibt auch keine Möglichkeit herauszufinden, welches das Eingabegebietsschema war (nicht unbedingt die bevorzugte Browsersprache) ... Das Beste, was ich mir einfallen lassen konnte (und was für mich gut genug ist), ist: var number = $(...).get(0).valueAsNumber; if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.'); Aber diese Lösung funktioniert nur, wenn das Die
eingegebene

Antworten:

107

Ich denke, was in den obigen Antworten fehlt, ist die Notwendigkeit, einen anderen Wert für das stepAttribut anzugeben , der einen Standardwert von hat 1. Wenn der Validierungsalgorithmus der Eingabe Gleitkommawerte zulassen soll, geben Sie einen entsprechenden Schritt an.

Zum Beispiel wollte ich Dollarbeträge, also habe ich einen Schritt wie diesen angegeben:

 <input type="number" name="price"
           pattern="[0-9]+([\.,][0-9]+)?" step="0.01"
            title="This should be a number with up to 2 decimal places.">

Es ist nichts Falsches daran, den Wert mit jQuery abzurufen, aber Sie werden es nützlich finden, die DOM-API direkt zu verwenden, um die validity.validEigenschaft der Elemente abzurufen .

Ich hatte ein ähnliches Problem mit dem Dezimalpunkt, aber der Grund, warum ich feststellte, dass es ein Problem gab, war das Styling, das Twitter Bootstrap einer Zahleneingabe mit einem ungültigen Wert hinzufügt.

Hier ist eine Geige, die zeigt, dass das Hinzufügen des stepAttributs funktioniert, und auch testet, ob der aktuelle Wert gültig ist:

TL; DR: Setzen Sie das a- stepAttribut auf einen Gleitkommawert, da es standardmäßig verwendet wird 1.

HINWEIS : Das Komma wird für mich nicht überprüft, aber ich vermute, dass es funktionieren würde, wenn ich die Einstellungen für die Sprache / Region meines Betriebssystems auf einen Ort setze, an dem ein Komma als Dezimaltrennzeichen verwendet wird. * Anmerkung in Anmerkung *: Dies war bei Betriebssystem- / Tastatureinstellungen nicht der Fall. * Deutsch * in Ubuntu / Gnome 14.04.

Natchiketa
quelle
8
Wenn Sie beliebig viele Dezimalstellen zulassen möchten, geben Sie das stepAttribut "any"anstelle von z "0.01". B. wie hier gezeigt an. Sehen Sie sich diese optimierte Version von Nathciketas Geige für eine Demo an.
Mark Amery
4
Ich bin auch auf Probleme mit Kommas gestoßen, die nicht validiert wurden, obwohl ich "1.234,56" eingegeben habe <input type="number" step="any">. Ich konnte keine Möglichkeit finden, die HTML5-Validierung zu deaktivieren. Ich kann die Fehlermeldung deaktivieren oder anpassen, aber das Abrufen des Werts von der Eingabe ist immer ein Crapshoot. Irgendwelche Ideen?
Nick G.
5
This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.Also Muster ist nutzlos mittype="number"
Michael Laffargue
Wie Michael sagte, bitte ändern Sie das typein text, sonst macht Ihre Antwort keinen Sinn.
Phil294
23

Nach w3.org der Wert Attribut der Nummer eingegeben wird , als definierter Gleitkommazahl . Die Syntax der Gleitkommazahl scheint nur Punkte als Dezimaltrennzeichen zu akzeptieren.

Ich habe nachfolgend einige Optionen aufgeführt, die für Sie hilfreich sein könnten:

1. Verwenden des Musterattributs

Mit dem Musterattribut können Sie das zulässige Format mit einem regulären Ausdruck auf HTML5-kompatible Weise angeben. Hier können Sie angeben, dass das Kommazeichen zulässig ist, und eine hilfreiche Rückmeldung erhalten, wenn das Muster fehlschlägt.

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" name="my-num"
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

Hinweis: browserübergreifende Unterstützung ist sehr unterschiedlich. Es kann vollständig, teilweise oder nicht vorhanden sein.

2. JavaScript-Validierung

Sie könnten versuchen, einen einfachen Rückruf beispielsweise an den Wechsel (und / oder die Unschärfe) zu binden ) Fall , dass das Komma entweder ersetzen würde oder alle zusammen validieren.

3. Deaktivieren Sie die Browserüberprüfung ##

Drittens könnten Sie versuchen, das Attribut formnovalidate für die Zahleneingaben zu verwenden, um die Browserüberprüfung für dieses Feld insgesamt zu deaktivieren.

<input type="number" formnovalidate />

4. Kombination ..?

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" 
           name="my-num" formnovalidate
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>
kjetilh
quelle
2
input.valueAsNumber - Keine Hilfe, da dies nur mit Punkten als Dezimaltrennzeichen funktioniert und in meinem Fall der Endbenutzer möglicherweise Punkte oder Kommas verwendet. Formular-Tag novalidate - Es wurden keine Auswirkungen darauf festgestellt.
Devha
Leider gehen mir die Ideen aus, daher bin ich mir nicht sicher, ob Sie diese Funktion ohne eine Problemumgehungslösung browserübergreifend ausführen können. Ich habe meine Antwort aktualisiert, um das Musterattribut aufzunehmen , von dem ich auch festgestellt habe, dass man das formnovalidate- Attribut direkt in den Eingabefeldern verwenden kann. Ich weiß, es wird dir nicht gefallen, aber wenn alles fehlschlägt und du unbedingt Kommas brauchst, könnte input = "text" der einzige Weg sein.
kjetilh
Es sieht so aus, als würde die Nummer des Eingabetyps mehr Probleme verursachen, als die Benutzererfahrung tatsächlich verbessert. Auf Mobilgeräten wäre es großartig, wenn ich dem Benutzer nur eine numerische Tastatur öffnen könnte, wenn er nur Zahlen eingeben soll. Wie auch immer, ich muss das noch einmal überdenken ...
Devha
Da wir auch die Verwendung von Punkt und Komma als Dezimaltrennzeichen unterstützen müssen, planen wir, das Muster für die Validierung auf dem Desktop in Kombination mit type = "text" zu verwenden. Anschließend fügen wir die Funktionserkennung zur Erkennung mobiler Geräte hinzu und verwenden in diesem Fall type = "number".
Ehrfurcht
9

Ob für das Dezimaltrennzeichen Komma oder Punkt verwendet wird, liegt ganz beim Browser. Der Browser trifft seine Entscheidung basierend auf dem Gebietsschema des Betriebssystems oder Browsers, oder einige Browser nehmen Hinweise von der Website entgegen. Ich habe eine Browser-Vergleichstabelle erstellt, die zeigt, wie verschiedene Browser unterschiedliche Lokalisierungsmethoden unterstützen. Safari ist der einzige Browser, der Kommas und Punkte austauschbar verarbeitet.

Grundsätzlich können Sie als Webautor dies nicht wirklich kontrollieren. Bei einigen Problemumgehungen werden zwei Eingabefelder mit Ganzzahlen verwendet. Auf diese Weise kann jeder Benutzer die Daten wie erwartet eingeben. Es ist nicht besonders sexy, aber es wird in jedem Fall für alle Benutzer funktionieren.

Aeyoun
quelle
7

Verwenden Sie valueAsNumberanstelle von .val().

Eingabe. valueAsNumber [= Wert]

Gibt gegebenenfalls eine Zahl zurück, die den Wert des Formularsteuerelements darstellt. Andernfalls wird null zurückgegeben.
Kann eingestellt werden, um den Wert zu ändern.
Löst eine INVALID_STATE_ERR-Ausnahme aus, wenn das Steuerelement weder datums- oder zeitbasiert noch numerisch ist.

Mike Samuel
quelle
2
Das Problem ist, dass er Komma als Dezimaltrennzeichen unterstützen möchte und die Verwendung von type = "number" für die Eingabe beim Schreiben von Komma immer eine ungültige Zahl ergibt.
Ehrfurcht
Scheint unter Windows Phone nicht konsistent zu funktionieren. kehrt immer zurück NaN.
Bert Bruynooghe
@bertbruynooghe, Was weisen Sie als Wert zu?
Mike Samuel
Scheint nicht zu funktionieren, auch nicht mit '9', '9,1', '9.1'. Das Telefon ist als US konfiguriert, Tastaturlayouts in den USA getestet, nl-BE.
Bert Bruynooghe
4

Verwendet einen Texttyp, erzwingt jedoch das Erscheinungsbild der numerischen Tastatur

<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">

Das InputMode-Tag ist die Lösung

David Navarro
quelle
Aber es ist nicht mit allen Browsern kompatibel, nur mit den neuesten Versionen von iOS Safari, Chrome, Chromium, Opera ... caniuse.com/#feat=input-inputmode :(
pgarciacamou
Außerdem erhalten Sie diese nette Zifferntastatur auf Mobilgeräten nicht.
WoIIe
3

Ich habe keine perfekte Lösung gefunden, aber das Beste, was ich tun konnte, war, type = "tel" zu verwenden und die HTML5-Validierung (formnovalidate) zu deaktivieren:

<input name="txtTest" type="tel" value="1,200.00" formnovalidate="formnovalidate" />

Wenn der Benutzer ein Komma eingibt, wird es in jedem modernen Browser, den ich ausprobiert habe, mit dem Komma ausgegeben (neuestes FF, IE, Edge, Oper, Chrome, Safari Desktop, Android Chrome).

Das Hauptproblem ist:

  • Mobile Benutzer sehen ihre Telefontastatur, die sich möglicherweise von der Zifferntastatur unterscheidet.
  • Schlimmer noch, die Telefontastatur hat möglicherweise nicht einmal eine Kommataste.

Für meinen Anwendungsfall musste ich nur:

  • Zeigen Sie den Anfangswert mit einem Komma an (Firefox entfernt ihn für Typ = Nummer).
  • Nicht fehlschlagen HTML5-Validierung (wenn es ein Komma gibt)
  • Lassen Sie das Feld genau als Eingabe lesen (mit einem möglichen Komma).

Wenn Sie eine ähnliche Anforderung haben, sollte dies für Sie funktionieren.

Hinweis: Die Unterstützung des Musterattributs hat mir nicht gefallen. Das Formnovalidat scheint viel besser zu funktionieren.

Bolo
quelle
1

Wenn Sie es aufrufen, wird $("#my_input").val();es als Zeichenfolgenvariable zurückgegeben. Also verwenden parseFloatund parseIntzum Konvertieren. Wenn Sie parseFloatIhren Desktop oder Ihr Telefon verwenden, versteht ITSELF die Bedeutung von Variablen.

Außerdem können Sie einen Float in einen String konvertieren, indem Sie toFixedein Argument verwenden, das die Anzahl der Ziffern wie folgt enthält:

var i = 0.011;
var ss = i.toFixed(2); //It returns 0.01

quelle
Funktioniert nicht. Versuchen Sie parseFloat ("1,5") in IE11. Rückgabe 1. Die Sprache ist Deutsch für Betriebssystem und IE.
T3rm1
0

Meine Empfehlung? Verwenden Sie jQuery überhaupt nicht. Ich hatte das gleiche Problem wie du. Ich fand, dass $('#my_input').val()immer ein seltsames Ergebnis zurückkommt.

Versuchen Sie, document.getElementById('my_input').valueAsNumberanstelle von $("#my_input").val();und dann Number(your_value_retrieved)zu versuchen, eine Nummer zu erstellen. Wenn der Wert NaN ist, wissen Sie sicher, dass dies keine Zahl ist.

Wenn Sie eine Zahl in die Eingabe schreiben, akzeptiert die Eingabe tatsächlich fast jedes Zeichen (ich kann das Euro-Zeichen, einen Dollar und alle anderen Sonderzeichen schreiben). Daher ist es am besten, den Wert mit abzurufen .valueAsNumberanstatt jQuery zu verwenden.

Übrigens können Ihre Benutzer damit Internationalisierung hinzufügen (dh Kommas anstelle von Punkten unterstützen, um Dezimalzahlen zu erstellen). Lassen Sie das Number()Objekt einfach etwas für Sie erstellen und es ist sozusagen dezimalsicher.

Patrick D'appollonio
quelle
Das Problem wird nicht durch jQuery verursacht, und ich finde, dass valueAsNumberes auch nicht konsistent mit Browsern funktioniert.
Bert Bruynooghe
0

Klingt so, als würden Sie toLocaleString () für Ihre numerischen Eingaben verwenden.

Informationen zur Verwendung finden Sie unter https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString .

Die Lokalisierung von Zahlen in JS wird auch in der Internationalisierung (Zahlenformatierung "num.toLocaleString ()") behandelt, die für Chrome nicht funktioniert

stackasec
quelle
2
Es ist üblich, die Lösung genauer zu erläutern, auch wenn die Antwort vollständig von verlinkten Inhalten abgedeckt wird.
IvanH
Dieser Ansatz scheint besser zu sein als die anderen Ansätze, wenn der Back-End-Server das Gebietsschema und nicht den Browser selbst bestimmt. Leider toLocaleStringist plattformübergreifend nicht zuverlässig.
Bert Bruynooghe
Die plattformübergreifende Unterstützung scheint mir 2015 breit genug zu sein, siehe z . B. Mozillas Devnet . Wenn Sie dennoch Bedenken haben, finden
Stackasec
Mozillas Devnet ist für mobile Browser fast nicht kompatibel, und genau hier kann das numerische Textfeld die meisten Vorteile bieten. (Siehe ursprüngliche Frage.)
Bert Bruynooghe
... und mehr als genug Alternativen wurden gezeigt und referenziert. Habe Spaß.
Stackasec
0

Anscheinend haben Browser immer noch Probleme (obwohl Chrome und Firefox Nightly gut funktionieren). Ich habe einen hackigen Ansatz für die Leute, die wirklich ein Zahlenfeld verwenden müssen (vielleicht wegen der kleinen Pfeile, die Textfelder nicht haben).

Meine Lösung

Ich keyuphabe der Formulareingabe einen Ereignishandler hinzugefügt, den Status verfolgt und den Wert festgelegt, sobald er wieder gültig ist.

Reines JS-Snippet JSFIDDLE

Angular 9 Snippet

Joniras
quelle