如何检测输入字段上的编程值变化

How to detect programmatic value change on input field

本文关键字:编程 变化 字段 输入 何检测 检测      更新时间:2023-09-26

我已经阅读了关于这个主题的几个问题[1], [2], [3],但似乎没有一个提供这个问题的一般解决方案。所有的答案似乎都指向一些具体的案例。

我有这个简单的输入字段

<input type="number" id="inputBox" min="0" max="255" step="1" />

,我对它做了严格的输入验证:

inputBox.addEventListener("input", function () {
    validateInput(this);
});
inputBox.addEventListener("keydown", function (e) {
    validateInput(this, e);
});
function validateInput(elm, e) {
    // handle keydown event
    if (e) {
        // do not allow floating-point numbers, if it's not expected
        if (!isFloat(elm.step)) {
            if (e.key == ".") {
                e.preventDefault();
            }
        }
    }
    // handle input event
    else {
        // do not allow leading zeros
        while (elm.value.length > 1 && elm.value[0] === "0") {
            elm.value = elm.value.toString().slice(1);
        }
        // input should be between min and max
        if (elm.validity.rangeUnderflow) {
            elm.value = elm.min;
        }
        else if (elm.validity.rangeOverflow) {
            elm.value = elm.max;
        }
    }
}

对于用户输入,所有这些似乎都工作得很好。

var inputBox = document.getElementById("inputBox");
inputBox.addEventListener("input", function() {
  validateInput(this);
});
inputBox.addEventListener("keydown", function(e) {
  validateInput(this, e);
});
function validateInput(elm, e) {
  // handle keydown event
  if (e) {
    // do not allow floating-point numbers, if it's not expected
    if (!isFloat(elm.step)) {
      if (e.key == ".") {
        e.preventDefault();
      }
    }
  }
  // handle input event
  else {
    // do not allow leading zeros
    while (elm.value.length > 1 && elm.value[0] === "0") {
      elm.value = elm.value.toString().slice(1);
    }
    // input should be between min and max
    if (elm.validity.rangeUnderflow) {
      elm.value = elm.min;
    } else if (elm.validity.rangeOverflow) {
      elm.value = elm.max;
    }
  }
}
function isFloat(f) {
  var f = parseFloat(f);
  var floor = Math.floor(f);
  var fraction = f - floor;
  if (fraction > 0) {
    return true;
  }
  return false;
}
<input type="number" id="inputBox" min="0" max="255" step="1" />

但是用户仍然可以通过编程方式修改输入字段的值。用户可以通过控制台输入以下值来绕过验证,这些值是无效的/意外的值:

inputBox.value = "005";
inputBox.value = "2.5"
inputBox.value = "-05.5";

理想的解决方案是,如果用户使用inputBox.value更改字段值,则调用函数(例如validateProgrammaticInput())。

inputBox.value = -10; // magically call validateProgrammaticInput()

注意:我没有使用表单。没有提交按钮。这不会被发送到服务器。这是一个客户机应用程序。应该实时验证价值。如果I希望以编程方式修改字段值,我可以在代码中触发一个自定义事件来验证输入,但事实并非如此。我想要的是验证输入,如果用户以编程方式输入的话。所以我的用例与问题无关。

您可以在像这样更改值后以编程方式触发事件

var inputBox = document.getElementById("inputBox");
inputBox.addEventListener("input", function () {
  console.log("input");
    // input should be between min and max
    if (this.validity.rangeUnderflow) {
        this.value = this.min;
    }
    else if (this.validity.rangeOverflow) {
        this.value = this.max;
    }
    // do not allow leading zeros
    while (this.value.length > 1 && this.value.toString()[0] === "0") {
        this.value = this.value.toString().slice(1);
    }
});
inputBox.addEventListener("keydown", function (e) {
    // do not allow floating-point numbers, if it's not expected
    if (!isFloat(this.step)) {
        if (e.key == ".") {
            e.preventDefault();
        }
    }
},false);
function change(){
  inputBox.value = "005";
  inputBox.dispatchEvent(new Event('input'));
}
function isFloat(n){
    return Number(n) === n && n % 1 !== 0;
}
<input type="number" id="inputBox" min="0" max="255" step="1" />
<button onclick="change()">change</button>

所以,对我来说,您的事件侦听器根本没有被触发,因为它们没有发生。当以编程方式更改值时,字段上没有"keydown",因为DOM中没有触发事件。

对我来说,我认为你应该连接一些其他的事件处理程序,以及更多的"页面级"。在查看jQuery事件类别(https://api.jquery.com/category/events/)时,如果您将这些事件分配给页面本身—在鼠标x'y更改时,在页面上输入'leave和focus'blur。

使用所有这些事件似乎有点过分,但这似乎是一个独特的情况。对我来说,你永远不会真正信任用户输入,所以我倾向于在用户提交数据时重新计算/验证数据,但对于这种数据没有提交给你的场景,我认为通过一些页面级事件触发这些项目,而不是输入特定事件,可能会让你度过难关……