只允许输入数字的type="number"输入框

5
我希望创建一个输入框,只能输入自然数。(是的,我知道这可能不是最好的做法,因为用户无法获得任何反馈)。 如果输入的不是数字,则不应该出现在输入框中。 我想使用纯JavaScript(没有JQuery)。
通常情况下,我会这样做:
<input oninput="this.value = this.value.replace(/\D+/g, '')">

但我发现,在移动设备上更喜欢使用<input type="number">,因为它不显示整个键盘,而只显示数字。

所以我的问题是,如何将type="number"与筛选相结合(并使其与剪切/复制/粘贴兼容)?

如果输入任何非数字字符,则<input type="number">元素的值始终为一个空字符串。因此,我之前的筛选方法无法使用。有没有任何变通方法?

如果没有,我就必须监听keydown、paste、cut等许多事件。我需要考虑哪些事件,如何实现它,有没有我忽略的更简单的方法?


3
<input type="number" /> 中缺少什么?这并不清楚 type="number" 有什么限制,用户不能在其中输入除数字以外的任何内容。 - mplungjan
@mplungjan 我想它没有足够地妨碍用户。 - VLAZ
1
@mplungjan你可以在type="number"的输入框中键入任何字符。只是不符合规范而已。但我想完全阻止用户在输入框中输入其他字符。 - FireFuro99
@FireFuro99 https://dev59.com/cWULtIcB2Jgan1znm8E_#68394595 - mplungjan
你使用的是哪个浏览器?输入数字类型不允许我随意输入任何内容。 - Keith
3个回答

10

2
这里是一个使用HTML和原生JS的解决方案:

function setInputFilter(textbox, inputFilter) {
  ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].forEach(function(event) {
    textbox.addEventListener(event, function() {
      if (inputFilter(this.value)) {
        this.oldValue = this.value;
        this.oldSelectionStart = this.selectionStart;
        this.oldSelectionEnd = this.selectionEnd;
      } else if (this.hasOwnProperty("oldValue")) {
        this.value = this.oldValue;
        this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
      } else {
        this.value = "";
      }
    });
  });
}

setInputFilter(document.getElementById("numTxtBox"), function(value) {
  return /^-?\d*$/.test(value); });
  <tr><td>Number Only </td><td><input id="numTxtBox"></td></tr>

更新:

上述代码在Firefox和Chrome中出现故障。

以下是一个可在所有浏览器中运行的替代方案!

function validate(num) {
  var theEvent = num || window.event;

  // Handle paste
  if (theEvent.type === 'paste') {
      var key = event.clipboardData.getData('text/plain');
  } else {
  // Handle key press
      var key = theEvent.keyCode || theEvent.which;
      key = String.fromCharCode(key);
  }
  var regex = /[0-9]|\./;
  if( !regex.test(key) ) {
    theEvent.returnValue = false;
    if(theEvent.preventDefault) theEvent.preventDefault();
  }
}
<input type='number' onkeypress='validate(event)' onpaste='validate(event)' />


@FireFuro99 你是什么意思?在这个例子中,它只允许插入整数,以及复制/粘贴/Ctrl+A?你不应该需要 input type="number",因为这是一个变通方法。设置类型是多余的。 - BeerusDev
“input type="number"”是为移动设备提供数字键盘建议而必须使用,而非通常的字母键盘。这正是本问题的核心所在,请务必仔细阅读问题。 - FireFuro99
1
“它会中断”是指JS代码不再起作用。在将type =“number”添加到输入框后,您可以输入非数字字符。 请在Firefox中尝试。 (Chrome和Edge默认情况下会阻止您在type =“number”输入框中输入非数字字符。Firefox则不会。) - FireFuro99
1
onkeypress在你粘贴东西时不会触发,所以它不能处理粘贴。 但修复方法相当简单:(添加“onpaste = ...”)。 <input type ='number' onkeypress ='validate(event)' onpaste ='validate(event)'/> 此外,变量(用于键)的位置不正确。我会把它放在if之前: var key; if (theEvent.type ...) { key = ...; } else { key = ...; key = ...; } - FireFuro99
1
都没有注意到,谢谢你指出来!如果我的回答对你有帮助,请不要忘记将其标记为已接受!祝你有美好的一天。 - BeerusDev
显示剩余3条评论

2

在Chrome中测试(只能输入数字,-和e

在Firefox中可以输入但无法提交

Try typing anything and then hit enter
<form>
<input type="number" required />
</form>

那我们试试这个 - 如果在输入字符时清空字段是可以的,那么我们就不需要使用keyUp或其他方法了。

在任何地方输入字符时,Firefox会返回空字符串,Chrome则不允许输入字符。

document.querySelector("form").addEventListener("input",function(e) {
  const tgt = e.target;
  if (tgt.type && tgt.type==="number") { 
    const val = tgt.value;
    const nums = val.replace(/[^\d.-]/g, '');
    if (!/\d+/.test(val)) tgt.value="";
  }  
})
Try typing anything and then hit enter
<form>
<input type="number" required />
</form>


我正在台式电脑上(windows系统),使用最新版本的Firefox浏览器。在这里你可以进行测试。如果您需要,我可以测试其他浏览器,但我强烈认为结果将是相同的。 - FireFuro99
1
啊,我只用Chrome(ium) - mplungjan
@FireFuro99,你可以编写它们,但它们是无效的。如果你有1a2,表单将无法提交。 - VLAZ
1
是的,我知道这不会有效。但我希望在输入框中阻止用户首先输入非数字字符。 - FireFuro99
@FireFuro99,“但我想要阻止用户”,通常这不是对待用户的好方式。例如,我可能想使用Firefox,因为它允许我粘贴数值amount=£12.00,然后删除我不想要的部分。如果我不喜欢Firefox的这个功能,我会选择使用Chrome。在这两个浏览器中,当提交无效的数值时,都会出错,从用户的角度来看,这才是最重要的部分。当然,作为开发者,如果这很重要,那完全可以理解,但作为一个网页开发者,很容易变得过于控制,而实际上这会带来负面影响。 - Keith
1
@FireFuro99 最后一点提醒!!几乎每个我使用过的网站,开发人员都试图在输入方面变得聪明,即使使用了经过验证的UI工具包,如JQueryUI等,它们通常最终成为最难使用的网站,特别是在移动设备上。在您的情况下可能有很好的理由,但这只是需要注意的事项。 - Keith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接