I'm trying to validate a textfield for hex colors only using regex. I stumbled upon this answer, and tried it for my textField, and it doesn't work as I expect it to. Here's the code:
/^[0-9A-F]{6}$/i.test(e.target.value)
It's supposed to check if the textfield is 0 - 9 || A - F (capital or lowercase), but when I log that, it always says false.
How can I validate a hex textfield?
Full Code:
JSFiddle
document.getElementById('hexTextField').addEventListener('keyup', function(e) {
// Allow: tab, home, end, left, up, right, down
if ([9, 36, 35, 37, 38, 39, 40].indexOf(e.keyCode) !== -1 ||
// Allow: Ctrl || Command && a, c, x and v
(!0 === e.ctrlKey || !0 === e.metaKey) && /65|67|88|86/.test(e.keyCode)) {
if (e.keyCode === 86 && /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(e.target.value)) {
//myColor.setColor(e.target.value, 'hex');
}
return;
}
console.log(/^[0-9A-F]{6}$/i.test(e.target.value));
if (/^[0-9A-F]{6}$/i.test(e.target.value)) {
//myColor.setColor(e.target.value, 'hex');
} else {
e.preventDefault();
}
});
<input type="text" id="hexTextField" spellcheck="false" maxlength="6">
Update
There seems to be some confusion of what exactly I'm asking. I'm trying to validate the textField as the user is typing, not when the user finished. I hope this will clarify my question.
What the regex code does is, it checks if the textfield has the 'valid' chars, && if there are 6 chars in the textfield.
So if one would want to validate the textfield as the user types, you would use this regex:
/[0-9A-Fa-f]$/i
Notice, I removed the {6} which comes out to true only if there are 6 chars.
Related
I have a html <input> element that I want to accept only numbers and to be recognised on mobile devices as a number field. I also want invalid characters to be swallowed, just like for standard type=number swallowing disallowed characters.
I've tried the obvious type=number but it has a number of shortcomings. Specifically it allows 'e', '+' and '-' (at least in chrome), but these were easy to fix with some JS. The real problem is with the '.' character, I want to be able to enter floating point numbers e.g. '0.10', '5.5054', but don't want to be able to enter invalid strings like '0.10.1' for instance. I tried to resolve this by allowing only 1 '.' at a time but this failed as the input.value gets massaged by the browser e.g. '5.' becomes '5', '5..' becomes null (!) and it seems impossible to get the raw string value typed in the input. The above means checking for existing '.'s and taking action appears to be a dead end...
Core questions:
Is there a way I missing to inspect and conform the input?
'Is there a way of marking an input as a number without the logistical baggage of type=number?
Note:
* I realise that you can paste whatever you want in, I consider that behaviour pathological and shouldn't be covered by input prevention.
Update
To clarify, I have already tried keypress, keydown etc events and they aren't adequate as I want to see how many '.'s exist in the input currently to choose whether or not to allow another. At this point the input.value has been massaged by the browser to remove '.'s. I want to conditionally allow characters based on the current number of '.'s that have been entered.
Example
HTML (angular style binding for brevity)
<input type="number" (keydown)="keyDown()">
JS
function keyDown($event: KeyboardEvent) {
const inputField = // obtain reference to input element
const value = inputField.value;
if ( value.indexOf('.') !== -1 && $event.key === '.') { // disallow another . if one is present
// ! input field prunes . so this check isn't sufficient
$event.preventDefault();
return;
}
// This is the crux of the problem e.g.
// type 5. into input field, value === 5
// type 5.. into the input field, value === null
// Since the . char is removed by the input element there's no way to know how many are present!
console.log(value);
}
Summary
Is there a way to signal that an <input> is of type number without using the type=number attribute setting.
i.e. mobile devices recognise and display number pad etc
For an <input> that has type=number is there a way to swallow all key input that doesn't result in a valid number
Before the character is added to the input by the browser, no janky deletion on keyup
Is there a way to signal that an <input> is of type number without using the type=number attribute setting.
i.e. mobile devices recognise and display number pad etc
Use inputmode="decimal" instead of type="number" to signal a mobile device to use a number pad keyboard input. This way you can continue to use type="text" and process the input as needed.
See MDN for more info and inputtypes.com to test on a device.
A slightly different approach. It allows digits, only 1 period, and backspace. All the rest of KeyboardEvent.keys including ctrl + v and ctrl + c are ignored. But if wish to allow them, you can do so.
To check if the character is one of the 10 digits, I am using event.key since they can have two different codes: Digits[0-9] and Numpad[0-9]. But for the period and backspace, I am using event.code since they have only one code.
const input = document.querySelector("#number_input");
const App = {
isDigit: function(key) {
const digits = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
];
return digits.includes(key);
},
isPeriod: function(code) {
return code === "Period";
},
isBackSpace: function(code) {
return code === "Backspace";
},
handleEvent: function(event) {
const key = event.key;
const code = event.code;
const value = input.value;
if (App.isDigit(key) || App.isPeriod(code) || App.isBackSpace(code)) {
if (App.isPeriod(code) && value.indexOf(key) !== -1) {
event.preventDefault();
}
} else {
event.preventDefault();
}
}
};
input.onkeydown = App.handleEvent
<input id="number_input" />
A clever hack
Since you insist to use a number input. First use, a dummy text input which you can hide it using either CSS or Js and validate its value instead of the number input.
const input = document.querySelector("#number_input");
const dummyInput = document.querySelector("#dummy_input")
const App = {
isDigit: function(key) {
const digits = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
];
return digits.includes(key);
},
isPeriod: function(code) {
return code === "Period";
},
isBackSpace: function(code) {
return code === "Backspace";
},
handleEvent: function(event) {
const key = event.key;
const code = event.code;
const dummyValue = dummyInput.value;
if (App.isBackSpace(code)) {
dummyInput.value = dummyValue.substring(0, dummyValue.length - 1)
} else {
if (App.isDigit(key) || App.isPeriod(code)) {
if (App.isPeriod(code) && dummyValue.indexOf(key) !== -1) {
event.preventDefault();
} else {
dummyInput.value += event.key
}
} else {
event.preventDefault();
}
}
}
};
input.onkeydown = App.handleEvent
<input type="number" id="number_input" />
<input type="text" id="dummy_input" />
Update
All of the answers that use input[type="number"] have a problem. You can change the input's value to a negative number by mouse wheel/spinner. To fix the issue, set a minimum value for the input.
<input type="number" min="1" id="number_input" />
You need to listen for onchange events and then change value of the dummy input.
const input = document.querySelector("#number_input");
const dummyInput = document.querySelector("#dummy_input")
const App = {
isDigit: function(key) {
const digits = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
];
return digits.includes(key);
},
isPeriod: function(code) {
return code === "Period";
},
isBackSpace: function(code) {
return code === "Backspace";
},
handleEvent: function(event) {
const key = event.key;
const code = event.code;
const dummyValue = dummyInput.value;
if (App.isBackSpace(code)) {
dummyInput.value = dummyValue.substring(0, dummyValue.length - 1)
} else {
if (App.isDigit(key) || App.isPeriod(code)) {
if (App.isPeriod(code) && dummyValue.indexOf(key) !== -1) {
event.preventDefault();
} else {
dummyInput.value += event.key
}
} else {
event.preventDefault();
}
}
},
handleChange: function(event) {
dummyInput.value = event.target.value
}
};
input.onkeydown = App.handleEvent;
input.onchange = App.handleChange;
<input type="number" min="1" id="number_input" />
<input type="text" id="dummy_input" />
trigger special function for onkeypress and check if your allowed character are typed or not. If not - prevent the default behavior.
let special = document.getElementById('special_input');
special.addEventListener("keypress", function(e) {
let dot = 46;
// allowed char: 0-9, .
let allow_char = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, dot];
if (allow_char.indexOf(e.which) !== -1) {
// only 1 dot
if (e.which == 46 && special.value.indexOf('.') !== -1)
e.preventDefault();
} else {
e.preventDefault();
}
});
<input id='special_input'>
updated
The answer is updated as per requirement changes.
okay I try to fix one more problem and that is paste
according to following code you can not paste anything, you can only paste numbers, if you try to paste string, the input box will become empty automatically :)
let special = document.getElementById('inputField');
special.addEventListener("keypress", function(e) {
let dot = 46;
// allowed char: 0-9, .
let allow_char = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, dot];
if (allow_char.indexOf(e.which) !== -1) {
// only 1 dot
if (e.which == 46 && special.value.indexOf('.') !== -1)
e.preventDefault();
} else {
e.preventDefault();
}
});
function checkString()
{
setTimeout(() => {
var value = document.getElementById("inputField").value;
value = parseInt(value);
if(isNaN(value))
document.getElementById("inputField").value = "";
}, 100);
}
<input type="number" id="inputField" onpaste="checkString()"/>
Check truthy with
value == parseFloat(value)
parseFloat() will capture the first decimal point and remove any additional ones.
Using '==' instead of '===' will make sure the reference value isn't changed.
function keyDown($event: KeyboardEvent) {
const inputField = // obtain reference to input element
const value = inputField.value;
if ( value == parseFloat(value)) { // disallow another . if one is present
// ! input field prunes . so this check isn't sufficient
$event.preventDefault();
return;
}
// This is the crux of the problem e.g.
// type 5. into input field, value === 5
// type 5.. into the input field, value === null
// Since the . char is removed by the input element there's no way to know how many are present!
console.log(value);
}
Here is a similar test you can run in node.js to verify it accomplishes what you are going for.
function numCheck (value) {
if (value == parseFloat(value)) {
console.log(value)
} else {
console.log('not a number')
}
}
numCheck("5");
numCheck("5.5");
numCheck("5.5.5");
numCheck("A");
For restrictions, Regex is best way to go. Register event listener on keypress
numbersOnly(event) {
const numbers = /^([0-9])$/;
const result = numbers.test(event.key);
return result;
}
Above function will swallow charset, if it doesn't match regex
Javascript Regex: validating a double/float
Above link has regex, who allows double/float. Hope it helps :)
This may be what your looking for:
This input eats all caracters exept for numbers and "."
let prev = "";
function keyUp(event) {
if ((!event.target.value && event.keyCode !== 8) || event.target.value.indexOf('e') !== -1 || parseFloat(event.target.value) == NaN) {
event.target.value = prev;
} else {
prev = event.target.value;
}
}
<input type="number" onkeyup="keyUp(event)">
Perhaps an indirect solution to your problem. You can look into validity property to determine if the input is valid.
You can check the validity without the need to access the value, which may not be returned in case of invalid input.
HTML:
<input type="number" id="num" step="0.1"/>
JS:
var numField = document.getElementById('num');
numField.addEventListener("keyup", event => {
if(!numField.validity.valid)
{
alert('invalid input');
}
});
Some tests:
34 -> valid
3.4 -> valid
e -> invalid
+4 -> valid
3.4. -> invalid
3.4.. -> invalid
.4 -> valid (evaluates to 0.4)
3e+2 -> valid
1e -> invalid
eee -> invalid
-0.3e+1 -> valid
..32e.. -> invalid
This works both with pasting and inputting the values.
UPDATE:
The original question is a bit verbose. I am trying to break it down and answer part by part.
Input[type="number"] allows access to the value only if it is valid and returns empty otherwise. Thus, you can know if value is correct or not, however you cannot get the invalid value.
You could get around this by pushing individual keypresses into a buffer. However, maintaining sync between the buffer and actual value is challenging due to copy/paste, input field swallowing certain keys, moving the cursor around and inserting keys, etc. Implementing reliable cross-platform support for all of this seems like overkill. A better approach would be to implement other means to input the number, e.g. a slider. This resource covers the basics of designing number inputs
So, you are left with knowing if the current input is valid and the last key pressed. The problem is that certain invalid inputs, e.g. "4." may lead to a valid input "4.1". Thus, just swallowing the last key in case the input turns invalid is out of the question.
You could implement a rule that if invalid input is not turned into a valid one within 2 keystrokes (or 1 second) the input returns to last valid state swallowing the invalid input. However, I would argue that this creates UX problems because users may not be used to such behavior and it opens doors for users submitting technically valid, yet unwanted values.
Core questions:
Is there a way I missing to inspect and conform the input?
Is there a way of marking an input as a number without the logistical baggage of type=number?
Apparently not.
Yes, there is by rethinking the way how you enter numeric values.
Regular Expression: /^[1-9][0-9]*$/
The regexp works as intended on http://www.phpliveregex.com
My problem is that it doesn't work when implemented with JS, see my code on http://jsfiddle.net/LHHU7
The JS:
$("#mytextbox").on("keypress", function(event) {
var re = /^[1-9][0-9]*$/;
var key = doKey(arguments[0] || window.event);
var char = String.fromCharCode(key);
if (key == 8 || key == 37 || key == 39 || re.test(char)) {
return true;
}
return false;
});
$('#mytextbox').on("paste",function(e)
{
e.preventDefault();
});
function doKey(event) {
var key = event.keyCode | event.charCode;
return key;
}
Test cases expected:
0001 fail
11 11 fail
1000 success
1264 success
5001 success
What's happening with my code:
0001 fail WORKING
11 11 fail WORKING
1000 success NOT WORKING
1264 success WORKING
5001 success NOT WORKING
For some reason 0 won't be entered. I've already tried on chrome, with no success. I've tried changing my RegExp multiple times with no different results. I've also tried different implementations on my code, but still no success.
Please see if you can get it working on my jsfiddle before posting your answers. Thanks!
You're only checking a single character (the latest one) against the regex, when you probably really want to match the content of the textbox + the character. This makes it impossible to enter a zero at all, since it will always be matched against ^[1-9].
Matching the existing textbox value + the character should work better;
if (key == 8 || key == 37 || key == 39 ||
re.test(document.getElementById("mytextbox").value + char)) {
return true;
}
As #Joachim Isaksson mentioned, you are only looking at the last character so your regex is wrong. Update regex to:
var re = /^[0-9]$/;
This will match one number, 0-9.
Edit the Following to your code it works fine DEMO
var testString=$('#mytextbox').val();
if (key == 8 || key == 37 || key == 39 || re.test(testString + char) )
I have an input field which I only want positive and negative integers to be allowed in. I track their typing with onkeyup() since that's the most consistent across browsers. The real issue comes in when trying to replace non-numeric characters without replacing the dash at the start.
if(e.keyCode < 48 || e.keyCode > 57) {
var data = e.target.value;
if(e.target.value.match(/^[-]?/))
e.target.value = '-' + data.substr(1).replace(/\D*/, "");
else
e.target.value = data.replace(/\D*/,"");
}
Basically what's happening here is I ignore when they type in numbers, but for everything else attempt to replace anything they may have added that isn't a number. The issue with this right now is when I press Backspace, the dash comes back right away for some reason.
E.g. My input field has this: - When I press backspace. My input field stays as this: -
WORKING CODE:
if(e.keyCode < 48 || e.keyCode > 57) {
var data = e.target.value;
if(e.target.value.match(/^[-]+/))
e.target.value = '-' + data.substr(1).replace(/\D/, "");
else { console.log('else');
e.target.value = data.replace(/\D/,"");
}
}
Change
if(e.keyCode < 48 || e.keyCode > 57) {
to
if((e.keyCode < 48 || e.keyCode > 57) && e.keyCode!=8) {
Then you'll ignore the backspace character just like a number, which won't cause any other issues.
I just figured out the issue, Renegade has a decent method, but I made a Regex mistake. It should be this:
if(e.target.value.match(/^[-]+/))
Rather than:
if(e.target.value.match(/^[-]?/))
Since the latter will give true even if the dash does not exist. ? means 0 or 1 matches, + is 1 or more.
I tried to make a javascript function to validate integer values from a text box. What is the best way to validate it so that only integer and float values are acceptable?
Required java script function for number validation.
// remove whitespaces
var input = input.replace(/\s+/g,"");
// check if the input is a valid number
if(isFinite(input) && input != ''){
// do your thing
}
Remember that isFinite only accepts values like '20.50' and not '20,50' as is custom in some countries. If you need this kind of flexibility you need to do additional string preprocessing. And with this solution only spaces are allowed as thousand delimiters (e.g '100 000').
Unfortunately the check for an empty string is necessary since isFinite('') returns true.
You could also use this function from user CMS (for a detailed explanation see: Validate decimal numbers in JavaScript - IsNumeric())
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Best ever solution for me for numeric validation in javascript.
function isFloat(evt) {
var charCode = (event.which) ? event.which : event.keyCode;
if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57)) {
alert('Please enter only no or float value');
return false;
}
else {
//if dot sign entered more than once then don't allow to enter dot sign again. 46 is the code for dot sign
var parts = evt.srcElement.value.split('.');
if (parts.length > 1 && charCode == 46)
{
return false;
}
return true;
}
}
Just Copy and past javascript code and apply to your textbox onkeypress like this ..
<input type="text" onkeypress="return isFloat(event)" />
onload =function(){
var ele = document.querySelectorAll('.number-only')[0];
ele.onkeypress = function(e) {
if(isNaN(this.value+""+String.fromCharCode(e.charCode)))
return false;
}
ele.onpaste = function(e){
e.preventDefault();
}
}
<input class="number-only" type=text />
JavaScript has a built in function, isNaN(text). Just pass the text of your text box to this function to get a Boolean result.
var valid = !isNaN(value);
Eg:
!isNaN('0'); // true
!isNaN('34.56'); // true
!isNaN('.34'); // true
!isNaN('-34'); // true
!isNaN('foo'); // false
!isNaN('08'); // true
!isNaN(''), !isNaN(' '), !isNaN('\n\t'), etc are all true!
Whitespace test + isNaN FTW:
var valid = !/^\s*$/.test(value) && !isNaN(value);
I have a regular text-box:
<input type="text">
I use jQuery to handle key-related events:
$("input:text").keydown(function() {
// keydown code
}).keypress(function() {
// keypress code
}).keyup(function() {
// keyup code
});
The user focuses on a text-box and presses various keys on his keyboard (the usual ones: letters, numbers, SHIFT, BACKSPACE, SPACE, ...). I need to detect when the user presses a key that is going to increase the length of the text-box value. For example, the "A" key will increase it, the "SHIFT" key wont.
I remember watching a lecture by PPK where he mentioned the difference between those two. It has something to do with the event - keydown vs. keypress - and possibly with the event properties - key, char, keyCode.
Update!
I need to know this information within the keydown or keypress handlers. I cannot wait for the keyup event to occur.
Why I need this:
I have a text-box which size dynamically changes based on the user input. You can have a look at this demo: http://vidasp.net/tinydemos/variable-size-text-box.html
In the demo, I have a keydown and keyup handler. The keyup handler adjusts the text-box size based on the input value. However, the keydown handler sets the size to be 1 character larger then the input value. The reason I do this is that if I didn't, then the character would overflow outside the text-box and only when the user would let go of the key, the text-box would expand. This looks weird. That's why I have to anticipate the new character - I enlarge the text-box on each keydown, ergo, before the character appears in the text-box. As you can see in the demo, this method looks great.
However, the problem are the BACKSPACE and ARROW keys - they will also expand the text-box on keydown, and only on keyup the text-box size will be corrected.
A work-around:
A work-around would be to detect the BACKSPACE, SHIFT, and ARROW keys manually and act based on that:
// keydown handler
function(e) {
var len = $(this).val().length;
if (e.keyCode === 37 || e.keyCode === 39 ||
e.keyCode === 16) { // ARROW LEFT or ARROW RIGHT or SHIFT key
return;
} else if (e.keyCode === 8) { // BACKSPACE key
$(this).attr("size", len <= 1 ? 1 : len - 1);
} else {
$(this).attr("size", len === 0 ? 1 : len + 1);
}
}
This works (and looks great) for BACKSPACE, SHIFT, ARROW LEFT and ARROW RIGHT. However, I would like to have a more robust solution.
This I think will do the job, or if not is very close and will need only minor tweaking. The thing you have to remember is that you can't reliably tell anything at all about any character that may be typed in a keydown or keyup event: that all has to be done in a keypress handler. The definitive resource for key events is http://unixpapa.com/js/key.html
You also need to consider pastes, which this code won't handle. You will need to have separate paste event handler (although this event isn't supported in Firefox < 3.0, Opera, and very old WebKit browsers). You'll need a timer in your paste handler since it's impossible in JavaScript to access the content that's about to be pasted.
function isCharacterKeyPress(evt) {
if (typeof evt.which == "undefined") {
// This is IE, which only fires keypress events for printable keys
return true;
} else if (typeof evt.which == "number" && evt.which > 0) {
// In other browsers except old versions of WebKit, evt.which is
// only greater than zero if the keypress is a printable key.
// We need to filter out backspace and ctrl/alt/meta key combinations
return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
}
return false;
}
<input type="text" onkeypress="alert(isCharacterKeyPress(event))">
Here's a much simpler solution which worked well for me:
document.addEventListener('keyup', event => {
if (String.fromCharCode(event.keyCode).match(/(\w|\s)/g)) {
//pressed key is a char
} else {
//pressed key is a non-char
//e.g. 'esc', 'backspace', 'up arrow'
}
});
This doesn't require probing a DOM element (which would add latency and ugliness).
Updated example use:
The possible solution I can find is checking the length of key in event.
Eg:-
<input type="text" id="testId" onkeyup="keyChecking(event)" />
<script type="text/javascript">
function keyChecking(event) {
if (event.key.length == 1) {
alert("key produced character " + event.key);
} else {
alert("Key DOES NOT produce character");
const alphabets = "AZaz09";
const key = event.key;
var notEvenASymbol = false;
for (let i = 0; i < key.length; i++) {
var charCode = key.charCodeAt(i);
if ((charCode >= alphabets.charCodeAt(0) && charCode <= alphabets.charCodeAt(1)) ||
(charCode >= alphabets.charCodeAt(2) && charCode <= alphabets.charCodeAt(3)) ||
(charCode >= alphabets.charCodeAt(4) && charCode <= alphabets.charCodeAt(5))
) {
notEvenASymbol = true;
console.log(charCode);
break;
}
}
if (notEvenASymbol) {
alert("Key DOES NOT produce even a symbol");
}
console.log(event.key);
}
}
</script>
So, if you press any characters/symbols, the event.key will contain that character and its length will be 1. If you press character V then the event.key will have value V but if you press enter key then it will contain value Enter, if you press shift then Shift and so on. Therefore, if a key doesn't produce a character then its length will be greater than 1.
Updated
Some special keys in the keyboard produce symbol and its length may be greater than 1 so I modified the code so that it can alert even if it's not a symbol. Eg:- 😄 its length is 2. Some mobile keyboards have shortcut keys for such symbols.
A non character/symbol key in the keyboard will always be a combination of alphabets, number characters or of both, Eg:- F2, Shift.
Thanks #Vicky Chijwani for bringing attention to this scenario.
To detect in a keydown handler if a pressed key produces a single unicode character, you can use the ES6 unicode u flag for regular expressions.
We use the KeyboardEvent.key property, which returns the value of the pressed key. According to the docs:
If the pressed key has a printed representation, the returned value is a non-empty Unicode character string containing the printable representation of the key.
inputElement.addEventListener("keydown", ({ key }) => {
if (/^.$/u.test(key)) {
// `key` matches a single unicode character
}
});
The solution does not handle pasting...
OK, I think I've got it. The solution is a bit hackish, but actually works really well.
On keydown, do a setTimeout for 1 millisecond, that calls a function to check/change the length of your input box.
function checkLength() {
var len = $("input:text").val().length;
$("input:text").attr("size", len === 0 ? 1 : len + 1);
}
$("input:text").attr({
"size": 1,
"spellcheck": false
}).keydown(function() {
setTimeout(checkLength, 1);
});
p { padding:50px; }
input {
border:1px solid gray;
padding:6px;
font-size:26px;
font-family:monospace;
outline:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<input type="text"></input>
It seems to work really well, especially in a few places where your version doesn't (e.g. backspace, CTRL+V, or selecting a whole bunch of text and hitting delete)
Edit: Even setTimeout with a 0ms delay seems to work!
You should use the property keyEventArgs.Key in the keydown function, this will return the numeric value that will depend on the system.
here is a link that has the different key codes for the different browsers and OS:
http://www.quirksmode.org/js/keys.html
This may not be the method that you're looking for, but you can just check the value of this.value.length in your keydown function. The return value is the length of the text in the input field BEFORE the new character is added. So if you check the length again in the keyup function, it will be greater if the user pressed a character, but the same if the user hit the shift key.
I presume you are setting up a counter on the length of an input field, in which case you don't need to be so fancy, you can just keep assigning the length of the field to a variable, and when the user gets to your max length only allow them to press delete or backspace like so:
$("input:text").keypress(function() {
var current = $(this).val().length;
if (current >= 130) {
if (e.which != 0 && e.which != 8) {
e.preventDefault();
}
}
}
You can use the current variable to display the counter as well, or do maxlength - current to do a countdown of how many charachters are left
Your goal of keeping the textbox larger than the text that has been entered into it.
I'd accomplish this by planning on having room for two additional characters (not one) in the text box. Then:
// pseudo-code....
old_len = textbox.value.length
keyUp function() {
var new_len = textbox.value.length
if (new_len != old_len) {
old_len = new_len
textbox.style.size = new_len + 2 // pseudo code.
}
}
The advantage of the above is that you don't need to descend into the nether world of keycodes.
Not sure about all possible keyboards, but in my keyboard I noticed that combining the "keypress" event (don't use keydown or keyup) with event.key will return a character only if it's printable, the only exception is the "Enter" key which will return the word "Enter"
so I come up with the following simple solution:
document.addEventListener('keypress', (event) => {
if(event.key && event.key != 'Enter'){
console.log('this is a character')
}
});
This solution seems to also ignore shortcuts like ctrl+c or ctrl+v which other answers don't handle
Note: tested in mozilla and brave, I would like to see what is the result in other browsers (please comment)
Based on other answers I created following:
export function producesCharacter(event: React.KeyboardEvent<HTMLInputElement>) {
return !event.ctrlKey && !event.altKey && event.key.length === 1;
}
Other solutions may not work in React due to deprecation warnings
You can subscribe to "InputEvent" and then get "data" prop. For example
input.addEventListener('beforeinput', (event) => {
const data = event.data;
// if "data" is present - user enter some character
// if "data" is NOT present - user tap non character key (e.g. delete, shift and other)
if(data) {
const isAllow = /\d/.test(data);
if(!isAllow) {
e.preventDefault();
}
}
})
More info
event.data - https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/data
beforeinput event - https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/beforeinput_event
I understand that you wanted to solve it within "keyup" or "keydown" listeners. However, I came across an issue similar to this, and solved it by using the "input" eventListener. It listens for changes in the input and makes changes accordingly. Thought I would share.
You could do something like this:
$("input:text").on("input", (e) => {
e.target.size = e.target.value.length
})
Because: "The input event fires when the value of an , , or element has been changed."
This will also handle pasting and deleting.
One thing: In your example you are incrementing the size by 1 per character. The problem with this approach is that character width is variable and dependent on the font used. It won’t be totally accurate, but will still work
You can detect key like "shift" and remove before display
//remove some text in blacklist from input
function removeFromString(words, str) {
return words.reduce((result, word) => result.replaceAll(word, ''), str)
}
var pureInput = "";
document.addEventListener("keydown", function(event) {
const black_List_Keys = ["Shift","Control","Alt","Enter","Backspace"];
pureInput = removeFromString(black_List_Keys,pureInput+event.key);
document.getElementById("demo").textContent = pureInput;
});
<h1 id="demo">Press Keys</h1>
<p>Try type this word using shift And char like : <br> <b>T</b>ail<b>W</b>ind</p>
The following code uses the correct .key event and not the (outdated?) which event
if (/[a-zA-Z]/.test(e.key) && e.key.length == 1) {
//keypress is character
}