防止在输入类型号中键入非数值类型

如果输入不是一个有效的数字,使用 <input type=number>将导致事件侦听器内的 this.value返回一个空字符串。您可以在 http://jsfiddle.net/fSy53/上看到这方面的一个例子

但是,无效字符仍然显示在输入中。

有没有办法从事件侦听器中获得实际上是 展示的值,包括无效字符?

我的最终目标是防止用户在字段中实际键入任何非数字字符。我需要使用 type=number,以便移动设备使用数字虚拟键盘。我的目标是在 keyup keypress上执行类似于 this.value = this.value.replace(/[^0-9.]/g, "")的操作,但这不起作用,因为如果输入了无效字符,从 this.value读取将返回 ""

123682 次浏览

Try it:

document.querySelector("input").addEventListener("keyup", function () {
this.value = this.value.replace(/\D/, "")
});

Try preventing the default behaviour if you don't like the incoming key value:

document.querySelector("input").addEventListener("keypress", function (evt) {
if (evt.which < 48 || evt.which > 57)
{
evt.preventDefault();
}
});

You can accomplish this by preventing the keyPress event from occurring for non-numeric values

e.g (using jQuery)

$('.input-selector').on('keypress', function(e){
return e.metaKey || // cmd/ctrl
e.which <= 0 || // arrow keys
e.which == 8 || // delete key
/[0-9]/.test(String.fromCharCode(e.which)); // numbers
})

This accounts for all different types of input (e.g. input from the number pad has different codes than the keyboard) as well as backspace, arrow keys, control/cmd + r to reload etc

Please note that e.which, e.keyCode and e.charCode are deprecated: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which

I prefer e.key:

document.querySelector("input").addEventListener("keypress", function (e) {
var allowedChars = '0123456789.';
function contains(stringValue, charValue) {
return stringValue.indexOf(charValue) > -1;
}
var invalidKey = e.key.length === 1 && !contains(allowedChars, e.key)
|| e.key === '.' && contains(e.target.value, '.');
invalidKey && e.preventDefault();});

This function doesn't interfere with control codes in Firefox (Backspace, Tab, etc) by checking the string length: e.key.length === 1.

It also prevents duplicate dots at the beginning and between the digits: e.key === '.' && contains(e.target.value, '.')

Unfortunately, it doesn't prevent multiple dots at the end: 234....

It seems there is no way to cope with it.

inputs[5].addEventListener('keydown', enterNumbers);


function enterNumbers(event) {
if ((event.code == 'ArrowLeft') || (event.code == 'ArrowRight') ||
(event.code == 'ArrowUp') || (event.code == 'ArrowDown') ||
(event.code == 'Delete') || (event.code == 'Backspace')) {
return;
} else if (event.key.search(/\d/) == -1) {
event.preventDefault();
}
}

in this case, the value of the input field stays intact when a non-number button is pressed, and still delete, backspace, arrowup-down-left-right work properly and can be used for modifying the digital input.

This solution seems to be working well for me. It builds on @pavok's solution by preserving ctrl key commands.

document.querySelector("input").addEventListener("keypress", function (e) {
if (
e.key.length === 1 && e.key !== '.' && isNaN(e.key) && !e.ctrlKey ||
e.key === '.' && e.target.value.toString().indexOf('.') > -1
) {
e.preventDefault();
}
});

I will add MetaKey as well, as I am using MacOS

input.addEventListener("keypress", (e) => {
const key = e.key;
if (!(e.metaKey || e.ctrlKey) && key.length === 1 && !/\d\./.test(key)) {
e.preventDefault();
}
}

Or, you can try !isNaN(parseFloat(key))

The other answers seemed more complicated than necessary so I adapted their answers to this short and sweet function.

function allowOnlyNumbers(event) {
if (event.key.length === 1 && /\D/.test(event.key)) {
event.preventDefault();
}
}

It won't do change the behavior of any arrow, enter, shift, ctrl or tab keys because the length of the key property for those events is longer than a single character. It also uses a simple regular expressions to look for any non digit character.

Update on the accepted answer:

Because of many properties becoming deprecated

(property) KeyboardEvent.which: number @deprecated

you should just rely on the key property and create the rest of the logic by yourself:

The code allows Enter, Backspace and all numbers [0-9], every other character is disallowed.

document.querySelector("input").addEventListener("keypress", ({ key, preventDefault }) => {
if (isNaN(parseInt(key, 10)) && !['Backspace', 'Enter'].includes(key)) {
preventDefault();
}
});

NOTE This will disable paste action

Based on Nrzonline's answer: I fixed the problem of the multiple "." at the end of the input by adding a

let lastCharacterEntered

outside of the input and then onKeyPress

e => {
var allowedChars = "0123456789.";
function contains(stringValue, charValue) {
return stringValue.indexOf(charValue) > -1;
}
var invalidKey =
(e.key.length === 1 && !contains(allowedChars, e.key)) ||
(e.key === "." && contains(e.target.value, "."));
console.log(e.target.value);
invalidKey && e.preventDefault();
if (!invalidKey) {
if (lastCharacterEntered === "." && e.key === ".") {
e.preventDefault();
} else {
lastCharacterEntered = e.key;
}
}
}

I just had the same problem and discovered an alternative solution using the validation API - works without black magic in all major browsers (Chrome, Firefox, Safari) except IE. This solution simply prevents users from entering invalid values. I also included a fallback for IE, which is not nice but works at least.

Context: onInput function is called on input events, setInputValue is used to set the value of the input element, previousInputValue contains the last valid input value (updated in setInputValue calls).

    function onInput (event) {
const inputValue = event.target.value;


// badInput supported on validation api (except IE)
// in IE it will be undefined, so we need strict value check
const badInput = event.target.validity.badInput;


// simply prevent modifying the value
if (badInput === true) {
// it's still possible to enter invalid values in an empty input, so we'll need this trick to prevent that
if (previousInputValue === '') {
setInputValue(' ');
setTimeout(() => {
setInputValue('');
}, 1);
}
return;
}


if (badInput === false) {
setInputValue(inputValue);
return;
}


// fallback case for IE and other abominations


// remove everything from the string expect numbers, point and comma
// replace comma with points (parseFloat works only with points)
let stringVal = String(inputValue)
.replace(/([^0-9.,])/g, '')
.replace(/,/g, '.');


// remove all but first point
const pointIndex = stringVal.indexOf('.');
if (pointIndex !== -1) {
const pointAndBefore = stringVal.substring(0, pointIndex + 1);
const afterPoint = stringVal.substring(pointIndex + 1);


// removing all points after the first
stringVal = `${pointAndBefore}${afterPoint.replace(/\./g, '')}`;
}


const float = parseFloat(stringVal);
if (isNaN(float)) {
// fallback to emptying the input if anything goes south
setInputValue('');
return;
}
setInputValue(stringVal);
}

Prevent typing non-Alphabet in specific input id for pages that have more than one input item.it's usable for Oracle Apex developers --- Append in HTML header of page

<script type="text/javascript">
function validateNumber(event) {
const activeElmnt = document.activeElement;
var keyCode = event.keyCode;
var excludedKeys = [8, 37, 39, 46];
 

if ( activeElmnt.id == "input id in HTML page"){
if (!((keyCode >= 65 && keyCode <= 90) ||
(keyCode >= 97 && keyCode <= 122) ||
(excludedKeys.includes(keyCode)))) {
console.log("alphabets are not allowed");
event.preventDefault();


}
}
console.log("keycode: " + keyCode + "ActiveElemet: "+activeElmnt.id);
}
</script>

-- Append in page HTML Body attribute onkeydown="validateNumber(event);"

A very nice react solution... You just want to consume the event if its NaN

    onKeyedPress = (e) => {
if(!parseInt(e.key)){
e.preventDefault();
}
}

try this one :

  1. current key pressed -> e
  2. if e is not a number -> isNaN(e.key)
  3. when condition is true , so default action should not be taken as it normally would be -> e.preventDefault()
  4. else, return default action... e
input.addEventListener("keypress", function (e) {
if (isNaN(e.key)) e.preventDefault();
});

here is my simple solution simply in this solution u should keep the input type to text so when you use event.target.value you get the full string not only the numbers or an empty string instead so you actually can check if there is a point yet or not. and i didn't use the deprecated properties event.which

isNumber(event) {
var allowed = "";
if (event.target.value.includes(".")) {
allowed = "123456789";
} else {
allowed = "123456789.";
}
if (!allowed.includes(event.key)) {
event.preventDefault();
}
}


document.getElementById('number').addEventListener('keypress', isNumber);


the HTML


```

 function isNumber(event) {
var allowed = "";
if (event.target.value.includes(".")) {
allowed = "0123456789";
} else {
allowed = "0123456789.";
}
if (!allowed.includes(event.key)) {
event.preventDefault();
}
}
      

document.getElementById('number').addEventListener('keypress',isNumber);
<h3>You can input only numbers and one point (this would be a float or int) </h3>
<input type="text" id="number" />

This one should work. Only works with integers.

function validateNumberInput(e) {
if (isNaN(e.key)) {
e.preventDefault();
}
}

You can however implement floats with few more lines:

function validateNumberInput(e) {
if (isNaN(e.key) && e.key !== '.') {
e.preventDefault();
} else if (e.key === '.') {
if (e.target.value.indexOf('.') >= 0) {
e.preventDefault();
}
}
}

Finally use it like:

targetInput.addEventListener('keypress', function (e) {
validateNumberInput(e);
});