我已经阅读了关于这个主题的几个问题[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/)时,如果您将这些事件分配给页面本身—在鼠标xy更改时,在页面上输入leave和focusblur。
使用所有这些事件似乎有点过分,但这似乎是一个独特的情况。对我来说,你永远不会真正信任用户输入,所以我倾向于在用户提交数据时重新计算/验证数据,但对于这种数据没有提交给你的场景,我认为通过一些页面级事件触发这些项目,而不是输入特定事件,可能会让你度过难关……