// Restricts input for the given textbox to the given inputFilter function.function setInputFilter(textbox, inputFilter, errMsg) {[ "input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {textbox.addEventListener(event, function(e) {if (inputFilter(this.value)) {// Accepted value.if ([ "keydown", "mousedown", "focusout" ].indexOf(e.type) >= 0){this.classList.remove("input-error");this.setCustomValidity("");}
this.oldValue = this.value;this.oldSelectionStart = this.selectionStart;this.oldSelectionEnd = this.selectionEnd;}else if (this.hasOwnProperty("oldValue")) {// Rejected value: restore the previous one.this.classList.add("input-error");this.setCustomValidity(errMsg);this.reportValidity();this.value = this.oldValue;this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);}else {// Rejected value: nothing to restore.this.value = "";}});});}
您现在可以使用setInputFilter函数安装输入过滤器:
setInputFilter(document.getElementById("myTextBox"), function(value) {return /^\d*\.?\d*$/.test(value); // Allow digits and '.' only, using a RegExp.}, "Only digits and '.' are allowed");
// Restricts input for the given textbox to the given inputFilter.function setInputFilter(textbox, inputFilter, errMsg) {[ "input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {textbox.addEventListener(event, function(e) {if (inputFilter(this.value)) {// Accepted value.if ([ "keydown", "mousedown", "focusout" ].indexOf(e.type) >= 0) {this.classList.remove("input-error");this.setCustomValidity("");}
this.oldValue = this.value;this.oldSelectionStart = this.selectionStart;this.oldSelectionEnd = this.selectionEnd;}else if (this.hasOwnProperty("oldValue")) {// Rejected value: restore the previous one.this.classList.add("input-error");this.setCustomValidity(errMsg);this.reportValidity();this.value = this.oldValue;this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);}else {// Rejected value: nothing to restore.this.value = "";}});});}
// Install input filters.setInputFilter(document.getElementById("intTextBox"), function(value) {return /^-?\d*$/.test(value);}, "Must be an integer");setInputFilter(document.getElementById("uintTextBox"), function(value) {return /^\d*$/.test(value);}, "Must be an unsigned integer");setInputFilter(document.getElementById("intLimitTextBox"), function(value) {return /^\d*$/.test(value) && (value === "" || parseInt(value) <= 500);}, "Must be between 0 and 500");setInputFilter(document.getElementById("floatTextBox"), function(value) {return /^-?\d*[.,]?\d*$/.test(value);}, "Must be a floating (real) number");setInputFilter(document.getElementById("currencyTextBox"), function(value) {return /^-?\d*[.,]?\d{0,2}$/.test(value);}, "Must be a currency value");setInputFilter(document.getElementById("latinTextBox"), function(value) {return /^[a-z]*$/i.test(value);}, "Must use alphabetic latin characters");setInputFilter(document.getElementById("hexTextBox"), function(value) {return /^[0-9a-f]*$/i.test(value);}, "Must use hexadecimal characters");
.input-error {outline: 1px solid red;}
<h2>JavaScript input filter showcase</h2><p>Supports Copy+Paste, Drag+Drop, keyboard shortcuts, context menu operations, non-typeable keys, the caret position, different keyboard layouts, and <a href="https://caniuse.com/#feat=input-event" target="_blank">all browsers since IE 9</a>.</p><p>There is also a <a href="https://jsfiddle.net/emkey08/tvx5e7q3" target="_blank">jQuery version</a> of this.</p><table><tr><td>Integer</td><td><input id="intTextBox"></td></tr><tr><td>Integer >= 0</td><td><input id="uintTextBox"></td></tr><tr><td>Integer >= 0 and <= 500</td><td><input id="intLimitTextBox"></td></tr><tr><td>Float (use . or , as decimal separator)</td><td><input id="floatTextBox"></td></tr><tr><td>Currency (at most two decimal places)</td><td><input id="currencyTextBox"></td></tr><tr><td>A-Z only</td><td><input id="latinTextBox"></td></tr><tr><td>Hexadecimal</td><td><input id="hexTextBox"></td></tr></table>
document.querySelector("form").addEventListener("submit", (event) => {event.preventDefault();console.log(`Submit!Number is ${event.target.elements.number.valueAsNumber},integer is ${event.target.elements.integer.valueAsNumber},form data is ${JSON.stringify(Object.fromEntries(new FormData(event.target).entries()))}.`);})
label {display: block;}
<form><fieldset><legend>Get a feel for the UX here:</legend><label>Enter any number: <input name="number" type="number" step="any" required></label><label>Enter any integer: <input name="integer" type="number" step="1" required></label><label>Submit: <input name="submitter" type="submit"></label></fieldset></form>
var input = document.getElementById('number');input.onkeyup = input.onchange = enforceFloat;
//enforce that only a float can be inputedfunction enforceFloat() {var valid = /^\-?\d+\.\d*$|^\-?[\d]*$/;var number = /\-\d+\.\d*|\-[\d]*|[\d]+\.[\d]*|[\d]+/;if (!valid.test(this.value)) {var n = this.value.match(number);this.value = n ? n[0] : '';}}
<input id="number" value="-3.1415" placeholder="Type a number" autofocus>
EDIT: I removed my old answer because I think it is antiquated now.
function number(e) {var theEvent = e || window.event;var key = theEvent.keyCode || theEvent.which;if(key!=13&&key!=9){//allow enter and tabkey = String.fromCharCode( key );var regex = /[0-9]|\./;if( !regex.test(key)) {theEvent.returnValue = false;if(theEvent.preventDefault) theEvent.preventDefault();}}}
$(document).ready(function(){$("input[type=text]").filter(".number,.NUMBER").on({"focus":function(e){$(e.target).data('oldValue',$(e.target).val());},"keypress":function(e){e.target.oldvalue = e.target.value;number(e);},"change":function(e){var t = e.target;var min = $(t).attr("min");var max = $(t).attr("max");var val = parseInt($(t).val(),10);if( val<min || max<val){alert("Error!");$(t).val($(t).data('oldValue'));}
}});});
如果输入是动态的,请使用:
$(document).ready(function(){$("body").on("focus","input[type=text].number,.NUMBER",function(e){$(e.target).data('oldValue',$(e.target).val());});$("body").on("keypress","input[type=text].number,.NUMBER",function(e){e.target.oldvalue = e.target.value;number(e);});$("body").on("change","input[type=text].number,.NUMBER",function(e){var t = e.targetvar min = $(t).attr("min");var max = $(t).attr("max");var val = parseInt($(t).val());if( val<min || max<val){alert("Error!");$(t).val($(t).data('oldValue'));}});});
<input name="amount" type="text" value="Only number in here"/>
<script>$('input[name=amount]').keyup(function(){$(this).val($(this).val().replace(/[^\d]/,''));});</script>
function validateInput() {if (jQuery('#x1').val().toString().match(/^[-]?[0-9]+[\.]?[0-9]*$/) == null ||jQuery('#x2').val().toString().match(/^[-]?[0-9]+[\.]?[0-9]*$/) == null ||jQuery('#y1').val().toString().match(/^[-]?[0-9]+[\.]?[0-9]*$/) == null ||jQuery('#y2').val().toString().match(/^[-]?[0-9]+[\.]?[0-9]*$/) == null) {alert("A number must be entered for each coordinate, even if that number is 0. Please try again.");location.reload();}}
As someone commented below, the solution above does not handle leading zeros. If your particular use case requires that these are not allowed you can add to the pattern above like so:
/*** Base input {@see Element} {@see EventListener} filter abstract class** @implements EventListener*/class AbstractInputFilter {
/*** Attach the input filter to the input {@see Element}** @param inputElement The input {@see Element} to filter* @param isValid - The callback that determines if the input is valid.* @throws Error*/constructor(inputElement, isValid = null) {// Abstract classif (this.constructor === AbstractInputFilter) {throw new Error("Object of Abstract Class cannot be created");}
if (typeof isValid === "function") {this.isValid = isValid;}
for (const event of ["input", "keydown", "keyup","mousedown", "mouseup", "select", "contextmenu", "drop"]) {inputElement.addEventListener(event, this);}}
/*** Checks the value is valid** @callback isValid default call-back that will throw* an {Error} if not implemented by extending this* {AbstractInputFilter} class.** @param value The value to check* @returns {boolean}* @throws Error*/isValid(value) {throw new Error('must be implemented by callback!');}
/*** Handles the {@see event} dispatched by* the {@see EventTarget} object from the input {@see Element}* to filter its contant while it is being filled.** @param event the {@see event} dispatched by* the {@see EventTarget} input {@see Element}* @override*/handleEvent(event) {const inputElement = event.currentTarget;if (this.isValid(inputElement.value)) {inputElement.oldValue = inputElement.value;inputElement.oldSelectionStart = inputElement.selectionStart;inputElement.oldSelectionEnd = inputElement.selectionEnd;} else if (inputElement.hasOwnProperty("oldValue")) {inputElement.value = inputElement.oldValue;inputElement.setSelectionRange(inputElement.oldSelectionStart, inputElement.oldSelectionEnd);} else {this.value = "";}}}
/*** Generic Input element {@see EventListener} filter** @extends AbstractInputFilter* It needs the {@see AbstractInputFilter~isValid} callback* to determine if the input is valid.*/class InputFilter extends AbstractInputFilter {}
/*** Unsigned Integer Input element {@see EventListener} filter* @extends AbstractInputFilter*/class UIntInputFilter extends AbstractInputFilter {isValid(value) {return /^\d*$/.test(value);}}
/*** Unsigned Float Input element {@see EventListener} filter* @extends AbstractInputFilter*/class UFloatInputFilter extends AbstractInputFilter {isValid(value) {return /^\d*\.?\d*$/.test(value);}}
// Filter with pre-made InputFilters (re-use the filter)new UIntInputFilter(document.getElementById("UInt"));new UFloatInputFilter(document.getElementById("UFloat"));
// Filter with custom callback filter anonymous functionnew InputFilter(document.getElementById("AlNum"), function(value) {return /^\w*$/.test(value);});
<label>Unsigned integer: </label><input id="UInt"><br/><label>Unsigned float: </label><input id="UFloat"><br/><label>AlphaNumeric (no special characters): </label><input id="AlNum">