【问题标题】:Prevent typing non-numeric in input type number防止在输入类型编号中输入非数字
【发布时间】:2013-11-26 19:12:15
【问题描述】:

如果输入不是有效数字,使用<input type=number> 将导致事件侦听器内部的this.value 返回一个空字符串。你可以在http://jsfiddle.net/fSy53/看到一个例子

但是,无效字符仍然显示在输入中。

有没有办法从事件监听器中获取实际显示的值,包括无效字符?

我的最终目标是防止用户在字段中实际输入任何非数字字符。我需要使用type=number,以便移动设备使用数字虚拟键盘。我的目标是在keyup keypress 上执行类似this.value = this.value.replace(/[^0-9.]/g, "") 的操作,但这不起作用,因为如果输入了无效字符,从this.value 读取会返回""

【问题讨论】:

  • 我想之前有人问过这个问题,答案是否定的,让我挖掘一下。 编辑:这里是:stackoverflow.com/questions/3090810/…
  • 关于数字键盘:有一个新的 HTML5 属性 inputmode 可以设置为 numeric 以显示数字键盘。不幸的是,根据mozilla,目前还没有浏览器支持它
  • 请注意,所描述的问题发生在 Firefox 中,但不在 Chrome 中。如果设置了type='number',Chrome 将阻止非数字字符出现在输入中。
  • 关于inputmode属性的更新:默认情况下任何浏览器仍然不支持它(参见caniuse.com/#search=inputmode),但可以通过设置dom.forms.inputmode标志在Firefox中选择启用。跨度>
  • hmmm...“e”不是type=number中显示的唯一“无效”字符吗??

标签: javascript html


【解决方案1】:

如果您不喜欢传入的键值,请尝试阻止默认行为:

document.querySelector("input").addEventListener("keypress", function (evt) {
    if (evt.which < 48 || evt.which > 57)
    {
        evt.preventDefault();
    }
});

【讨论】:

  • keypress 事件仅在文档上触发。您需要为此设置一个键盘管理器
  • 不正确。 keypress 在输入元素上触发,并冒泡到文档
  • @megawac 你有引用吗?这与我的经验相反。 OP表示防止非数字内容是目标,我认为这是正确的方法:在它发生之前防止它,不要担心 .value
  • @GlennLane 问题在于,对于诸如$ 之类的移位键,.which 与非移位键相同,而在虚拟键盘上,e.shiftKey 未设置为真实的价值。相关:stackoverflow.com/questions/19964074/…
  • 这样你就不能按箭头,退格等键,存在扩展解决方案stackoverflow.com/a/995193/691194
【解决方案2】:

您可以通过防止非数字值发生 keyPress 事件来实现此目的

例如(使用 jQuery)

$('.input-selector').on('keypress', function(e){
  return e.metaKey || // cmd/ctrl
    e.which <= 0 || // arrow keys
    e.which == 8 || // delete key
    /[0-9]/.test(String.fromCharCode(e.which)); // numbers
})

这说明了所有不同类型的输入(例如,数字键盘的输入与键盘的代码不同)以及退格键、箭头键、控制/cmd + r 重新加载等

【讨论】:

【解决方案3】:

请注意 e.whiche.keyCodee.charCode 已弃用:https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which

我更喜欢 e.key

document.querySelector("input").addEventListener("keypress", function (e) {
    var allowedChars = '0123456789.';
    function contains(stringValue, charValue) {
        return stringValue.indexOf(charValue) > -1;
    }
    var invalidKey = e.key.length === 1 && !contains(allowedChars, e.key)
            || e.key === '.' && contains(e.target.value, '.');
    invalidKey && e.preventDefault();});

此函数通过检查字符串长度不会干扰 Firefox 中的控制代码(BackspaceTab 等):e.key.length === 1

它还可以防止在开头和数字之间出现重复的点:e.key === '.' &amp;&amp; contains(e.target.value, '.')

不幸的是,它并不能防止末尾出现多个点:234....

似乎没有办法应对。

【讨论】:

【解决方案4】:

其他答案似乎比必要的复杂,因此我将他们的答案调整为这个简短而甜蜜的功能。

function allowOnlyNumbers(event) {
  if (event.key.length === 1 && /\D/.test(event.key)) {
    event.preventDefault();
  }
}

它不会改变任何箭头键、enter、shift、ctrl 或 tab 键的行为,因为这些事件的键属性的长度比单个字符长。它还使用简单的正则表达式来查找任何非数字字符。

【讨论】:

  • 如果有人想要十进制数怎么办?比如10.01?这并不妨碍1.1.1 提交。
【解决方案5】:
inputs[5].addEventListener('keydown', enterNumbers);

function enterNumbers(event) {
  if ((event.code == 'ArrowLeft') || (event.code == 'ArrowRight') ||
     (event.code == 'ArrowUp') || (event.code == 'ArrowDown') || 
     (event.code == 'Delete') || (event.code == 'Backspace')) {
     return;
  } else if (event.key.search(/\d/) == -1) {
    event.preventDefault();
  }
}

在这种情况下,当按下非数字按钮时,输入字段的值保持不变,并且仍然可以删除,退格,上下左右箭头正常工作,可用于修改数字输入。

【讨论】:

    【解决方案6】:

    这个解决方案似乎对我很有效。它通过保留 ctrl 键命令建立在 @pavok 的解决方案之上。

    document.querySelector("input").addEventListener("keypress", function (e) {
      if (
        e.key.length === 1 && e.key !== '.' && isNaN(e.key) && !e.ctrlKey || 
        e.key === '.' && e.target.value.toString().indexOf('.') > -1
      ) {
        e.preventDefault();
      }
    });
    

    【讨论】:

      【解决方案7】:

      我也会添加 MetaKey,因为我使用的是 MacOS

      input.addEventListener("keypress", (e) => {
          const key = e.key;
          if (!(e.metaKey || e.ctrlKey) && key.length === 1 && !/\d\./.test(key)) {
              e.preventDefault();
          }
      }
      

      或者,你可以试试!isNaN(parseFloat(key))

      【讨论】:

        【解决方案8】:

        已接受答案的更新:

        因为许多属性被弃用

        (属性)KeyboardEvent.which: number @deprecated

        您应该只依赖 key 属性并自己创建其余逻辑:

        代码允许 Enter、Backspace 和所有数字 [0-9],不允许每隔一个字符。

        document.querySelector("input").addEventListener("keypress", (e) => {
          if (isNaN(parseInt(e.key, 10)) && e.key !== "Backspace" && e.key !== "Enter") {
              e.preventDefault();
            }
        });
        

        注意 这将禁用粘贴操作

        【讨论】:

          【解决方案9】:

          根据 Nrzonline 的回答:我修复了多个“。”的问题。在输入的末尾添加一个

          let lastCharacterEntered
          

          在输入之外再onKeyPress

          e => {
                    var allowedChars = "0123456789.";
                    function contains(stringValue, charValue) {
                      return stringValue.indexOf(charValue) > -1;
                    }
                    var invalidKey =
                      (e.key.length === 1 && !contains(allowedChars, e.key)) ||
                      (e.key === "." && contains(e.target.value, "."));
                    console.log(e.target.value);
                    invalidKey && e.preventDefault();
                    if (!invalidKey) {
                      if (lastCharacterEntered === "." && e.key === ".") {
                        e.preventDefault();
                      } else {
                        lastCharacterEntered = e.key;
                      }
                    }
                  }
          

          【讨论】:

            【解决方案10】:

            我刚刚遇到了同样的问题,并发现了使用验证 API 的替代解决方案 - 在除 IE 之外的所有主要浏览器(Chrome、Firefox、Safari)中都可以正常工作。此解决方案只是防止用户输入无效值。 我还包括了一个 IE 的后备方案,虽然不是很好,但至少可以工作。

            上下文:onInput函数在输入事件上被调用,setInputValue用于设置输入元素的值,previousInputValue包含最后一个有效的输入值(在 setInputValue 调用中更新)。

                function onInput (event) {
                    const inputValue = event.target.value;
            
                    // badInput supported on validation api (except IE)
                    // in IE it will be undefined, so we need strict value check
                    const badInput = event.target.validity.badInput;
            
                    // simply prevent modifying the value
                    if (badInput === true) {
                    // it's still possible to enter invalid values in an empty input, so we'll need this trick to prevent that
                        if (previousInputValue === '') {
                            setInputValue(' ');
                            setTimeout(() => {
                                setInputValue('');
                            }, 1);
                        }
                        return;
                    }
            
                    if (badInput === false) {
                        setInputValue(inputValue);
                        return;
                    }
            
                    // fallback case for IE and other abominations
            
                    // remove everything from the string expect numbers, point and comma
                    // replace comma with points (parseFloat works only with points)
                    let stringVal = String(inputValue)
                        .replace(/([^0-9.,])/g, '')
                        .replace(/,/g, '.');
            
                    // remove all but first point
                    const pointIndex = stringVal.indexOf('.');
                    if (pointIndex !== -1) {
                        const pointAndBefore = stringVal.substring(0, pointIndex + 1);
                        const afterPoint = stringVal.substring(pointIndex + 1);
            
                        // removing all points after the first
                        stringVal = `${pointAndBefore}${afterPoint.replace(/\./g, '')}`;
                    }
            
                    const float = parseFloat(stringVal);
                    if (isNaN(float)) {
                        // fallback to emptying the input if anything goes south
                        setInputValue('');
                        return;
                    }
                    setInputValue(stringVal);
            }
            

            【讨论】:

              【解决方案11】:

              防止在具有多个输入项的页面的特定输入 id 中键入非字母。它适用于 Oracle Apex 开发人员 --- 附加在页面的 HTML 标题中

              <script type="text/javascript">
              function validateNumber(event) {
                const activeElmnt = document.activeElement;  
                var keyCode = event.keyCode;
                var excludedKeys = [8, 37, 39, 46];
               
                 if ( activeElmnt.id == "input id in HTML page"){
                      if (!((keyCode >= 65 && keyCode <= 90) ||
                          (keyCode >= 97 && keyCode <= 122) ||
                          (excludedKeys.includes(keyCode)))) {
                          console.log("alphabets are not allowed");
                          event.preventDefault();
              
                }
              }
                console.log("keycode: " + keyCode + "ActiveElemet: "+activeElmnt.id);
              }
              </script>
              

              -- 附加在页面 HTML Body 属性中 onkeydown="validateNumber(event);"

              【讨论】:

                【解决方案12】:

                试试看:

                document.querySelector("input").addEventListener("keyup", function () {
                   this.value = this.value.replace(/\D/, "")
                });
                

                【讨论】:

                • 如果输入包含字符,则清除该值,而不仅仅是非数字字符。这是因为数字框的值是浮点数。因此(根据规范)非浮点数会将控件的值设置为 ''。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-10-13
                • 1970-01-01
                • 1970-01-01
                • 2021-12-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多