问题
I've read several questions [1], [2], [3] regarding this topic, but none seems to provide a general solution to this problem. All answers seems to be directed to some specific cases.
I have this simple input field
<input type="number" id="inputBox" min="0" max="255" step="1" />
and I do a strict input validation on it:
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;
}
}
}
All this seems to be working fine for user input.
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" />
But the user can still modify the input field value programmatically. The user can enter the following values through the console to bypass the validation and these are invalid/unexpected values:
inputBox.value = "005";
inputBox.value = "2.5"
inputBox.value = "-05.5";
An ideal solution to this would be to call a function (e.g. validateProgrammaticInput()
) if the user changes the field value using inputBox.value
.
inputBox.value = -10; // magically call validateProgrammaticInput()
Note: I'm not using a form. There's no submit button. This will not be sent to a server. This is a client application. Value should be validated in real-time. If I want to modify the field value programmatically, I can trigger a custom event in my code to validate the input, but that's not the case. What I want is to validate the input, if the user enters it programmatically. So my use case is irrelevant to the problem. Thought I should point these out before a confusion.
回答1:
you can trigger the event programmaticaly after changing the value like this
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>
回答2:
So, to me, your event listeners aren't triggered at all because theyre not occurring. There's no "keydown" on the field when the values are changed programmatically, as no events are triggered in the DOM.
To me, I think you should wire some other event handler as well that's more "page level". In looking at the jQuery event categories (https://api.jquery.com/category/events/) what if you assigned these events to the page itself - on mouse x\y changing, on page enter\leave and focus\blur.
It may seem a little overboard to use all of these events, but this seems to be a unique case. To me, you never really trust user input, so I tend to recalculate\validate data when submit by the user, but for this scenario where the data isn't being submitted to you, I think triggering these items by some page level events rather than input specific events may get you over the hump...
来源:https://stackoverflow.com/questions/39249781/how-to-detect-programmatic-value-change-on-input-field