Jak obsługiwać liczby zmiennoprzecinkowe i separatory dziesiętne z numerem typu danych wejściowych html5


Tworzę aplikację internetową przeznaczoną głównie dla przeglądarek mobilnych. Używam pól wprowadzania typu liczbowego, więc (większość) przeglądarek mobilnych wyświetla tylko klawiaturę numeryczną, aby zapewnić lepsze wrażenia użytkownika. Ta aplikacja internetowa jest najczęściej używana w regionach, w których separatorem dziesiętnym jest przecinek, a nie kropka, więc muszę obsługiwać oba separatory dziesiętne.
Jak pokryć to zamieszanie kropką i przecinkiem?
Moje ustalenia:

Chrome na komputer

  • Typ danych wejściowych = liczba
  • Użytkownik wpisuje „4,55” w polu wprowadzania
  • $ ("# my_input"). val ();
    zwraca „455”
  • Nie mogę uzyskać prawidłowej wartości z danych wejściowych


Firefox na komputer

  • Typ danych wejściowych = liczba
  • Użytkownik wpisuje „4,55” w polu wprowadzania
  • $ ("# my_input"). val ();
    zwraca „4,55”
  • W porządku, mogę zastąpić przecinek kropką i uzyskać poprawną liczbę zmiennoprzecinkową


Przeglądarka Android

  • Typ danych wejściowych = liczba
  • Użytkownik wpisuje „4,55” w polu wprowadzania
  • Gdy dane wejściowe tracą fokus, wartość jest obcinana do „4”
  • Myli użytkownika


Windows Phone 8

  • Typ danych wejściowych = liczba
  • Użytkownik wpisuje „4,55” w polu wprowadzania
  • $ ("# my_input"). val ();
    zwraca „4,55”
  • W porządku, mogę zastąpić przecinek kropką i uzyskać poprawną liczbę zmiennoprzecinkową

Jakie są „sprawdzone metody” w sytuacjach takich jak ta, w których użytkownik może użyć przecinka lub kropki jako separatora dziesiętnego, a ja chcę, aby typ danych wejściowych HTML był liczbą, aby zapewnić użytkownikom lepsze wrażenia?
Czy mogę w locie zamienić przecinek na kropkę podczas wiązania kluczowych zdarzeń, czy to działa z danymi numerycznymi?

EDIT
>
Obecnie nie mam żadnego rozwiązania, w jaki sposób uzyskać wartość zmiennoprzecinkową (jako ciąg lub liczbę) z typu danych wejściowych ustawionego na liczbę. Jeśli użytkownik końcowy wpisze „4,55”, chrome zawsze zwróci „455”, „4,55” Firefox zwróci i to dobrze.
Bardzo denerwuje też to, że w Androidzie (testowany emulator 4.2), gdy w polu wprowadzania wpisuję „4.55” i zmieniam fokus na coś innego, to wpisana liczba jest obcinana do „4”.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Myślę, że powyższe odpowiedzi nie muszą określać innej wartości atrybutu
step
, który ma wartość domyślną
1
. Jeśli chcesz, aby algorytm walidacji danych wejściowych akceptował wartości zmiennoprzecinkowe, określ odpowiedni krok.
Na przykład potrzebowałem kwot w dolarach, więc określiłem krok taki:
<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.">

Nie ma nic złego w korzystaniu z jQuery w celu uzyskania wartości, ale pomocne będzie bezpośrednie użycie interfejsu DOM API do uzyskania właściwości elementów
validity.valid
.
Miałem podobny problem z przecinkiem dziesiętnym, ale zdałem sobie sprawę, że to problem, ponieważ styl, który Twitter Bootstrap dodaje do numeru wejściowego z nieprawidłową wartością.
Oto skrzypce pokazujące, że dodanie atrybutu
step
sprawia, że ​​działa, a także sprawdzenie, czy aktualna wartość jest prawidłowa:


TL;DR:
ustaw atrybut a
step
na zmiennoprzecinkowy, ponieważ jego domyślna wartość to
1
.

NOTE

: przecinek nie działa dla mnie, ale podejrzewam, że jeśli ustawię preferencje języka/regionu systemu operacyjnego w miejscu, w którym przecinek jest używany jako separator dziesiętny, zadziała. * uwaga do notatki *: nie dotyczyło to ustawień języka/klawiatury systemu operacyjnego * niemieckiego * w systemie Ubuntu/Gnome 14.04.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Według atrybutu w3.org

value
numer wejścia
http://www.w3.org/TR/html-mark ... umber
zdefiniowana jako liczba z

zmiennoprzecinkowy
http://www.w3.org/TR/html-mark ... at... Wydaje się, że składnia liczb zmiennoprzecinkowych akceptuje tylko kropki jako separatory dziesiętne.
Poniżej wymieniłem kilka opcji, które mogą Ci się przydać:

1. Korzystanie z atrybutu pattern
>
Korzystanie z atrybutu
pattern

http://www.w3.org/TR/html5/for ... ibute
możesz określić prawidłowy format wyrażenia regularnego w sposób zgodny z HTML5. W tym miejscu możesz określić, czy znak przecinka jest dozwolony i otrzymać pomocny komunikat zwrotny, jeśli wzorzec nie działa.
<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."/>


Uwaga:

Obsługa różnych przeglądarek jest bardzo zróżnicowana. Może być kompletny, częściowy lub nieistniejący.

2. Walidacja JavaScript
>
Możesz spróbować powiązać proste wywołanie zwrotne, takie jak zdarzenie

onchange

(and/or

blur
), który zastąpi przecinek lub sprawdzi wszystko razem.

3. Wyłącz sprawdzanie przeglądarki ##
>
Po trzecie, możesz spróbować użyć

http://www.w3.org/TR/html5/for ... idate
atrybut formnovalidate na wejściach numerycznych z zamiarem całkowitego wyłączenia weryfikacji przeglądarki dla tego pola.
<input type="number" formnovalidate/>


4. połączenie ..?
>
<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."/>
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To, czy użyć przecinka, czy kropki jako separatora dziesiętnego, zależy całkowicie od przeglądarki. Przeglądarka podejmuje tę decyzję na podstawie ustawień regionalnych systemu operacyjnego lub przeglądarki, albo niektóre przeglądarki akceptują podpowiedzi ze strony internetowej. Zrobiłem

tabela porównawcza przeglądarek
https://www.ctrl.blog/entry/ht ... .html
pokazujące, jak różne przeglądarki obsługują różne metody lokalizacji. Safari to jedyna przeglądarka, która zamiennie obsługuje przecinki i kropki.
Zasadniczo, jako autor stron internetowych, nie masz nad tym rzeczywistej kontroli. Niektóre obejścia obejmują użycie dwóch pól wejściowych z liczbami całkowitymi. Dzięki temu każdy użytkownik może wprowadzać dane w oczekiwany sposób. Nie jest specjalnie seksowna, ale sprawdzi się w każdym przypadku dla wszystkich użytkowników.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Posługiwać się
valueAsNumber
http://www.w3.org/TR/2011/WD-h ... umber
zamiast
.val ()
.


Wejście. valueAsNumber [= wartość]
>
Jeśli ma to zastosowanie, zwraca liczbę reprezentującą wartość kontrolki formularza; w przeciwnym razie zwraca null.

Można ustawić, aby zmienić wartość.

Zgłasza wyjątek INVALID_STATE_ERR, jeśli formant nie jest oparty na dacie, godzinie ani cyfrze.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

używa typu tekstowego, ale wymusza wygląd klawiatury numerycznej
<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">

rozwiązaniem jest tag inputmode
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Nie znalazłem idealnego rozwiązania, ale najlepsze, co mogłem zrobić, to użyć type = "tel" i wyłączyć walidację html5 (formnovalidate):
<input name="txtTest" type="tel" value="1,200.00" formnovalidate="formnovalidate"/>

Jeśli użytkownik wstawi przecinek, zostanie wyświetlony średnik w każdej nowoczesnej przeglądarce, którą wypróbowałem (najnowsza FF, IE, edge, opera, chrome, safari desktop, android chrome).
Główny problem jest taki:
  • Użytkownicy mobilni zobaczą klawiaturę swojego telefonu, która może się różnić z klawiatury numerycznej.
  • Co gorsza, klawiatura telefonu może nawet nie mieć klawisza przecinka.

W moim przypadku potrzebowałem tylko:
  • Wydrukuj wartość początkową oddzieloną przecinkami (firefox wykreśla ją dla type=number)
  • Weryfikacja HTML5 nie powiodła się (jeśli jest przecinek)
  • Niech pole będzie czytane dokładnie jako dane wejściowe (z możliwym przecinkiem)

Jeśli masz podobne wymagania, powinno to działać dla Ciebie.

Uwaga:

Nie podobało mi się wsparcie dla atrybutu wzorca. Wydaje się, że formalidat działa znacznie lepiej.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Kiedy wywołujesz
$ ("# my_input"). Val ();
, jest zwracana jako zmienna łańcuchowa. Dlatego użyj
parseFloat
i
parseInt
do konwersji.
Gdy używasz
parseFloat
, komputera lub telefonu

ITSELF

rozumie znaczenie zmiennej.
Poza tym możesz przekonwertować zmiennoprzecinkowy na ciąg przy użyciu argumentu
toFixed
, który ma argument z liczbą cyfr, jak pokazano poniżej:
var i = 0.011;
var ss = i.toFixed(2);//It returns 0.01
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wygląda na to, że przeglądarki nadal mają problemy (chociaż Chrome i Firefox Nightly radzą sobie dobrze).
Mam hakerskie podejście do osób, które naprawdę muszą używać pól liczbowych (może z powodu małych strzałek, których nie ma w polach tekstowych).

Moja decyzja
>
Dodałem procedurę obsługi zdarzeń
keyup
do danych wejściowych formularza, prześledziłem stan i ustawiłem wartość, gdy tylko stanie się ponownie ważna.

Czysty fragment JavaScript

JSFIDDLE
https://jsfiddle.net/gu4th0oq/25/
>
<div class="snippet-code snippet-currently-hidden">
<div class="snippet" data-babel="false" data-console="true" data-hide="true" data-lang="js">
<pre class="snippet-code-js lang-js prettyprint-override">
var currentString = '';
var badState = false;
var lastCharacter = null;document.getElementById("field").addEventListener("keyup",($event) => {
if ($event.target.value && !$event.target.validity.badInput) {
currentString = $event.target.value;
} else if ($event.target.validity.badInput) {
if (badState && lastCharacter && lastCharacter.match(/[\.,]/) && !isNaN(+$event.key)) {
$event.target.value = ((+currentString) + (+$event.key/10));
badState = false;
} else {
badState = true;
}
}
document.getElementById("number").textContent = $event.target.value;
lastCharacter = $event.key;
});document.getElementById("field").addEventListener("blur",($event) => {
if (badState) {
$event.target.value = (+currentString);
badState = false;
document.getElementById("number").textContent = $event.target.value;
}
});

<pre class="snippet-code-css lang-css prettyprint-override">
#result{
padding: 10px;
background-color: orange;
font-size: 25px;
width: 400px;
margin-top: 10px;
display: inline-block;
}#field{
padding: 5px;
border-radius: 5px;
border: 1px solid grey;
width: 400px;
}

<pre class="snippet-code-html lang-html prettyprint-override">
<input type="number" id="field" keyup="keyUpFunction" step="0.01" placeholder="Field for both comma separators"><span id="result" >
<span >Current value: </span>
<span id="number"></span>
</span>


Fragment Angular 9
>
<div class="snippet-code snippet-currently-hidden">
<div class="snippet" data-babel="false" data-console="false" data-hide="true" data-lang="js">
<pre class="snippet-code-js lang-js prettyprint-override">
@Directive({
selector: '[appFloatHelper]'
})
export class FloatHelperDirective {
private currentString = '';
private badState = false;
private lastCharacter: string = null; @HostListener("blur", ['$event']) onBlur(event) {
if (this.badState) {
this.model.update.emit((+this.currentString));
this.badState = false;
}
} constructor(private renderer: Renderer2, private el: ElementRef, private change: ChangeDetectorRef, private zone: NgZone, private model: NgModel) {
this.renderer.listen(this.el.nativeElement, 'keyup', (e: KeyboardEvent) => {
if (el.nativeElement.value && !el.nativeElement.validity.badInput) {
this.currentString = el.nativeElement.value;
} else if (el.nativeElement.validity.badInput) {
if (this.badState && this.lastCharacter && this.lastCharacter.match(/[\.,]/) && !isNaN(+e.key)) {
model.update.emit((+this.currentString) + (+e.key/10));
el.nativeElement.value = (+this.currentString) + (+e.key/10);
this.badState = false;
} else {
this.badState = true;
}
}
this.lastCharacter = e.key;
});
}

}

<pre class="snippet-code-html lang-html prettyprint-override">
<input type="number" matInput placeholder="Field for both comma separators" appFloatHelper [(ngModel)]="numberModel">
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wygląda na to, że chciałbyś użyć metody toLocaleString () na swoich wejściach numerycznych.
Cm

. https://developer.mozilla.org/ ... tring
https://developer.mozilla.org/ ... tring
używać go.
Uwzględniono również lokalizację liczb w JS

internacjonalizacja (formatowanie liczb „num.toLocaleString ()”) nie działa w Chrome
https://coderoad.ru/8906567/
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Moja rekomendacja? W ogóle nie używaj jQuery. Miałem ten sam problem co ty. Zauważyłem, że
$ ('# my_input'). Val ()
zawsze zwraca jakiś dziwny wynik.
Spróbuj użyć
document.getElementById ('my_input'). ValueAsNumber
zamiast
$ ("# my_input"). Val ();
, a następnie użyj
Number (your_value_retrieved)
, aby spróbować utworzyć numer. Jeśli wartość to NaN, prawdopodobnie wiesz, że to nie jest liczba.
Jedną rzeczą do dodania jest to, że kiedy piszesz liczbę na wejściu, wejście faktycznie akceptuje prawie każdy znak (mogę napisać znak euro, dolara i wszystkie inne znaki specjalne), więc najlepiej jest uzyskać wartość za pomocą .valueAsNumber i nie z jQuery.
Aha, i BTW, który umożliwia użytkownikom dodawanie internacjonalizacji (tj. Obsługę przecinków zamiast kropek do tworzenia liczb dziesiętnych). Po prostu pozwól, aby obiekt
Number ()
utworzył coś dla Ciebie i jest to bezpieczne po przecinku, że tak powiem.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się