Jak uzyskać nieprzetworzoną wartość w polu <input type = „number”>?

117

Jak uzyskać „rzeczywistą” wartość <input type="number">pola?


Mam inputpudełko i używam nowszego typu wprowadzania HTML5 number:

<input id="edQuantity" type="number">

Jest to obsługiwane głównie w Chrome 29:

wprowadź opis obrazu tutaj

Teraz potrzebuję możliwości odczytania „surowej” wartości wprowadzonej przez użytkownika w polu wprowadzania. Jeśli użytkownik wprowadził numer:

wprowadź opis obrazu tutaj

wtedy edQuantity.value = 4i wszystko jest w porządku.

Ale jeśli użytkownik wprowadzi nieprawidłowy tekst, chcę pokolorować pole wejściowe na czerwono:

wprowadź opis obrazu tutaj

Niestety, dla type="number"pola wejściowego, jeśli wartość w polu tekstowym nie jest liczbą, to valuezwraca pusty ciąg:

edQuantity.value = "" (String);

(przynajmniej w Chrome 29)

Jak mogę uzyskać „surową” wartość <input type="number">kontrolki?

Próbowałem przejrzeć listę innych właściwości pola wprowadzania w Chrome:

wprowadź opis obrazu tutaj

nie widziałem niczego, co przypominałoby rzeczywiste dane wejściowe.

Nie mogłem też znaleźć sposobu, aby stwierdzić, czy pudełko jest „puste” , czy nie. Może mogłem wywnioskować:

value          isEmpty        Conclusion
=============  =============  ================
"4"            false          valid number
""             true           empty box; not a problem
""             false          invalid text; color it red

Uwaga : możesz zignorować wszystko po linii poziomej; to tylko wypełniacz, aby uzasadnić pytanie. Ponadto: nie myl przykładu z pytaniem. Ludzie mogą chcieć odpowiedzi na to pytanie z powodów innych niż kolorowanie ramki na czerwono (jeden przykład: konwersja tekstu "four"na "4"symbol łaciński podczas zdarzenia onBlur)

Jak mogę uzyskać „surową” wartość <input type="number">kontrolki?

Czytanie bonusowe

Ian Boyd
źródło
2
„Rzeczywista” wartość numerycznego pola wejściowego musi być liczbą. Jeśli chcesz zezwolić na wejście inne niż wartości liczbowe, numberto nie jest typem wejściowym, którego szukasz; użyj normalnego textwejścia.
robertc
7
@robertc Chrome jest agentem umożliwiającym wprowadzanie danych innych niż liczby; Muszę tylko wiedzieć, że wpisali coś innego niż cyfry.
Ian Boyd,
1
Sprawdzić w polu validitystanu - Spodziewam się, typeMismatchale nie sprawdził się.
robertc
2
@ int32_t Przeczytaj szóstą linię w dół (tj. „Ale jeśli użytkownik wejdzie ...” )
Ian Boyd
6
Mój przypadek użycia ... Mam dwa pola numeryczne: szerokość i długość geograficzną. Chciałbym wykryć, czy ktoś wkleił „lat, lon” i odpowiednio sobie poradzić. Obecnie jest to niemożliwe z type = "number". ponieważ „lat, lon” jest niepoprawne .. nie ma sposobu na pobranie wartości „surowej” w celu wykonania wyrażenia regularnego. Inny przypadek użycia: wyświetlanie błędu klienta: „ blahto nieprawidłowa liczba”.
Brad Kent

Odpowiedzi:

55

Zgodnie z WHATWG nie powinieneś być w stanie uzyskać wartości, chyba że jest to prawidłowe dane liczbowe. Algorytm oczyszczania pola numeru wejściowego mówi, że przeglądarka ma ustawić wartość na pusty ciąg, jeśli dane wejściowe nie są prawidłową liczbą zmiennoprzecinkową.

Algorytm wartość dezynfekcja jest następująca: Jeśli wartość elementu nie jest ważna liczba zmiennoprzecinkowa , a następnie ustawić go na pusty ciąg zamiast.

Określając typ ( <input type="number">), prosisz przeglądarkę o wykonanie jakiejś pracy za Ciebie. Jeśli z drugiej strony chciałbyś móc przechwycić nieliczbowe dane wejściowe i coś z nimi zrobić, musiałbyś polegać na starym wypróbowanym i prawdziwym polu wprowadzania tekstu i samodzielnie przeanalizować zawartość.

W3 ma także te same specyfikacje i dodaje:

Programy użytkownika nie mogą zezwalać użytkownikowi na ustawienie wartości niepustego łańcucha, który nie jest prawidłową liczbą zmiennoprzecinkową.

j08691
źródło
6
Byłoby użyteczne, gdyby oprogramowanie użytkownika nie pozwalało użytkownikowi ustawić wartości niepustego łańcucha, który nie jest prawidłową liczbą zmiennoprzecinkową. Ale jeśli whatwg mówi, że nie można tego zrobić; to jest odpowiedź. Obejście problemu zostało dodane poniżej.
Ian Boyd
57
Określając typ ( <input type="number">), prosisz przeglądarkę o wykonanie jakiejś pracy za Ciebie. Osobiście po prostu prosiłem przeglądarki mobilne, aby pokazały klawiaturę numeryczną i otrzymałem potwierdzenie jako nieprzyjemny dodatek. Większość z tych problemów wynika z faktu, że typeatrybut określa zarówno reguły walidacji, jak i reguły dotyczące mechanizmu wprowadzania danych do wyświetlenia, ale całkiem możliwe jest wyświetlenie klawiatury numerycznej użytkownikom mobilnym bez konieczności stosowania sprawdzania poprawności liczb na komputerach stacjonarnych. HTML 5.1 przynajmniej ostatecznie rozwiąże ten problem za pomocą inputmodeatrybutu.
Mark Amery,
4
ale kiedy przeglądarka nie wystarcza, chciałbym móc to uzupełnić. takie jak usuwanie spacji z danych wejściowych, wnioskowanie kropki dziesiętnej ...
njzk2
1
ponadto w różnych językach, takich jak francuski, istnieją 2 słowa oznaczające liczbę. jeden dla liczb jako identyfikatorów, takich jak numery kart kredytowych, a drugi dla zliczania liczb, takich jak liczby zmiennoprzecinkowe.
njzk2
1
@MotiKorets nie działa do wprowadzania liczb zmiennoprzecinkowych, ponieważ iPhone'y nie umieszczają przecinka dziesiętnego na klawiaturze. Niestety programiści są w tej chwili całkiem pokręceni, jeśli chodzi o zapewnienie niezłego UX wejścia zmiennoprzecinkowego ...
Andy
50

Nie odpowiada na pytanie, ale użytecznym obejściem jest sprawdzenie

edQuantity.validity.valid

Element ValidityStateobiektu daje wskazówki o tym, co wprowadził użytkownik. Rozważmy dane type="number"wejściowe z a mini maxset

<input type="number" min="1" max="10">

My zawsze chcemy użyć .validity.valid.

Inne właściwości podają tylko informacje o bonusie:

User's Input  .value  .valid | .badInput  .rangeUnderflow  .rangeOverflow
============  ======  ====== | =========  ===============  ==============
""            ""      true   | false      false            false  ;valid because field not marked required
"1"           "1"     true   | false      false            false  
"10"          "10"    true   | false      false            false
"0"           "0"     false  | false      true             false  ;invalid because below min
"11"          "11"    false  | false      false            true   ;invalid because above max
"q"           ""      false  | true       false            false  ;invalid because not number
"³"           ""      false  | true       false            false  ;superscript digit 3
"٣"           ""      false  | true       false            false  ;arabic digit 3
"₃"           ""      false  | true       false            false  ;subscript digit 3

Przed użyciem musisz upewnić się, że przeglądarka obsługuje walidację HTML5:

function ValidateElementAsNumber(element)
{
   //Public Domain: no attribution required.
   if ((element.validity) && (!element.validity.valid))
   {
      //if html5 validation says it's bad: it's bad
      return false;
   }

   //Fallback to browsers that don't yet support html5 input validation
   //Or we maybe want to perform additional validations
   var value = StrToInt(element.value);
   if (value != null)
      return true;
   else
      return false;
}

Premia

Spudly ma przydatną odpowiedź, którą usunął:

Po prostu użyj :invaliddo tego selektora CSS .

input[type=number]:invalid {
    background-color: #FFCCCC;
}

Spowoduje to, że Twój element zmieni kolor na czerwony po wprowadzeniu wartości nienumerycznej.

Obsługa przeglądarki dla <input type='number'>jest mniej więcej taka sama jak :invalid, więc nie ma problemu.

Przeczytaj więcej na ten temat :invalid tutaj .

Ian Boyd
źródło
Nie działa w Operze. Mówi, że jest ważny, nawet jeśli wprowadzisz ciąg.
Bergi
Opera obsługuje tę .validitywłaściwość, ale nie obsługuje poprawnie .valid?!
Ian Boyd
Tak, ale kiedy wprowadzony numer jest nieprawidłowy ? Działa tak, jakby dane wejściowe były puste. A typeMismatchmoże mieć sens, ale dotyczy to tylko e-maili lub adresów URL…
Bergi
@Bergi Powyższa tabela zawiera przykłady, w których wprowadzane liczby mogą być nieprawidłowe: "q", "11" (wtedy maksimum to 10), "0" (gdy min wynosi 1), "" (wtedy element jest required)
Ian Boyd
1
@Bergi .badInputdodano 20.11.2012 . Ale nikt nie powinien patrzeć, badInputczy dane wejściowe są prawidłowe; powinni patrzeć .valid. Możliwe (i poprawne) .badInputmoże być fałsz i nadal mieć nieprawidłowe dane wejściowe. .validdefiniuje się jako brak jakichkolwiek błędów walidacji (np. niedopasowania, przepełnienia, niedopełnienia), co .badInputstanowi tylko jeden rodzaj błędu. Zwróć uwagę na powyższy wykres, gdzie .badInputjest fałsz, ale dane wejściowe są nadal nieprawidłowe.
Ian Boyd
4

Śledź wszystkie wciśnięte klawisze na podstawie ich kodów klawiszy

Przypuszczam, że można by słuchać zdarzeń keyup i zachować tablicę wszystkich wprowadzonych znaków na podstawie ich kodów klawiszy. Ale jest to dość żmudne zadanie i prawdopodobnie podatne na błędy.

http://unixpapa.com/js/key.html

Wybierz wejście i uzyskaj wybór jako ciąg

document.querySelector('input').addEventListener('input', onInput);

function onInput(){
  this.select(); 
  console.log( window.getSelection().toString() )
}
<input type='number'>

Cały kredyt dla: int32_t

sandstrom
źródło
To rozwiązanie zostało wypróbowane w innym miejscu i nie działa . Zwłaszcza, gdy naciśnie użytkowników Delete, Backspace, Ctrl+X, Ctrl+V, Right-click-cut, Right-click-paste.
Ian Boyd
Zgadzam się z tobą, w zasadzie to, o co prosił OP, nie jest możliwe. Jednak oba hacki, o których wspomniałem (i są to hacki, nie przeczę) działają do pewnego stopnia. Może w jakimś przypadku mogą się komuś przydać?
sandstrom
zdumiewająco, selekcja wydaje się działać. Jakie są ograniczenia tej metody?
njzk2
Ograniczenia: tekst jest zaznaczony wizualnie. Jeśli użytkownik coś wpisze, zawartość zniknie
fregante
Edytowane z demo na żywo, które pokazuje, jak zła jest ta metoda
vsync