防止输入类型=“数字”在其值中获得超过一个点并限制小数位数

Prevent input type=“number” from getting more than one dot in its value and limit decimals numbers

之前: 我知道这个问题在这个论坛上已经被问过不止一次了。我知道我可以 post 我对这些其他 post 的回答。我的问题是,提出这些问题的用户在 3 到 4 年前提出过,并且查看他们的作者资料,他们似乎并不十分活跃,我相信这些问题永远不会被标记为已解决。

因此,我一直在四处寻找帮助来准确地做到这一点,但没有简单的解决方案可以限制用户在输入类型 =“数字”中键入多个点。保持输入类型="number" 很重要,因为它可能会影响某些移动设备上的键盘。

我知道防止键盘事件似乎有局限性,有些人可能会争辩说该字段应该只在提交、更改或模糊时进行评估。我说输入 type="number" 已经限制了某些按键的效果,除了数字或 "e" 或“.”,而且这是即时发生的。

最重要的是,一些解决方案无法限制允许的浮动数量。

你可以找到非常详细的解释in this Codepen

这个解决方案很简单,在数字字段中只允许一个点。它不会阻止在数字中返回并在 "." 之前添加数字。它不会阻止执行浏览器键盘快捷键,如刷新、复制和粘贴(只要粘贴的值是有效数字)和其他。它将允许在数字正文中添加 ".",但会删除超过设定限制的任何超出的浮点数。

我仍然无法阻止的唯一行为是,如果您反复按输入末尾的点键,点会闪烁。发生这种情况是因为 "13." 的键入值是有效数字,而 returns "13""13.." 的键入值不是 returns ""。在我的解决方案中,如果值 returns "" 没有按退格键或删除键,它会回滚到最后一个有效值,即 "13",从键入的值 "13."

我已经尝试过这样的解决方案,如果一个点被按下一次,它就不会被第二次触发,但每次我都设法在一个已经存在的点之后立即按下该点,然后什么也没有,并且除非我先按任何其他键,否则无法输入点。

我认为多次按下时闪烁是最好的解决方案,因为用户不可能键入一个点却什么也没有发生。

let lastValidInputValue;
let selectedDot = false;


const onKeypress = (e) => {
  if (e.key === "." && e.target.value.indexOf(".") !== -1 && !selectedDot) e.preventDefault();
  selectedDot = false;

  if (e.key === "e") e.preventDefault();
};


const onInput = (e) => {
  if (
    e.target.value.indexOf(".") < e.target.value.length - e.target.getAttribute("data-toFixed") - 1 &&
    e.target.value.indexOf(".") !== -1
  ) {
    let newValue;
    newValue = e.target.value.slice(
      0,
      e.target.value.indexOf(".") +
        parseInt(e.target.getAttribute("data-toFixed")) +
        1
    );
    newValue = parseFloat(newValue);
    e.target.value = newValue;
  }
  if (e.target.value !== "") {
    lastValidInputValue = e.target.value;
  } else if (e.inputType.match(/delete/g)) {
    lastValidInputValue = "";
  } else {
    e.target.value = lastValidInputValue;
  }
};

 const onSelect = (e) => {
   if(window.getSelection().toString().indexOf(".") > -1) selectedDot = true;
 }
<input type="number" id="myNumber" name="myNumber" data-toFixed="2" step="any" onkeypress="onKeypress(event)" oninput="onInput(event)" onselect="onSelect(event)">