【问题标题】:How to allow only digits to be entered into an input[type="number"] field?如何只允许在 input[type="number"] 字段中输入数字?
【发布时间】:2017-09-28 13:08:24
【问题描述】:

我有一个输入字段,用户应该只能在其中输入数字 [0-9]

document.getElementById("integer").addEventListener('input', restrictToInteger);
function restrictToInteger() {
    this.value = this.value.replace(/[^\d]/g, '');
}
<input type="number" id="integer" />

jsFiddle Demo

问题是这样的:当我输入一个数字(例如1234)然后按点(.),+或-输入字段的内容被浏览器自动删除(值设置为"" = 空字符串)。但为什么?将类型从 number 更改为 text 似乎可以解决问题。但是后来我失去了输入字段的向上/向下箭头功能。有什么想法吗?

【问题讨论】:

  • 演示中没有发生。输入点时输入未清除
  • 在chrome中验证JSFiddle,输入字段的内容没有被清除。
  • 无效值不返回带输入数字的字符串
  • @JennyO'Reilly 什么浏览器消失了?
  • @JennyO'Reilly 根据 w3c 规范[...]The value attribute, if specified and not empty, must have a value that is a valid floating-point number.[...],所以你只能得到this.value,如果它是有效的。如何报告无效输入取决于浏览器。 4.10.5.1.9 Number state (type=number).

标签: javascript html input


【解决方案1】:

HTML 4 有一个名为onkeypress事件。有了这个属性,我们可以在不使用额外 JS 的情况下做到这一点:

<input type="number" onkeypress="return (event.charCode == 8 || event.charCode == 0 || event.charCode == 13) ? null : event.charCode >= 48 && event.charCode <= 57">

此处从09 的数字允许使用从4857event.charCode

【讨论】:

【解决方案2】:

我认为浏览器清除输入值的原因是因为带有两个点的字符串不是数字。

关于您的代码的一些更正:

如果您想接受带小数部分的数字,您需要更改表达式正则。现在,您只是表示您想接受数字 [0-9] 而不再接受字符。

要完成您想要的,您需要将/[^\d]/g 更改为/[^\d.]/g

document.getElementById("integer").addEventListener('input', restrictToInteger);

function restrictToInteger()
{
  this.value = this.value.replace(/[^\d.]/g, '');
}
<input type="number" id="integer" />

但是:如果您将输入定义为数字类型,则不需要正则表达式。因此,您只需要像这样定义输入,并且应该根据您的情况:

<input type="number" id="integer" />

[解决方案]

为了完全满足您的需求,我提供了一个解决方案,可以捕获输入的 keydown 事件并检查是否有任何 '.'在输入上。如果是,我会阻止字符进入输入。

document.getElementById("integer").addEventListener('keydown', restrictToInteger);
var lastCodeWasDot = false;
function restrictToInteger(e)
{
   var inputValue = document.getElementById("integer").value;
   var isDot = false;
   var isDot = (e.keyCode && e.keyCode == 110) || (e.charCode && e.charCode == 190);
   console.log(e.keyCode);
   if(isDot && (inputValue.indexOf(".") > -1 || inputValue == "" || lastCodeWasDot)) {
       e.preventDefault();
   }
   lastCodeWasDot = isDot;
   
}
<input type="number" id="integer" />

解释解决方案

需要var isDot = (e.keyCode && e.keyCode == 110) || (e.charCode && e.keyCode == 190) || false;这行代码,因为跨浏览器兼容性

我现在不知道为什么,但是如果您尝试从 Firefox 中的输入数字类型中获取值,并且如果该值以点结尾,那么您将获得的值将没有输入的最后一个点.为了解决这个问题,我需要添加变量lastCodeWasDot 来解决这个问题。

注意:数字输入可以接受浮点数,包括负号和 e 或 E 字符(查看this 帖子)

【讨论】:

  • @JennyO'Reilly 我提出了一个更广泛的答案。如果您有更多问题,请随意填写
  • 问题是简单地设置 type='number' 仍然允许用户在字段中输入千位分隔符(例如逗号)。我希望用户只能输入数字。没有别的了。
  • 但您仍然可以输入数千个点。不是OP想要的。 :-)
  • @JennyO'Reilly 现在我认为这可以解决您的问题。你能检查我是否真的理解你的问题并解决它吗?
  • @RicardoRocha 对我来说,同样使用 Firefox,我仍然可以输入字母。它并没有阻止我,它只是添加了一个红色轮廓(这很酷)。
【解决方案3】:

根据Alexandru-Ionut Mihainatchiketa 的回答,我创建了以下解决方案:

document.getElementById("integer").addEventListener("input", allowOnlyDigits);

function allowOnlyDigits() {  
  if (this.validity.valid) {
    this.setAttribute('current-value', this.value.replace(/[^\d]/g, ""));
  }
  this.value = this.getAttribute('current-value');
}
<input type="number" id="integer" />

在输入时检查值的有效性。如果它是有效的,那么所有的非数字都被移除并且值被存储在元素的一个自定义属性中。如果该值无效,则恢复之前的值。

注意事项:

  • RegEx 替换仅适用于 Internet Explorer,因为它允许您在数字末尾输入 ,.
  • 在 IE、Edge、Chrome 和 Firefox 中测试
  • Chrome 仍允许您在数字前输入 +,在数字后输入 ,
  • 我发现了一个问题:如果使用值初始化字段,当您第一次在键盘上敲击无效字符时,该值会丢失。
  • 另一个问题:您不能输入负数。

【讨论】:

    【解决方案4】:

    唯一的问题是您的输入类型。将其更改为text,它应该可以工作!

    function validate(e) {
        var charCode = e.keyCode? e.keyCode : e.charCode
        if (!(charCode >= 48 && charCode <= 57)) {
            if(!(charCode>=37 && charCode<=40))
                if(charCode!=8 && charCode!=46)
                return false;
        }
    }
    <input type="number" id="integer" pattern="[0-9]"
    onkeydown="return validate(event)"/>

    【讨论】:

    • 我知道它可以与 type='text' 一起使用,如问题末尾所述。 ;-)
    • 使用此方法时箭头键功能丢失。虽然我知道用js很容易模拟出来。
    • @JennyO'Reilly 我已经更新了我的答案,抱歉我错过了你的最后一行
    • @JennyO'Reilly 导航意义?
    • 对不起。我的意思是,您不能再使用箭头键在字段内移动光标。
    【解决方案5】:

    您可以通过copying输入的值并使用setAttributegetAttribute方法来存储这些值来实现您的要求。

    function myFunction(input){
      input.setAttribute('current-value',"");
      input.oninput=function(){  
          let currentValue=input.getAttribute('current-value');
          if(input.value!='' || (currentValue>=1 && currentValue<=9))
            input.setAttribute('current-value',input.value);
          input.value=input.getAttribute('current-value');
      }
    }
    <input type="number" oninput="myFunction(this)"/>
    <input type="number" oninput="myFunction(this)"/>
    <input type="number" oninput="myFunction(this)"/>
    <input type="number" oninput="myFunction(this)"/>
    <input type="number" oninput="myFunction(this)"/>

    【讨论】:

    • 不错。有什么方法可以实现更模块化的解决方案,以便可以将其应用于不需要全局变量的任意数量的输入字段?
    • 这不会让你删除输入的值:)
    • @Walk:对。 :-D
    • @JennyO'Reilly,我实现了一个更加模块化的解决方案,以便它可以应用于任意数量的输入字段,使用 hashtable
    • @JennyO'Reilly 你可以像这样保存它this.setAttribute('oldValue', '123'); 我同意,这是一个更简单的解决方案。
    【解决方案6】:

    当您调用oninput 时,&lt;input&gt; 元素首先调用其内部方法来处理该值。这可以防止您的函数看到任何实际的错误字符,即 e+-. - 所有这些都被 JavaScript 用于格式化数字。

    您可以通过在更改 this.value 之前和之后添加 console.log 调用来看到这一点。

    console.log(this.value);
    this.value=this.value.replace(/[^\d]/g, '');
    console.log(this.value);
    

    没有任何区别!

    如果你尝试,例如:

    console.log(this.value);
    this.value+=1; // or *=2 for numerical fun
    console.log(this.value);
    

    你可以看到不同。

    因此,您的函数正在加速正常的内部调用 &lt;input type='number'/&gt; 在处理非法输入时通常会进行。

    不太明白为什么该字段为空而不是1

    【讨论】:

      【解决方案7】:

      我会切换到cancelable 事件,例如keydown
      这样一来,您就可以防止输入字符:

      var cancelEvent = function (e) {
          e.preventDefault();
          return false;
      },
      restrictToInteger = function restrictToInteger(e) {
          var acceptableInput = /[0-9]/g,
              clipboardKeys = /[zxcv]/ig,
              field = e.key || e.char,
            isClipboardOperation = (clipboardKeys.test(field) && e.ctrlKey),
              inputIsAcceptable = field ? (
                  acceptableInput.test(field)
                  || field.length > 1
                  || isClipboardOperation
              ) : true;
      
          if (!inputIsAcceptable) {
              cancelEvent(e);
          }
      },
      ensureIntegerValueOnPaste = function ensureIntegerValueOnPaste(e) {
      	var data = e.clipboardData || e.dataTransfer,
        		text = data.getData('text'),
              int = parseInt(this.value + text, 10);
      
          if (isNaN(int)) {
              cancelEvent(e);
          } else {
              window.setTimeout(function () {
                  e.target.value = int;
              }, 0);
          }
      },
      input = document.getElementById("integer");
      
      input.addEventListener('keydown', restrictToInteger);
      input.addEventListener('drop', ensureIntegerValueOnPaste);
      input.addEventListener('paste', ensureIntegerValueOnPaste);
      &lt;input type="number" id="integer" /&gt;

      更新小提琴:https://jsfiddle.net/838pa8hv/2/

      免责声明:

      • 仅在 Chrome 中测试。
      • field.length &gt; 1 的测试是捕获有效的非数字键,因为向上/向下箭头的值分别为 ArrowUpArrowDown。这也允许按下 Shift(或 HomeBackspaceDelete 等)等键。

      编辑: 要处理粘贴(和掉落),您可以在相应的事件中执行相同的操作。 Updated fiddle 和上面的代码 sn-p。

      编辑
      如果预期的可用性是能够将部分数字粘贴/拖放到字段以不允许负整数,那么您只需更改intensureIntegerValueOnPaste 函数中的定义方式。 Updated fiddle 和上面的代码 sn-p。

      【讨论】:

      • 我发现了一个错误。 :-) 您可以将字母复制/粘贴到字段中。
      • @JennyO'Reilly 更新了我的答案。希望对您有所帮助。
      • 嘿,谢谢!如果我输入“1”,我无法在其后面粘贴“2”。粘贴似乎会覆盖整个内容。这是故意的吗?
      • @JennyO'Reilly 我会考虑这种预期行为,因为我认为大多数人不会输入数字的一部分然后粘贴或删除其余部分。通常,我认为他们要么粘贴/删除,要么只输入数字。您可以通过从isNaN(int) 条件中删除整个虚假子句来更改行为以允许部分粘贴/删除.我不喜欢这样,因为- 可能会出现在场地的中间或末端,这……看起来很傻。
      • 我明白了。然而,预期的可用性正是:粘贴数字的一部分。不过有一件事:你不能输入负值,对吗? (但是问题最初并没有要求)
      【解决方案8】:

      你不需要正则表达式,你可以使用parseFloat()函数。您的输入类型保持不变,仍然有“箭头”来增加/减少数字,并且它确保您的输入不会从零开始。

      document.getElementById("integer").addEventListener('input', restrictToInteger);
      function restrictToInteger() {
        this.value = parseFloat(this.value);
      }
      &lt;input type="number" id="integer" /&gt;

      【讨论】:

      • 这不起作用,因为我们已经在其他人的帮助下发现,如果浏览器认为该字段的值不是有效数字,它会自动清除该字段的值。
      【解决方案9】:

      您必须检查该值是否不是数字然后停止用户。

      document.getElementById("integer").addEventListener('input', restrictToInteger);
      
      function restrictToInteger(e)
      {
        if(isNaN(e.data)){
           alert("only numbers allowed");
        }
      }
      &lt;input type="number" id="integer" /&gt;

      【讨论】:

      • 但是如果你输入一个有效的数字然后点击一个点,该字段的内容就会被浏览器删除。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      • 2016-03-07
      • 2014-09-14
      • 1970-01-01
      • 2022-11-22
      • 2018-03-06
      • 2016-07-02
      相关资源
      最近更新 更多