I have an HTML input element for positive integer numbers. I need to evaluate this input field and ensure that only proper values are inserted.
function exampleFunction(event, element) {
// If event is not backspace and Not a Number
if (event.which != 8) {
//If the event is Not a Number
if (isNaN(String.fromCharCode(event.which))) {
// Cancels the event
event.preventDefault();
}
//If the length reached the limit
else {
var value = document.getElementById(element.id).value;
var maxLength = document.getElementById(element.id).maxLength;
var valueLength = document.getElementById(element.id).value.length;
if (valueLength >= maxLength) {
// Cancels the event
event.preventDefault();
} else {
// Convert the value to a number and back to string. This means leading 0 will be gone.
document.getElementById(element.id).value = Number(value);
}
}
}
};
<input id="exampleInput" type="number" value="0" min="0" step="1" maxlength="5" onkeypress="exampleFunction(event, this)">
purposes:
default value is 0
only numbers shall be accepted
no decimal value .,
no other characters +-e
the input can come from:
typing
copy
backspace and delete can also modify the value
length of input shall also be limited for 5 character length
leading 0 shall be eliminated after a proper new value
Problems:
the default value is 0 and leading zeros are not immediately deleted, only after the second number is typed
with ctrl+v .,+-e characters can be inserted
Question:
Is any better solution for my purposes?
If it is jQuery related, it is also acceptable.
Maybe I am not using the proper event. I tried also to handle the
input event but it is not possible to evaluate the input text.
I am not sure if I make this too complicated, or the solution would be much more complex than I think.
I suggest you to use .addEventListener() instead of the inline event handler.
So to the same input element, you can add more than one event. To do what you wish to do, there are three events implied:
keydown to prevent the not allowed keys
contextmenu for mouse pasting
input to parseInt the value
The below snippet is restricting the input to nubers only. No dot, minus sign, e or whatever except numbers are allowed.
Pasting can be done via [CTRL]+[v] or the mouse contextmenu. In both cases, I assume the previous value of the input should be squarely cleared.
I took the pasted negative numbers case in account using Math.abs().
// Get the element
let myInput = document.querySelector("#exampleInput")
// This event handler only allows numbers, backspace and [ctrl]+[v]
myInput.addEventListener("keydown", function(event) {
console.log("Key:", event.key)
// If this is to be a keyboard paste [CTRL]+[v],
// squarely clears the input value before the paste is done
if (event.ctrlKey && event.key === "v") {
console.log("keyboard paste")
this.value = ""
return;
}
// If the key is not backspace, but is NAN, it is not a number.
// In short, only a number OR a backspace is allowed at this point.
if (event.key !== "Backspace" && isNaN(event.key)) {
event.preventDefault();
console.log(" --------- Event prevented")
}
});
// This handler is for "mouse pastes"
// It squarely clears the input value before the paste is done
myInput.addEventListener("contextmenu", function(event) {
this.value = ""
})
// This handler fixes the value length and parses as a positive integer
myInput.addEventListener("input", function(event) {
console.log("Original value", this.value)
// Get the maxlength attribute value
var maxLength = parseInt(this.maxLength)
// ParseInt the value (will remove any leading zero) and ensure it is positive
// Then keep just the [maxlength] first characters.
var value = Math.abs(parseInt(this.value)).toString().slice(0, maxLength)
console.log("Fixed value", value)
this.value = value;
});
<input id="exampleInput" type="number" value="0" min="0" step="1" maxlength="5">
Here we go with a JQuery solution
Features:
Remove default "0" on focus.
Set maximum length to (5)
Allowed numeric content only and Backspace, Del, Home, End, Arrow-Left, Arrow-Right,
ctrl+v, ctrl+c, ctrl+a buttons.
Check if the copied text contains any numeric value and collect it and remove non-numeric values.
Check if pasted text length + current value length are meeting maximum length
$(document).ready(function() {
//Remove default "0" ONLY! when focus at the input.
$("#exampleInput").on('focus', function() {
var oldval = $("#exampleInput").val();
if (oldval < 1) {
$("#exampleInput").val("");
}
});
/* SET CTRL+V , CTRL+C funciton */
var ctrlprs = false,
ctrlk = 17,
mccmd = 91,
vk = 86,
ak = 65,
ck = 67;
$(document).keydown(function(e) {
if (e.keyCode == ctrlk || e.keyCode == mccmd) ctrlprs = true;
}).keyup(function(e) {
if (e.keyCode == ctrlk || e.keyCode == mccmd) ctrlprs = false;
});
//Listen to the input in keydown
$("#exampleInput").on('keydown', function(e) {
var txt = $("#exampleInput").val();
//exceptions for [b-space,end,home,left,right,del]
var keys = [8, 35, 36, 37, 39, 46];
var rgx = $.inArray(e.which, keys) < 0;
var cnvrt = String.fromCharCode(e.which);
/* allow CTRL + "a or c or v" */
if (ctrlprs && ((e.keyCode == ck) || (e.keyCode == ak) || (e.keyCode == vk))) {
} else if ((txt.length == 5) || (cnvrt.match(/[^0-9]/)) || (e.shiftKey)) {
if ((rgx)) {
e.preventDefault();
/* prevent all text except numbers, and set max input value length to (5) */
}
}
});
/*Bind a paste function to check if clipboard data met with requirements or not.*/
$("#exampleInput").on('paste', function(e) {
var oldl = $("#exampleInput").val();
var oldval = e.originalEvent.clipboardData.getData('text');
if (oldval.match(/[0-9]{1,5}$\d/g)) {} else {
//remove all non-numeric text from clipboard text.
var newvar = oldval.replace(/\D/g, "");
setTimeout(function() {
//check if ( clipboard[Numeric only] + input value ) length equals or less than (5).
var totlen = oldl.length + newvar.length;
if (newvar.length > 0 && totlen <= 5) {
$("#exampleInput").val(oldl + newvar);
} else {
//if total length is more than (5) keep the input value before paste.
console.log("total length is : " totlen);
$("#exampleInput").val(oldl);
}
}, 1);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="exampleInput" type="number" value="0" min="0" step="1" maxlength="5">
Related
I would like to disallow the user to type comma or dot while typing in the input field of the type number.
I have already searched and found solution, but it does not work.
If I type e.g. point, no matter which of the two solutions below, the input field is cleared.
This is my input field
<input type="number" class="form-control numbersOnly" name="angebot" id="angebot" min="1" step="1" placeholder="<?php the_field('language_shop_detail_button_counter_offer_placeholder', 'option'); ?>">
Those are the 2 approaches that don't work.
jQuery('.numbersOnly').keyup(function () {
this.value = this.value.replace(/[^0-9\.]/g,'');
});
and
$('.angebotAbgebenContainer #angebot').keyup(function(event) {
var current = $(".angebotAbgebenContainer #angebot").val();
console.log("current", current);
var replaced = current.replace(/\./g, "");
console.log("replaced", replaced);
//replaced = parseInt(replaced);
// $('.angebotAbgebenContainer #angebot').val(replaced);
});
Those are the 2 approaches that don't work. As soon as I make a point, in both approaches, the input field is cleared.
But what I want is, if someone tries to type a point or a comma, it doesn't appear and if someone copy pastes a number, the comma and point must also be gone.
This works for me
Note it is type text
$('#angebot').on("input",function(event) {
var current = $(this).val();
console.log("current", current);
var replaced = current.replace(/[\D\.,]/g, "");
console.log("replaced", replaced);
$(this).val(replaced);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<input type="text" id="angebot" />
If you are going to input numeric values in the input only, might as well disable the inputting of all keys except numeric, like:
$(document).on("keypress keyup blur", ".numbersOnly", function (event) {
$(this).val($(this).val().replace(/[^\d].+/, ""));
if ((event.which < 48 || event.which > 57)) {
event.preventDefault();
}
});
Where 48 - 57 represents keycodes, you can find all keycodes here.
Can use prevent default as below, and on change for paste
$(function() {
$('#angebot').on('keydown', function(e) {
if (e.keyCode == 188 || e.keyCode == 110) { // 188 for comma, 110 for point
e.preventDefault();
}
}).on('change', function() {
var self = $(this);
self.html( self.html().replace(new RegExp(',', 'g'),'') ); // Remove all commas.
self.html( self.html().replace(new RegExp('.', 'g'),'') ); // Remove all points
});
})
I am using a JS solution to allow letters and backspace only.
I want to add more options to the input, but can't see to find the right solution.
My Code:
<input id="inputTextBox">
$(document).ready(function(){
$("#inputTextBox").keypress(function(event){
var inputValue = event.which;
if(!(inputValue >= 65 && inputValue <= 123) && (inputValue != 32 && inputValue != 0)) {
event.preventDefault();
}
console.log(inputValue);
});
});
This give me the correct result of only letter input and use of backspace.
For the correct user experiece I need to add the following.
Allow input '?' , '*' and 'spacebar'.
And if possible, change the input in the form when the user typ.
So if a user typ a '?' or 'spacebar', it changes into the value '*' automatic.
Thanks in advance.
Slightly modified from this solution:
How to allow only numeric (0-9) in HTML inputbox using jQuery?
EDIT: added code to preserve position when ? and spaces are replaced
// Restricts input for the set of matched elements to the given inputFilter function.
// Modified to pass element to callback function
(function($) {
$.fn.inputFilter = function(inputFilter) {
return this.on("input keydown keyup mousedown mouseup select contextmenu drop", function() {
if (inputFilter(this)) {
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
} else if (this.hasOwnProperty("oldValue")) {
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
} else {
this.value = "";
}
});
};
}(jQuery));
$(document).ready(function(event) {
$("#inputTextBox").inputFilter(function(el) {
var oldSelectionStart = el.selectionStart;
var oldSelectionEnd = el.selectionEnd;
var oldValue = el.value;
el.value = el.value.replace(/[* ]/g, '?'); //replace * space with ?
el.value = el.value.replace(/[^a-zA-Z?]/g, '');
if (oldValue != el.value)
el.setSelectionRange(oldSelectionStart-(oldValue.length-el.value.length), oldSelectionEnd-(oldValue.length-el.value.length));
return /^[a-zA-Z?]+?$/.test(el.value); // alphabet question only
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="inputTextBox">
Simply added a keyup function to replace the character '?' and space to *
and also added envent ids of space and '?' in your keypress function.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="inputTextBox">
<script>
$(document).ready(function(){
$("#inputTextBox").keypress(function(event){
var inputValue = event.which;
if(!(inputValue >= 65 && inputValue <= 123) && (inputValue != 32 && inputValue != 0 && inputValue != 63 && inputValue != 42 && inputValue != 32)) {
event.preventDefault();
}
});
$("#inputTextBox").keyup(function(){
var inputTxt = $('#inputTextBox').val();
inputTxt = inputTxt.replace('?', '*').replace(' ', '*')
$('#inputTextBox').val(inputTxt);
});
});
</script>
You have an issue with your code already since the 65 - 123 contains letters, but it also contains [] _ to name a few.
so you probably want 65-90 for A-Z then 97-122 for a-z 48-57 for 0-9. then check each character you want to allow, they probably wont be in a range.
If you look at the ascii chart here https://theasciicode.com.ar/ascii-printable-characters/question-mark-ascii-code-63.html you will see all the numbers you need to include (or exclude)
On the keyUp event, you could look at the value and then change the last character to the * if you wish, but remember that will change the actual value, not just mask it.
If you want it masked, you should use an <input type="password"> field, which has that behaviour by default.
I am using Vue.JS (Bootstrap-Vue) to build a form, my input has the following code:
<b-form-input
v-mask="'####'"
number
type="number"
no-wheel
pattern="[0-9]"
step="1"
:class="{ 'hasError': $v.form.dobYear.$error }"
v-model.number="$v.form.dobYear.$model"
class="form-input"
name="year"
id="year"
maxlength="4"
min="1900"
max="2020"
#keydown="filterKey"
></b-form-input>
When a user presses down I want to prevent more than 4 characters to be entered, this works, but when testing, I can see period and dashes and other similar characters can also be added into the input and ignores the maximum of 4 characters. How can I update the following code to ensure nothing but numbers can be added to my input on mobile. I'm trying to detect if any of those unwanted keys are pressed then prevent the default action. (I've tested on Android Chrome)
filterKey(e) {
const value = e.target.value;
const key = e.key;
console.log(value, this.amount);
if (String(value).length === 4) {
//check if a number is pressed after 4 have been entered
if (!isNaN(Number(key))) {
e.preventDefault();
return;
} else if (key == 190 || key == 189 || key == 107 || key == 69) {
e.preventDefault();
return;
}
}
}
The following snippet will not allow anything to be entered into the input element if the length of the input's value is already 4, or if a non-numeric character is typed (but will allow 'Backspace' and 'Delete' keys):
EDIT : Implemented Hiws' suggestion to let the user type in numbers even if the length is 4, if some text is selected in the input element
function filterKey(e) {
let previousValue = e.target.value;
let key = e.keyCode || e.charCode;
if (key != 8 && key != 46) { // Ignore backspace and delete
if (
// preventDefault if length of input is 4 and no text is selected in the input
( String(e.target.value).length >= 4 && e.target.selectionStart === e.target.selectionEnd ) ||
// preventDefault if entered a space or non-number
!e.key.trim() || isNaN(e.key)
) {
// Prevent input if input length crosses 4,
// or if input is not a number
e.preventDefault();
// Include below line only if you have no other event listeners on the element, or its parents
e.stopImmediatePropagation();
return;
}
}
}
You block keys other than numbers only if number value already equals to 4. Try changing your blocking logic to:
if (String(value).length > 4 || !isNaN(Number(key)) || unwanted keyCodes) {
e.preventDefault();
return;
You can use a regex to test against the value of the input field and avoid messing with keyCodes.
if ( !/^[0-9]{0,4}$/.test(String(value)) ) {
e.preventDefault();
return;
}
I have a calculator I'm working on and came across a problem. To combat so that users can't leave a field blank, I'm forcing a zero if the field is left empty. That's all fine, but the problem is that when the text in the field is deleted to remove the zero and enter a new number, it automatically enters zero so my new number looks like this: 05
How do i run a replace where if there is more than 2 places in the number and the first number is zero, replace the zero? Here's the code i'm using for my calculator.
$(function(){
calculate();
$('.input').keypress(function (e) {
//if the letter is not digit then display error and don't type anything
if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
return false;
}
});
$('.input').on('keyup',function(){
if($(this).val()==''){
$(this).val('0');
}
calculate();
});
});
function calculate(){
var d6 = parseFloat(($('#d6').val()).replace(/,/g,''));
var d20 = parseFloat(($('#d20').val()).replace(/,/g,''));
var b20 = d6;
var e20 = parseFloat(($('#e20').val()).replace(/,/g,''));
var f20 = d20*e20;
var f22 = b20/f20;
var f23 = (52-f22)*f20;
$('#f20').html(formatCurrency(f20));
$('#f22').html(f22.toFixed(2));
$('#f23').html(formatCurrency(f23));
}
function formatCurrency(x) {
return '$'+x.toString().replace(/\B(?=(?:\d{3})+(?!\d))/g, ",");
}
If you are essentially trying to turn it into a formatted number you could try type coercion:
'' + new Number('') // "0"
'' + new Number('0') // "0"
'' + new Number('05') // "5"
'' + new Number('0000.2') // "0.2"
Change the zeroing code to use the blur() event, i.e when the field loses focus.
$('.input').blur(function(){
if($(this).val()=='')
{
$(this).val('0');
}
});
I'm assuming that the text is removed from pressing the backspace key.
If that is the case then you keyup handler would fire when you backspace on the zero, which would detect no input, then add the zero.
First of all, you are doing it a hard way. And try this... if the user clicks on the input then it will be cleared and the user can write whatever number he wants...
$( ".input" ).focus(function() {
(this).val('');
});
In case you are using an HTML5 form you can avoid that piece of code like this:
<input type="number" placeholder="Type a number" required>
The required attribute is a boolean attribute.
When present, it specifies that an input field must be filled out.
Instead of using keyup and keypress event for checking and replacing blank to zero, use change event.
$(function(){
calculate();
$('.input').keypress(function (e) {
//if the letter is not digit then display error and don't type anything
if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
return false;
}
});
$('.input').on('keyup',function(){
calculate();
});
$('.input').on('change',function(){
if($(this).val()==''){
$(this).val('0');
}
});
});
function calculate(){
var d6Val = ($('#d6').val() !== "")? $('#d6').val() : '0';
var d20Val = ($('#d20').val() !== "")? $('#d20').val() : '0';
var e20Val = ($('#e20').val() !== "")? $('#e20').val() : '0';
var d6 = parseFloat((d6Val).replace(/,/g,''));
var d20 = parseFloat((d20Val).replace(/,/g,''));
var b20 = d6;
var e20 = parseFloat((e20Val).replace(/,/g,''));
var f20 = d20*e20;
var f22 = b20/f20;
var f23 = (52-f22)*f20;
$('#f20').html(formatCurrency(f20));
$('#f22').html(f22.toFixed(2));
$('#f23').html(formatCurrency(f23));
}
function formatCurrency(x) {
return '$'+x.toString().replace(/\B(?=(?:\d{3})+(?!\d))/g, ",");
}
One more thing. Change event only fires when you focus-out from that input.
Please let me know if you will face any issue.
Is there a way to block users from writing specific characters in input fields? I tried the code below, but when a user enters disallowed characters, they appear for a brief period before disappearing. I want the input to remain unchanged when invalid characters are written.
I want to use onchange because other restriction methods do not seem to work on mobile devices. The problem I want to solve is that characters appear briefly before being removed.
function checkInput(ob) {
const invalidChars = /[^0-9]/gi;
if(invalidChars.test(ob.value)) {
ob.value = ob.value.replace(invalidChars, "");
}
};
<input class="input" maxlength="1" onChange="checkInput(this)" onKeyup="checkInput(this)" type="text" autocomplete="off" />
you can use try this,
$('.input').keyup(function () {
if (!this.value.match(/[0-9]/)) {
this.value = this.value.replace(/[^0-9]/g, '');
}
});
SEE THIS FIDDLE DEMO
Updated :
You can try this Code,
$(document).ready(function() {
$(".input").keydown(function (e) {
// Allow: backspace, delete, tab, escape and enter
if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110]) !== -1 ||
// Allow: Ctrl+A
(e.keyCode == 65 && e.ctrlKey === true) ||
// Allow: home, end, left, right
(e.keyCode >= 35 && e.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
});
});
SOURCE
SEE UPDATED FIDDLE DEMO
UPDATED FOR ANDROID:
<EditText
android:id="#+id/editText1"
android:inputType="number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_marginTop="58dp"
android:layout_toRightOf="#+id/textView1"
android:maxLength="1" >
</EditText>
I think it may help you... using android:inputType="number" you can do that.
A combination of keypress and paste events does a trick:
var text = document.getElementById('text');
text.onkeypress = text.onpaste = checkInput;
function checkInput(e) {
var e = e || event;
var char = e.type == 'keypress'
? String.fromCharCode(e.keyCode || e.which)
: (e.clipboardData || window.clipboardData).getData('Text');
if (/[^\d]/gi.test(char)) {
return false;
}
}
<input class="input" maxlength="10" id="text" type="text" autocomplete="off" />
This code prevents from typing or pasting anything but a number. Also no blinking and invalid characters don't show up.
Works in IE7+.
Demo: http://jsfiddle.net/VgtTc/3/
All answers given so far suffer from at least one of the following accessibility issues:
They validate key codes, which does not work with non-QWERTY keyboard layouts.
They do not cover all input methods; especially drag&drop is often forgotten.
They alter the value, which resets the position of the caret.
They use the pattern attribute, but this does not provide feedback until the form is submitted.
Wouldn't it be a much better idea to actually validate the input before it's inserted?
The beforeinput event fires before the input's value is changed. The event has a data property which describes the content that the user wants to add to the input field. In the event handler, you simply check the data attribute, and stop the event chain if it contains disallowed characters.
We end up with the following very simple, very short code.
const input = document.getElementById("input");
const regex = new RegExp("^[0-9]*$");
input.addEventListener("beforeinput", (event) => {
if (event.data != null && !regex.test(event.data))
event.preventDefault();
});
<label for="input">Enter some digits:</label>
<input id="input" />
Some closing notes:
Accessibility: Provide a clear explanation of what input format is expected from the user. For example, you can use the title attribute of the input to show a tooltip explaining the expected format.
Security: This is client-side validation, and does not guarantee that the pattern is enforced when the form is sent to a server. For that, you'll need server-side validation.
Here's a little hack you could try: DEMO
What it does is that it colors every input text white and then changes it back to black if it suits your requirements. If you could live with the bit of lag that occurs when you enter a valid character.
function checkInput(ob) {
var invalidChars = /[^0-9]/gi
if (invalidChars.test(ob.value)) {
ob.value = ob.value.replace(invalidChars, "");
}
else {
document.getElementById('yourinput').style.color = '#000';
}
};
function hideInput(ob) {
document.getElementById('yourinput').style.color = '#FFF';
};
html
<input id="yourinput" class="input" maxlength="1" onKeydown="hideInput(this)" onKeyup="checkInput(this)" type="text" autocomplete="off" />
css
input {color:#FFF;}
check this code,
$('.input').keypress(function(e) {
var a = [];
var k = e.which;
for (i = 48; i < 58; i++)
a.push(i);
if (!(a.indexOf(k)>=0))
e.preventDefault();
});
<input id="testInput"></input>
<script>
testInput.onchange = testInput.oninput = restrict;
function restrict() {
testInput.value = testInput.value.replace(/[^a-z]/g, "");
}
</script>
I came up with something slightly different. oninput instead of onkeyup/onkeydown, and onchange instead of onpaste.
I restrict invalid characters on both keypress and paste events like:
<input type="text" onkeydown="validateKey(event)" onpaste="validatePaste(this, event)">
And define functions to handle these events inside tab or a separate javascript file:
<script>
function validateKey(e) {
switch(e.keyCode) {
case 8,9,13,37,39:
break;
default:
var regex = /[a-z .'-]/gi;
var key = e.key;
if(!regex.test(key)) {
e.preventDefault();
return false;
}
break;
}
}
function validatePaste(el, e) {
var regex = /^[a-z .'-]+$/gi;
var key = e.clipboardData.getData('text')
if (!regex.test(key)) {
e.preventDefault();
return false;
}
}
</script>