Como obter o valor bruto de um campo <input type = “number”>?

117

Como posso obter o valor "real" de um <input type="number">campo?


Eu tenho uma inputcaixa e estou usando o tipo de entrada HTML5 mais recente number:

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

Isso é principalmente compatível com o Chrome 29:

insira a descrição da imagem aqui

O que eu preciso agora é a capacidade de ler o valor "bruto" que o usuário inseriu na caixa de entrada. Se o usuário inseriu um número:

insira a descrição da imagem aqui

então edQuantity.value = 4, e tudo está bem.

Mas se o usuário inserir um texto inválido, quero colorir a caixa de entrada de vermelho:

insira a descrição da imagem aqui

Infelizmente, para uma type="number"caixa de entrada, se o valor na caixa de texto não for um número, valueretorna uma string vazia:

edQuantity.value = "" (String);

(no Chrome 29, pelo menos)

Como posso obter o valor "bruto" de um <input type="number">controle?

Tentei olhar a lista do Chrome de outras propriedades da caixa de entrada:

insira a descrição da imagem aqui

não vi nada que se pareça com a entrada real.

Nem consegui encontrar uma maneira de saber se a caixa "está vazia" ou não. Talvez eu pudesse ter inferido:

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

Nota : Você pode ignorar tudo após a régua horizontal; é apenas um preenchimento para justificar a pergunta. Além disso: não confunda o exemplo com a pergunta. As pessoas podem querer a resposta a esta pergunta por outras razões além de colorir a caixa de vermelho (um exemplo: converter o texto "four"no "4"símbolo latino durante o evento onBlur)

Como posso obter o valor "bruto" de um <input type="number">controle?

Leitura de bônus

Ian Boyd
fonte
2
O valor 'real' de um campo de entrada numérico deve ser um número. Se você deseja permitir entrada diferente de valores numéricos, numbereste não é o tipo de entrada que você está procurando; use uma textentrada normal .
robertc de
7
@robertc Chrome é o agente que permite outras entradas além de números; Eu só preciso saber que eles entraram outros do que os números coisas.
Ian Boyd
1
Verifique o validityestado do campo - seria de esperar, typeMismatchmas não verifiquei sozinho.
robertc
2
@ int32_t Leia a sexta linha para baixo (ou seja, "Mas se o usuário inserir ..." )
Ian Boyd
6
Meu caso de uso ... Tenho dois campos numéricos: latitude e longitude. Gostaria de detectar se alguém cola "lat, lon" e o manuseia de maneira adequada. Atualmente, isso é impossível com type = "number". uma vez que "lat, lon" é inválido .. não há como obter o valor "bruto" para executar uma regex. Outro caso de uso: exibir um erro do cliente: " blahé um número inválido".
Brad Kent,

Respostas:

55

De acordo com o WHATWG , você não deve ser capaz de obter o valor a menos que seja uma entrada numérica válida. O algoritmo de sanitização do campo de número de entrada diz que o navegador deve definir o valor como uma string vazia se a entrada não for um número de ponto flutuante válido.

O algoritmo de sanitização de valor é o seguinte: Se o valor do elemento não for um número de ponto flutuante válido , defina-o como uma string vazia.

Ao especificar o type ( <input type="number">), você está pedindo ao navegador para fazer algum trabalho para você. Se, por outro lado, você gostaria de ser capaz de capturar a entrada não numérica e fazer algo com ela, você teria que contar com o antigo campo de entrada de texto testado e comprovado e analisar o conteúdo você mesmo.

O W3 também tem as mesmas especificações e adiciona:

Os agentes do usuário não devem permitir que o usuário defina o valor como uma string não vazia que não seja um número de ponto flutuante válido.

j08691
fonte
6
Seria útil se os agentes do usuário não permitissem que o usuário definisse o valor como uma string não vazia que não é um número de ponto flutuante válido. Mas se o que Wg diz, isso não pode ser feito; então essa é a resposta. Solução alternativa para minha necessidade atual adicionada abaixo.
Ian Boyd
57
Ao especificar o type ( <input type="number">), você está pedindo ao navegador para fazer algum trabalho para você. Pessoalmente, estava apenas pedindo aos navegadores móveis que mostrassem um teclado numérico e recebi a validação como um extra desagradável. A maioria desses problemas se origina do fato de que o typeatributo determina regras de validação e regras sobre qual mecanismo de entrada exibir, mas é bem possível querer mostrar um teclado numérico para usuários móveis sem também querer validação de número aplicada a usuários de desktop. O HTML 5.1 irá pelo menos resolver este problema eventualmente com o inputmodeatributo.
Mark Amery
4
mas quando o navegador não fizer o suficiente, gostaria de poder concluí-lo. como remover espaços na entrada, inferir o ponto decimal ...
njzk2
1
além disso, em vários idiomas, como o francês, existem 2 palavras para o número. um para números como identificadores, como números de cartão de crédito, e um para contar números, como números de ponto flutuante.
njzk2
1
@MotiKorets não funciona para inserir números de ponto flutuante, pois iPhones não colocam um ponto decimal no teclado. Infelizmente, os desenvolvedores estão muito ferrados no momento, no que diz respeito a fornecer uma UX de entrada de ponto flutuante agradável ...
Andy
50

Não responde à pergunta, mas a solução útil é verificar

edQuantity.validity.valid

O ValidityStatede um objeto fornece pistas sobre o que o usuário inseriu. Considere uma type="number"entrada com um mine maxconjunto

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

Nós sempre quer usar .validity.valid.

Outras propriedades fornecem apenas informações de bônus:

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

Você terá que se certificar de que o navegador suporta validação HTML5 antes de usá-lo:

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;
}

Bônus

Spudly tem uma resposta útil que excluiu:

Basta usar o :invalidseletor CSS para isso.

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

Isso fará com que seu elemento fique vermelho sempre que um valor não numérico válido for inserido.

O suporte do navegador para <input type='number'>é quase o mesmo que :invalid, então não há problema.

Leia mais sobre :invalid aqui .

Ian Boyd
fonte
Não funciona no Opera. Diz válido mesmo se você inserir uma string.
Bergi,
O Opera suporta a .validitypropriedade, mas não controla corretamente .valid?!
Ian Boyd
Sim, mas quando uma entrada de número é inválida ? Ele apenas age como se a entrada estivesse vazia. A typeMismatchpode fazer sentido, mas isso é apenas para tipos de e-mail ou url…
Bergi
@Bergi A tabela acima dá exemplos em que as entradas de número podem ser inválidas: "q", "11" (então o máximo é 10), "0" (quando o mínimo é 1), "" (então o elemento é required)
Ian Boyd,
1
@Bergi .badInputfoi adicionado em 20/11/2012 . Mas ninguém deve olhar badInputpara ver se a entrada é válida; eles deveriam estar olhando .valid. É possível (e correto) .badInputser falso e ainda ter entrada inválida. .validé definido como a ausência de quaisquer erros de validação (por exemplo, incompatibilidades, overflows, underflows), dos quais .badInputé apenas um tipo de erro. Observe o gráfico acima onde .badInputé falso, mas a entrada ainda é inválida.
Ian Boyd
4

Rastreie todas as teclas pressionadas com base em seus códigos de tecla

Suponho que se possa ouvir os eventos de ativação e manter uma matriz de todos os caracteres inseridos, com base em seus códigos de tecla. Mas é uma tarefa muito tediosa e provavelmente sujeita a bugs.

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

Selecione a entrada e obtenha a seleção como uma string

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

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

Todo o crédito para: int32_t

Sandstrom
fonte
Essa solução foi tentada em outro lugar e não funciona . Especialmente quando os usuários prensas Delete, Backspace, Ctrl+X, Ctrl+V, Right-click-cut, Right-click-paste.
Ian Boyd
Eu concordo com você, basicamente o que o OP pediu não é possível. No entanto, os dois hacks que mencionei (e são hacks, não nego) funcionam até certo ponto. Talvez eles possam ser úteis para alguém, em algum caso?
sandstrom
surpreendentemente, a coisa da seleção parece funcionar. Quais são as limitações desse método?
njzk2
Limitações: o texto é selecionado visualmente. Se o usuário digitar algo, o conteúdo desaparecerá
fregante
Editado com uma demonstração ao vivo que mostra como esse método é ruim
vsync