防止 input type=“number" 的值超过一个点并限制小数位数

Inbefore:我知道这个问题在这个论坛上被问过不止一次.我知道我可以在这些其他帖子上发布我的答案.我的问题是,提出这些问题的用户是 3 到 4 年前提出的,并且查看他们的 autors 个人资料,他们似乎不太活跃,我相信这些问题永远不会被标记为已解决.

Inbefore: I know this question has been asked more than once on this forum. I know I could post my answer on these other posts. My issue is that the users who asked those questions did it 3 - 4 years ago, and looking at their autors profile, they do not seem very active and I beleive the questions would never be marked as solved.

所以我一直在四处寻找帮助,但没有简单的解决方案可以限制用户在输入 type=number" 中输入多个点.保持输入 type="number" 很重要,因为它可能会影响某些移动设备上的键盘.

So I've been looking around every where to find help on doing exactly that, with no simple solutions allowing to limit the user from typing more than one dot in an input type="number". It is important to keep the input type="number" as it may affect the keyboard on certain mobile devices.

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

I know it might seem limitative to prevent a keyboard event, and some might argue that the field should only be evaluated on submit or on change or on blur. I say the input type="number" already limits the effects of certain keypresses that are anything but numbers or "e" or ".", and that happens on the fly.

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

On top of it, some solutions made it impossible to limit the amount of floats allowed.

推荐答案

你可以在这个 Codepen 中找到非常详细的解释

You can find very detailed explainations in this Codepen

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

This solution is simple and will only allow one dot in the number field. It doesn't prevent from clicking back in the number and adding numbers before the ".". It doesn't prevent from executing browser keyboard shortcuts like refresh, copy and pasting (as long as the pasted value is a valid number) and others. It will allow to add "." withing the body of the number, but will remove any exceeding floats over the set limit.

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

The only behavior that I still can't prevent is if you press the dot key at the end of the input repeatedly, the dot will blink on and off. This happens because a typed value of "13." is a valid number and returns "13" and a typed value of "13.." is not and returns "". In my solution, if a value returns "" without the press of backspace or delete, it gets rolled back to the last valid value, wich is "13", obtained from the typed value "13.".

我已经尝试过解决方案,如果一个点被按下一次,它会被阻止第二次触发,但每次我设法在已经存在的点之后按下点,然后什么都没有,然后得到除非我先按任何其他键,否则无法键入点.

I've tried solutions where if a dot was pressed once, it was prevented to be triggered a second time, but every time I managed to get stuck with pressing the dot right after an already existing dot followed by nothing and then get stuck with not being able to type a dot unless I pressed any other key first.

我认为多次按下时闪烁是最好的解决方案,因为用户无法键入一个点而没有任何反应.

I think the blinking on multiple press is the best solution for ther's no way a user would type a dot and nothing happens.

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)">

相关文章