¿Cómo obtener el valor bruto de un campo <input type = “number”>?

117

¿Cómo puedo obtener el valor "real" de un <input type="number">campo?


Tengo una inputcaja y estoy usando un tipo de entrada HTML5 más nuevo number:

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

Esto es principalmente compatible con Chrome 29:

ingrese la descripción de la imagen aquí

Lo que ahora necesito es la capacidad de leer el valor "sin procesar" que el usuario ingresó en el cuadro de entrada. Si el usuario ha introducido un número:

ingrese la descripción de la imagen aquí

entonces edQuantity.value = 4, y todo va bien.

Pero si el usuario ingresa texto no válido, quiero colorear el cuadro de entrada de rojo:

ingrese la descripción de la imagen aquí

Desafortunadamente, para un type="number"cuadro de entrada, si el valor en el cuadro de texto no es un número, entonces valuedevuelve una cadena vacía:

edQuantity.value = "" (String);

(en Chrome 29 al menos)

¿Cómo puedo obtener el valor "bruto" de un <input type="number">control?

Intenté buscar en la lista de Chrome de otras propiedades del cuadro de entrada:

ingrese la descripción de la imagen aquí

No vi nada que se parezca a la entrada real.

Tampoco pude encontrar una manera de saber si la casilla "está vacía" o no. Tal vez podría haber inferido:

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

Nota : puede ignorar todo después de la regla horizontal; es solo un relleno para justificar la pregunta. Además: no confunda el ejemplo con la pregunta. La gente puede querer la respuesta a esta pregunta por otras razones además de colorear el cuadro de rojo (Un ejemplo: convertir el texto "four"en el "4"símbolo latino durante el evento onBlur)

¿Cómo puedo obtener el valor "bruto" de un <input type="number">control?

Lectura adicional

Ian Boyd
fuente
2
El valor "real" de un campo de entrada numérico debe ser un número. Si desea permitir entradas que no sean valores numéricos, entonces numberno es el tipo de entrada que está buscando; utilice una textentrada normal .
robertc
7
@robertc Chrome es el agente que permite la entrada que no sean números; Solo necesito saber que han ingresado otras cosas además de números.
Ian Boyd
1
Verifique el validityestado del campo ; lo esperaría, typeMismatchpero no lo he verificado.
robertc
2
@ int32_t Leer la sexta línea hacia abajo (es decir, "Pero si el usuario ingresa ..." )
Ian Boyd
6
Mi caso de uso ... Tengo dos campos numéricos: latitud y longitud. Me gustaría detectar si alguien pega "lat, lon" y lo maneja adecuadamente. Actualmente, esto es imposible con type = "number". ya que "lat, lon" no es válido ... no hay forma de obtener el valor "crudo" para realizar una expresión regular. Otro caso de uso: mostrar un error de cliente: " blahes un número inválido".
Brad Kent

Respuestas:

55

De acuerdo con WHATWG , no debería poder obtener el valor a menos que sea una entrada numérica válida. El algoritmo de desinfección del campo del número de entrada dice que se supone que el navegador debe establecer el valor en una cadena vacía si la entrada no es un número de punto flotante válido.

El algoritmo de desinfección de valores es el siguiente: si el valor del elemento no es un número de punto flotante válido, establézcalo en la cadena vacía.

Al especificar el tipo ( <input type="number">) le está pidiendo al navegador que haga un trabajo por usted. Si, por otro lado, desea poder capturar la entrada no numérica y hacer algo con ella, tendrá que confiar en el antiguo campo de entrada de texto probado y verdadero y analizar el contenido usted mismo.

El W3 también tiene las mismas especificaciones y agrega:

Los agentes de usuario no deben permitir que el usuario establezca el valor en una cadena no vacía que no sea un número de punto flotante válido.

j08691
fuente
6
Sería útil si los agentes de usuario no permitieran al usuario establecer el valor en una cadena no vacía que no sea un número de punto flotante válido. Pero si lo que dice, no se puede hacer; entonces esa es la respuesta. Solución alternativa para mi necesidad actual agregada a continuación.
Ian Boyd
57
Al especificar el tipo ( <input type="number">) le está pidiendo al navegador que haga un trabajo por usted. Personalmente, solo estaba pidiendo a los navegadores móviles que mostraran un teclado numérico y obtuve la validación como un extra desagradable. La mayoría de estos problemas surgen del hecho de que el typeatributo determina tanto las reglas de validación como las reglas sobre qué mecanismo de entrada mostrar, pero es muy posible querer mostrar un teclado numérico a los usuarios de dispositivos móviles sin que también se desee aplicar la validación de números a los usuarios de escritorio. HTML 5.1 al menos resolverá este problema eventualmente con el inputmodeatributo.
Mark Amery
4
pero cuando el navegador no hace lo suficiente, me gustaría poder completarlo. como eliminar espacios en la entrada, inferir el punto decimal ...
njzk2
1
Además, en varios idiomas, como el francés, hay 2 palabras para el número. uno para números como identificadores, como números de tarjetas de crédito, y otro para contar números, como números de coma flotante.
njzk2
1
@MotiKorets no funciona para ingresar números de punto flotante ya que los iPhones no colocan un punto decimal en el teclado. Desafortunadamente, los desarrolladores están bastante jodidos en este momento en cuanto a proporcionar una buena experiencia de usuario de entrada de punto flotante ...
Andy
50

No responde a la pregunta, pero la solución útil es verificar

edQuantity.validity.valid

La ValidityStatede un objeto da pistas sobre lo que ingresó el usuario. Considere una type="number"entrada con a miny maxestablezca

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

Nosotros siempre queremos utilizar .validity.valid.

Otras propiedades solo brindan información adicional:

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

Tendrá que asegurarse de que el navegador admita la validación HTML5 antes de usarlo:

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

Prima

Spudly tiene una respuesta útil que eliminó:

Solo usa el :invalidselector de CSS para esto.

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

Esto activará su elemento para que se vuelva rojo cada vez que se ingrese un valor válido no numérico.

La compatibilidad del navegador con <input type='number'>es aproximadamente la misma que :invalid, así que no hay problema.

Leer más sobre :invalid aquí .

Ian Boyd
fuente
No funciona en Opera. Dice válido incluso si ingresa una cadena.
Bergi
Opera admite la .validitypropiedad, ¡pero no la maneja correctamente .valid?!
Ian Boyd
Lo hace, pero ¿cuándo es inválida una entrada numérica ? Simplemente actúa como si la entrada estuviera vacía. A typeMismatchpodría tener sentido, pero eso es solo para los tipos de correo electrónico o URL ...
Bergi
@Bergi La tabla anterior da ejemplos donde las entradas numéricas pueden ser inválidas: "q", "11" (entonces el máximo es 10), "0" (cuando el mínimo es 1), "" (entonces el elemento es required)
Ian Boyd
1
@Bergi .badInputse agregó el 20/11/2012 . Pero nadie debería mirar badInputpara ver si la entrada es válida; deberían estar mirando .valid. Es posible (y correcto) .badInputque sea falso y aún tenga una entrada no válida. .validse define como la ausencia de errores de validación (por ejemplo, desajustes, desbordamientos, subdesbordamientos), de los cuales .badInputes solo un tipo de error. Tenga en cuenta el gráfico anterior donde .badInputes falso, pero la entrada aún no es válida.
Ian Boyd
4

Seguimiento de todas las teclas presionadas según sus códigos de tecla

Supongo que uno podría escuchar los eventos de activación de teclas y mantener una matriz de todos los caracteres ingresados, según sus códigos de teclas. Pero es una tarea bastante tediosa y probablemente propensa a errores.

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

Seleccione la entrada y obtenga la selección como una cadena

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

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

Todo crédito a: int32_t

Sandstrom
fuente
Esa solución se probó en otro lugar y no funciona . Especialmente cuando los usuarios prensas Delete, Backspace, Ctrl+X, Ctrl+V, Right-click-cut, Right-click-paste.
Ian Boyd
Estoy de acuerdo contigo, básicamente lo que pidió el OP no es posible. Sin embargo, los dos hacks que mencioné (y son hacks, no lo niego) funcionan hasta cierto punto. ¿Quizás puedan ser útiles para alguien, en algún caso?
sandstrom
sorprendentemente, la selección parece funcionar. ¿Cuáles son las limitaciones de ese método?
njzk2
Limitaciones: el texto se selecciona visualmente. Si el usuario escribe algo, el contenido desaparecerá
Fregante
Editado con una demostración en vivo que muestra lo malo que es este método
vsync