Comment obtenir la valeur brute d'un champ <input type = "number">?

117

Comment puis-je obtenir la valeur "réelle" d'un <input type="number">champ?


J'ai une inputboîte et j'utilise un type d'entrée HTML5 plus récent number:

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

Ceci est principalement pris en charge dans Chrome 29:

entrez la description de l'image ici

Ce dont j'ai besoin maintenant, c'est la capacité de lire la valeur «brute» que l'utilisateur a entrée dans la zone de saisie. Si l'utilisateur a saisi un numéro:

entrez la description de l'image ici

puis edQuantity.value = 4, et tout va bien.

Mais si l'utilisateur entre un texte invalide, je veux colorer la zone de saisie en rouge:

entrez la description de l'image ici

Malheureusement, pour une zone de type="number"saisie, si la valeur de la zone de texte n'est pas un nombre, alors valuerenvoie une chaîne vide:

edQuantity.value = "" (String);

(au moins dans Chrome 29)

Comment puis-je obtenir la valeur "brute" d'un <input type="number">contrôle?

J'ai essayé de parcourir la liste des autres propriétés de la zone de saisie de Chrome:

entrez la description de l'image ici

je n'ai rien vu qui ressemble à l'entrée réelle.

Je ne pourrais pas non plus trouver un moyen de savoir si la boîte "est vide" ou non. J'aurais peut-être pu déduire:

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

Remarque : vous pouvez tout ignorer après la règle horizontale; c'est juste du remplissage pour justifier la question. Aussi: ne confondez pas l'exemple avec la question. Les gens pourraient vouloir la réponse à cette question pour des raisons autres que de colorer la boîte en rouge (un exemple: convertir le texte "four"en "4"symbole latin pendant l'événement onBlur)

Comment puis-je obtenir la valeur "brute" d'un <input type="number">contrôle?

Lecture bonus

Ian Boyd
la source
2
La valeur «réelle» d'un champ d'entrée numérique doit être un nombre. Si vous souhaitez autoriser une entrée autre que des valeurs numériques, ce numbern'est pas le type d'entrée que vous recherchez; utilisez une textentrée normale .
robertc
7
@robertc Chrome est l'agent autorisant des entrées autres que des nombres; j'ai juste besoin de savoir qu'ils ont entré des choses autres que des nombres.
Ian Boyd
1
Vérifiez l' validityétat du champ - je m'attendrais typeMismatchmais je ne me suis pas vérifié.
robertc
2
@ int32_t Lire la sixième ligne vers le bas (c'est-à-dire "Mais si l'utilisateur entre ..." )
Ian Boyd
6
Mon cas d'utilisation ... J'ai deux champs numériques: la latitude et la longitude. Je voudrais détecter si quelqu'un colle dans "lat, lon" et gérer de manière appropriée. Ceci est actuellement impossible avec type = "number". puisque "lat, lon" n'est pas valide .. il n'y a aucun moyen d'obtenir la valeur "brute" pour exécuter une expression régulière. Autre cas d'utilisation: affichage d'une erreur client: " blahest un numéro invalide".
Brad Kent

Réponses:

55

Selon le WHATWG , vous ne devriez pas pouvoir obtenir la valeur à moins qu'il s'agisse d'une entrée numérique valide. L'algorithme de nettoyage du champ de nombre d'entrée indique que le navigateur est censé définir la valeur sur une chaîne vide si l'entrée n'est pas un nombre à virgule flottante valide.

L' algorithme de nettoyage des valeurs est le suivant: Si la valeur de l'élément n'est pas un nombre à virgule flottante valide , définissez-le à la place sur la chaîne vide.

En spécifiant le type (<input type="number"> ), vous demandez au navigateur de faire un travail pour vous. Si, d'un autre côté, vous souhaitez être en mesure de capturer l'entrée non numérique et d'en faire quelque chose, vous devez vous fier à l'ancien champ de saisie de texte éprouvé et analyser le contenu vous-même.

Le W3 a également les mêmes spécifications et ajoute:

Les agents utilisateurs ne doivent pas autoriser l'utilisateur à définir la valeur sur une chaîne non vide qui n'est pas un nombre à virgule flottante valide.

j08691
la source
6
Cela serait utile si les agents utilisateurs ne permettaient pas à l'utilisateur de définir la valeur sur une chaîne non vide qui n'est pas un nombre à virgule flottante valide. Mais si whatwg dit cela ne peut pas être fait; alors c'est la réponse. Solution de contournement pour mon besoin actuel ajoutée ci-dessous.
Ian Boyd
57
En spécifiant le type ( <input type="number">), vous demandez au navigateur de faire un travail pour vous. Personnellement, je demandais simplement aux navigateurs mobiles d'afficher un clavier numérique et j'ai obtenu la validation comme un supplément désagréable. La plupart de ces problèmes proviennent du fait que l' typeattribut détermine à la fois les règles de validation et les règles sur le mécanisme de saisie à afficher, mais il est tout à fait possible de vouloir montrer un clavier numérique aux utilisateurs mobiles sans vouloir également que la validation des nombres s'applique aux utilisateurs de bureau. HTML 5.1 résoudra au moins ce problème avec l' inputmodeattribut.
Mark Amery
4
mais quand le navigateur n'en fait pas assez, j'aimerais pouvoir le compléter. comme la suppression d'espaces dans l'entrée, la déduction de la virgule décimale ...
njzk2
1
aussi, dans diverses langues, comme le français, il y a 2 mots pour le nombre. un pour les nombres comme identifiants, comme les numéros de carte de crédit, et un pour compter les nombres, comme les nombres à virgule flottante.
njzk2
1
@MotiKorets ne fonctionne pas pour entrer des nombres à virgule flottante car les iPhones ne mettent pas de point décimal sur le clavier. Malheureusement, les développeurs sont assez foutus pour le moment en ce qui concerne la fourniture d'une belle entrée en virgule flottante UX ...
Andy
50

Cela ne répond pas à la question, mais la solution de contournement utile consiste à vérifier

edQuantity.validity.valid

Le ValidityStated'un objet donne des indices sur ce que l'utilisateur a entré. Considérez une type="number"entrée avec un minet un maxensemble

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

Nous voulons toujours utiliser .validity.valid.

D'autres propriétés ne donnent que des informations bonus:

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

Vous devrez vous assurer que le navigateur prend en charge la validation HTML5 avant de l'utiliser:

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

Prime

Spudly a une réponse utile qu'il a supprimée:

Utilisez simplement le :invalidsélecteur CSS pour cela.

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

Cela déclenchera votre élément pour devenir rouge chaque fois qu'un valide non numérique est entré.

Le support du navigateur pour <input type='number'>est à peu près le même que :invalid, donc pas de problème là-bas.

En savoir plus :invalid ici .

Ian Boyd
la source
Ne fonctionne pas dans Opera. Il dit valide même si vous entrez une chaîne.
Bergi
Opera prend en charge la .validitypropriété, mais ne gère pas correctement .valid?!
Ian Boyd
C'est le cas, mais quand une entrée numérique est-elle invalide ? Il agit simplement comme si l'entrée était vide. Un typeMismatchpeut avoir du sens, mais ce n'est que pour les types de courrier électronique ou d'url ...
Bergi
@Bergi Le tableau ci-dessus donne des exemples où les entrées numériques peuvent être invalides: "q", "11" (alors le max est 10), "0" (quand le min est 1), "" (alors l'élément est required)
Ian Boyd
1
@Bergi a .badInputété ajouté le 20/11/2012 . Mais personne ne devrait regarder badInputpour voir si l'entrée est valide; ils devraient regarder .valid. Il est possible (et correct) .badInputd'être faux et d'avoir toujours une entrée invalide. .validest définie comme l'absence d'erreurs de validation (par exemple, les incohérences, les débordements, les sous-débits), dont .badInputun seul type d'erreur. Notez le graphique ci-dessus où .badInputest false, mais l'entrée n'est toujours pas valide.
Ian Boyd
4

Suivre toutes les touches enfoncées en fonction de leurs codes de touche

Je suppose que l'on pourrait écouter les événements keyup et conserver un tableau de tous les caractères entrés, en fonction de leurs codes clés. Mais c'est une tâche assez fastidieuse et probablement sujette à des bugs.

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

Sélectionnez l'entrée et obtenez la sélection sous forme de chaîne

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

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

Tout le crédit à: int32_t

Sandstrom
la source
Cette solution a été essayée ailleurs et ne fonctionne pas . Surtout quand les presses utilisateurs Delete, Backspace, Ctrl+X, Ctrl+V, Right-click-cut, Right-click-paste.
Ian Boyd
Je suis d'accord avec vous, ce que le PO a demandé n'est pas possible. Cependant, les deux hacks que j'ai mentionnés (et ce sont des hacks, je ne le nie pas) fonctionnent dans une certaine mesure. Peut-être peuvent-ils être utiles à quelqu'un, dans certains cas?
sandstrom
étonnamment, la sélection semble fonctionner. Quelles sont les limites de cette méthode?
njzk2
Limitations: le texte est sélectionné visuellement. Si l'utilisateur tape quelque chose, le contenu disparaîtra
fregante
Édité avec une démo en direct qui montre à quel point cette méthode est mauvaise
vsync