【问题标题】:Regex to allow only numbers and decimals not working in Javascript正则表达式只允许在 Javascript 中不起作用的数字和小数
【发布时间】:2017-06-18 05:42:55
【问题描述】:

我正在尝试下面的代码,但正则表达式不起作用,它允许输入框中的所有字符。

要求:输入文本框不应接受除数字和小数点以外的任何其他字符。

<html>
<body>
    <input type="text" onkeypress="myfunction(event);"></input>
<script>
    function myfunction(e){
         var p = new RegExp(/^[0-9]+([.][0-9]+)?$/);
         return e.charCode === 0 ||   p.test(String.fromCharCode(e.charCode));      
    }
</script>
</body>
</html>

【问题讨论】:

标签: javascript html regex


【解决方案1】:

这是另一种方法。我正在使用oninput 事件,该事件在用户每次更改值时触发(不仅是按键)。我正在保存最后一个有效值并在新值无效时恢复它。

<input type="text" id="test1" oninput="validateNumber(this);" />
<script>
var validNumber = new RegExp(/^\d*\.?\d*$/);
var lastValid = document.getElementById("test1").value;
function validateNumber(elem) {
  if (validNumber.test(elem.value)) {
    lastValid = elem.value;
  } else {
    elem.value = lastValid;
  }
}
</script>

与这里的大多数其他答案相比,它可以完美地使用所有输入技术,如拖放、复制和粘贴等。它还支持特殊的控制键,如 Ctrl+a(用于选择内容)、Pos1 , End 等等。

【讨论】:

  • 这种方法有一个与用户体验相关的小缺点。每当用户将光标放在已键入的值内的某个位置并键入与模式不匹配的内容时,光标就会在输入的末尾跳转。
  • 好点,@WiktorStribiżew。我认为这是因为我们在错误输入时替换了整个字符串。我会想办法解决这个问题。
  • 你需要把光标所在的地方存起来,然后放回去。我曾经尝试过这种方式,它涉及很多代码:(
  • 我刚刚玩过oninput 事件,但它没有提供更改完成之前有关光标位置的信息。您需要在每个 mousedownkeydown 事件上保存光标位置,这听起来确实是非常多的代码,但效果却很小。
  • 非常感谢@HubertGrzeskowiak
【解决方案2】:

您每次将 1 个字符传递给 myfunction 函数,因此您无法使用 /^[0-9]+([.][0-9]+)?$/ 正则表达式检查整个值以确保遵守您的格式。

检查您是否输入了数字,或者如果输入字段中还没有点,则只允许输入点:

<input type="text" id="test" onkeypress="return myfunction(event);" />
<script>
function myfunction(e) {
  return e.charCode === 0 || ((e.charCode >= 48 && e.charCode <= 57) || (e.charCode == 46 && document.getElementById("test").value.indexOf('.') < 0));
}
</script>

【讨论】:

  • 这样就可以了。我以前试过这个。我正在寻找一个单独使用正则表达式的解决方案,给我一个“单线”验证。无论如何,我似乎不能为此使用正则表达式。
  • 这在拖放和复制时失败。它还破坏了基于键盘的复制粘贴。
【解决方案3】:

尝试将字符串存储在“缓冲区”中:

<html>
<body>
    <input type="text" onkeypress="myfunction(event);"></input>
<script>
    var inputString = "";
    function myfunction(e){
         if (e.charCode === 0)
           return true;
         var p = new RegExp(/^[0-9]+([.][0-9]+)?$/);
         var testString = inputString + String.fromCharCode(e.charCode);
         if (p.test(testString))
           return true;
         inputString = testString;      
    }
</script>
</body>
</html>

因为我没有测试它,所以带一点盐:)

您也可以只读取输入的内容,但这并不一定很漂亮。另一方面,使用我的解决方案,您会遇到诸如退格或用户单击文本中间并以这种方式输入的问题。这只是为了让您了解这些限制。

【讨论】:

    【解决方案4】:

    应该在函数前加一个“return”。

    HTML:

    <input type="text" value="" onkeypress="return myfunction(event)" />
    

    JS:

    function myfunction(e){
      var p = new RegExp(/^[0-9]+([.][0-9]+)?$/);
      return e.charCode === 0 || p.test(String.fromCharCode(e.charCode));
    }
    

    关于正则表达式:

    正则表达式的问题是“。”是后面有数字的子集的一部分。 所以:“5。”无效,但“5.3”有效。但是,每次按键都会运行该函数!

    所以让我们试着写:5.3应该是有效的:

    5 - 有效

    。 - 无效

    3 - 有效

    解决方案是允许一个“。”只要它跟在一个数字之后,就可以单独使用。

    之后必须进行另一次验证,以确保“.”后面有数字。

    JSFIDDLE

    【讨论】:

    • Return 使其正常工作,但现在不接受小数。
    • 这个答案说明了为什么 OP 的解决方案不起作用但它没有提供解决方案。
    • 第一部分解决了一个问题,第二部分是关于如何解决正则表达式问题(“点”)的指南。 @Wiktor 的答案集中在该部分的解决方案上。
    【解决方案5】:

    我修改了@Wiktor Stribiżew 解决方案以允许从剪贴板插入,并确保您和我可以在多个输入元素上使用此解决方案,而无需针对单个元素。

    <input type="tel" onkeypress="return allowOnlyNumbers(event);" oninput="return allowOnlyNumbers(event);"/>
    

    注意事项

    1. [oninput] 将帮助我们从剪贴板插入。

    2. [onkeypress] 可以帮助我们处理单个字符。

      function allowOnlyNumbers(e)
      {
          // on input
          if (e.inputType == "insertFromPaste")
          {
              var validNumber = new RegExp(/^\d*\.?\d*$/);
              return (!validNumber.test(e.target.value) ? e.target.value = '' : e.target.value);
          }
      
          // on key press
          return e.charCode === 0 || ((e.charCode >= 48 && e.charCode <= 57) || (e.charCode == 46 && e.target.value.indexOf('.') < 0));
      }
      

    【讨论】:

      【解决方案6】:

      如果您使用的是 jquery,您可以执行以下操作

      let lastValid = $("#Control").val();
      $('#Control').on('input', function () {
          var validNumber = new RegExp(/^\d*\.?\d*$/);
          var newValue = $(this).val();
          if (validNumber.test(newValue)) {
              lastValid = newValue;
          } else { $(this).val(lastValid); }
      });
      

      【讨论】:

        【解决方案7】:

        这是我针对 StimulusJS 和 Rails 的解决方案。我有两个不同的正则表达式。首先,我检查输入是否为小数。我用这个支持德语小数的函数来做:

        export function decimalMatchFor( lang, value ) { 
          if (lang == null || lang == "") {
            return value.match(/^\d+\.\d{0,2}/igm);
          }
        
          if (lang == "de") {
            return value.match(/^\d+\,\d{0,2}/igm);
          } else if (lang == "en") {
            return value.match(/^\d+\.\d{0,2}/igm);
          } else {
            return value.match(/^\d+\.\d{0,2}/igm);
          }
        }
        

        在刺激控制器中,我正在使用以下代码:

        let lang = document.documentElement.lang;
        let cleaned = ""  
        let numberMatch = this.duration_floatTarget.value.match(/^\d+/);
        let decimalMatch = decimalMatchFor(lang, this.duration_floatTarget.value)
        if (decimalMatch) {
          cleaned = decimalMatch[0]
        } else if (numberMatch) {
          cleaned = numberMatch[0]
        }
        this.duration_floatTarget.value = cleaned;
        

        这对我来说效果很好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-20
          • 1970-01-01
          • 1970-01-01
          • 2011-05-19
          相关资源
          最近更新 更多