keydown event - key pressed on different systems - javascript

I have a number input, which I want user to by unable to insert any non-digit characters. We have attempted this in a number of ways:
We started with removing all non-numeric characters on blur:
$(my_input).blur(function() {
$(this).val($(this).val().replace(/[^\d]/, '')
}
The problem with the code above is that number field's val function returns empty string if the input is invalid. We definitively want a number field as our website is to be used on mobiles.
The option which I would prefer is to use keydown event:
$(my_input).keydown(function(e) {
if (e.shiftKey === true ) {
if (e.which == 9) {
return true;
}
return false;
}
if (e.which > 57) {
return false;
}
if (e.which==32) {
return false;
}
return true;
});
The above works almost as a charm. The problems are:
numeric keyboard not included in a range - this can be however easily fixed and is not a subject of this question.
For unknown to me reasons js on iOS is using different key codes, hence this is not working on huge part of mobile phones, iPads etc.. This is a deal breaker.
So the question - is there any way to determine which key was actually pressed with an keydown event. I have seen number of similar questions, none of them however covered those iOS differences. I've noticed that event has a 'key' property, however I am not sure how reliable this property is.

EDIT: I fell on this post which might be a neat way to solve your problem:
JavaScript: Avoiding hardcoded keycodes
It would boil down to
var digitCodes = "0123456789".split('').map(function (x) { return x.charCodeAt(0); });
There might be a better way to do this but you could detect if the device is running iOS (c.f. Detect if device is iOS) and use the appropriate keycodes (c.f. http://notes.ericjiang.com/posts/333).
var digitCodes;
if (isiOS()) {
digitCodes = keycodes.ios;
}
else {
digitCodes = keycodes.default;
}
if (digitCodes.indexof(e.which) != -1) {
...
}
Something like that...

You can try it this way
sample text box
<input type="text" name="sample" id="sample" onkeyup="positiveNumericOnly(this);" />
JS Code
function positiveNumericOnly(ele)
{
tempVal = ele.value.replace(/[^\d]/g, "");
if(tempVal != ele.value)
ele.value = tempVal;
}

Related

How to check for the multiple dots and stop to enter multiple dot using javascript?

I am having a input type text.
<input type="text" class="checkForDot" />
What i am trying to do is, when a user enters numbers into the box then find for the "." in the field, if it contains more then one ".", then prevent it to enter another "." in the text field.
my jquery code is:
$(".checkForDot").on("keyup", function (event) {
CheckForDot($(this).val());
});
function CheckForDot(value) {
if (value != null || value != '') {
var str = value.toString();
if (str.indexOf('.', str.indexOf('.') + 1) != -1) {
console.log("ok");
}
}
}
It is working fine, if two "." enters into the text box, but how to prevent to enter multiple "." in the text field?
If any other approach better than this please tell.
$(document).ready(function() {
var original='';
$('.checkForDot').on('input', function() {
if ($(this).val().replace(/[^.]/g, "").length > 1){
$(this).val(original);
}else{
original = $(this).val();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='text' class='checkForDot' />
Try to use this regex to find how many dots you got in string.
If you are looking to make a field that only allows for numbers, you should consider using an input of type="number" as they will only allow for valid number characters to by added to its value. In some cases, it might even bring a different visual keyboard to ease of filling, wich is better for accessibility and UX. The number input field will, by default allow for mutliple dots, wich is annoying and is a bit harder to prevent than in a text field so it's a case of figuring wether accessibility and your UX is more important than adding a few extra lines of Javascript.
A lot of people will tell you that it is bad practice to limit keyboard actions, and they are right. when you do a preventDefault() on everything but numbers and ".", you disable tabing through form fields, the browser alt menu, any ctrl shortcuts, anything that happens within the browser.
This solution is simple and will only allow one dot in the number field. It doesn't prevent from clicking back in the number and adding numbers before the ".". It doesn't prevent from executing browser keyboard shortcuts like refresh, copy and pasting, as long as the pasted value is a valid number. It will allow to add "." withing the body of the number.
The only behavior that can't be prevented is if the user press the dot key at the end of the input repeatedly, the dot will blink on and off. This happens because of the way the number field handles its value. Wen the user types a dot at the end of a number like "13.", javascript can only retreive "13" when looking at its value as long as no decimal number have been placed. If the user typed a dot again, the value of "13.." would not be a valid number and therefore javascript woudl retreive "". This ensure you eighter get a valid number or nothing at all. In my solution, if a value returns "" without the press of backspace, delete or cut, it gets rolled back to the last valid value, wich in my example was "13", obtained from the typed value "13.". Preventing this behavior seems practically impossible and isn't a deal breaker as you get ensured your field value is always a valid, single dot number.
let lastValidInputValue;
let selectedDot = false;
const onKeypress = (e) => {
if (e.key === "." && e.target.value.indexOf(".") !== -1 && !selectedDot) e.preventDefault();
selectedDot = false;
};
const onInput = (e) => {
if (e.target.value !== "") {
lastValidInputValue = e.target.value;
} else if (e.inputType.match(/delete/g)) {
lastValidInputValue = "";
} else {
e.target.value = lastValidInputValue;
}
};
const onSelect = (e) => {
selectedDot = (window.getSelection().toString().indexOf(".") > -1)? true : false;
}
<input type="number" id="myNumber" name="myNumber" step="any" onkeypress="onKeypress(event)" oninput="onInput(event)" onselect="onSelect(event)">
You can find very detailed comments and extra bits in this Codepen

get the new added characters to an input by js

I know this seems a quite easy target. I have an input[type=text], and I want to detect the new added character(s) in it. The normal way is:
$selector.keypress(function(e) {
//do sth here
var newchar = String.fromCharCode(e.which);
});
But the above method not working properly for some browsers on android devices. Typing the android virtual keyboard will not fire the keypress.
Then I found the following method is better:
$selector.on('input', function(e){
//do sth here
});
It works fine for android devices, and also, it can detect cut/paste.
Now the question is, is there a way to know the new added character(s) to the input? Do I need to do the complicated string comparison during inputing each time, i.e. compare the previous string and the new string in the input box? I said it's complicated because you may not always type in char(s) at the end, you may insert some char(s) in the middle of the previous string. Think about this, the previous string in the input box is "abc", the new string after pasting is "abcxabc", how can we know the new pasted string is "abcx", or "xabc"?
The method from keypress is quite simple:
String.fromCharCode(e.which);
So, is there similar way to do this by the on('input') method?
After reading Yeldar Kurmangaliyev's answer, I dived into this issue for a while, and find this is really more complicated than my previous expectation. The key point here is that there's a way to get the cursor position by calling: selectionEnd.
As Yeldar Kurmangaliyev mentioned, his answer can't cover the situation:
it is not working is when you select text and paste another text with
replacing the original one.
Based on his answer, I modified the getInputedString function as following:
function getInputedString(prev, curr, selEnd) {
if (selEnd === 0) {
return "";
}
//note: substr(start,length) and substring(start,end) are different
var preLen = prev.length;
var curLen = curr.length;
var index = (preLen > selEnd) ? selEnd : preLen;
var subStrPrev;
var subStrCurr;
for(i=index; i > 0; i--){
subStrPrev = prev.substr(0, i);
subStrCurr = curr.substr(0, i);
if (subStrCurr === subStrPrev) {
var subInterval = selEnd - i;
var interval = curLen - preLen;
if (interval>subInterval) {
return curr.substring(i, selEnd+(interval-subInterval));
}
else{
return curr.substring(i, selEnd);
}
}
}
return curr.substring(0, selEnd);
}
The code is quite self explanation. The core idea is, no matter what character(s) were added(type or paste), the new content MUST be ended at the cursor position.
There's also one issue for my code, e.g. when the prev is abcabc|, you select them all, and paste abc, the return value from my code will be "". Actually, I think it's reasonable, because for my scenario, I think this is just the same with delete the abc from previous abcabc|.
Also, I changed the on('input') event to on('keyup'), the reason is, for some android browsers, the this.selectionEnd will not work in a same way, e.g., the previous text is abc|, now I paste de and the current string will be abcde|, but depending on different browsers, the this.selectionEnd inside on('input') may be 3, or 5. i.e. some browsers will report the cursor position before adding the input, some will report the cursor position after adding the input.
Eventually, I found on('keyup') worked in the same way for all the browsers I tested.
The whole demo is as following:
DEMO ON JSFIDDLE
Working on the cross-browser compatibility is always difficult, especially when you need to consider the touch screen ones. Hope this can help someone, and have fun.
Important notes:
when a user types in a character, the cursor stands after it
when a user pastes the text, the cursor is also located after the pasted text
Assuming this, we can try to suggest the inputed \ pasted string.
For example, when we have a string abc and it becomes abcx|abc (| is a cursor) - we know that actually he pasted "abcx", but not "xabc".
How do this algorithmically? Lets assume that we have the previous input abc and the current input: abcx|abc (cursor is after x).
The new one is of length 7, while the previous one is of length 4. It means that a user inputed 4 characters. Just return these four characters :)
The only case when it is not working is when you select text and paste another text with replacing the original one. I am sure you will come up with a solution for it yoruself :)
Here is the working snippet:
function getInputedString(prev, curr, selEnd) {
if (prev.length > curr.length) {
console.log("User has removed \ cut character(s)");
return "";
}
var lengthOfPasted = curr.length - prev.length;
if (curr.substr(0, selEnd - lengthOfPasted) + curr.substr(selEnd) === prev)
{
return curr.substr(selEnd - lengthOfPasted, lengthOfPasted);
} else {
console.log("The user has replaced a selection :(");
return "n\\a";
}
}
var prevText = "";
$("input").on('input', function() {
var lastInput = getInputedString(prevText, this.value, this.selectionEnd);
prevText = this.value;
$("#result").text("Last input: " + lastInput);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<div id="result">Start inputing...</div>

Keycode is always zero in Chrome for Android

I need to detect the keycode for a custom search box on my website, but the keycode always returns as zero on Chrome for Android (except for backspace, which returns 8). Has anyone else experienced this, and how did you get around it? Our website works on all mobile browsers except Chrome for Android because we can't detect a non-zero keycode or charcode.
I'm running Chrome 27.0.1453.90 on Android 4.1.2 Jelly Bean. The problem can be duplicated with something as simple as:
alert(event.keyCode);
below solution also work for me. might be useful for others also.
var getKeyCode = function (str) {
return str.charCodeAt(str.length - 1);
}
document.getElementById("a").onkeyup = function (e) {
var kCd = e.keyCode || e.which;
if (kCd == 0 || kCd == 229) { //for android chrome keycode fix
kCd = getKeyCode(this.value);
}
alert(kCd)
}
I faced this issue and this is how I figured out how to solve the problem.
First, you need to enable USB debugging onto your Android phone so
you can see the logs of your browser on your desktop machine.
Second, refresh your web app on your phone and inside your console on the desktop type "monitorEvents(document)" or whatever element you want to inspect.
Do the action you want to inspect on your phone.
And this is how I found that the keydown event was actually fired by a unique event called "textInput" which contains the information inside event.originalEvent.data.
Hope this saves you time and good luck!
The true way to get the keyCode is to use
event.which
This property on event object is standardize the event.keyCode property. You can read about it also in jQuery documentation here or in MDN here
In other way, I have a lot of experience with keyboard events on android devices.
Android browser has problems sometimes with keyboard events due to device fragmentation (different ROMs between devices or external keyboard apps). The best way is to try to use all the keyboard events (keydown, keyup and keypress) and compare every result to get the pressed key.
The best way is to use in "input" event and get all the time the last charter. The input event can control like in my answer here.
We encountered this problem recently on a China made Android phone Meizu MX3, which has a deeply customized OS based on Android 4.4.4.
The default browswer and Chrome work just fine, but for some weird reasons we don't know, event.keyCode, event.charCode and event.which return 0 all the time in some other browsers(such as CM Browser or webview of Wechat app).
We resolved this by checking the last character you input such as 'A' or ' '(space), then we convert it to ascii code using charCodeAt such as "A".charCodeAt(0) which returns 97, which is the actual char code we need.
But we can only determine the char code of visible chars using this strategy, which meets our current need thank god.
Hope you guys can get some inspiration from this.
I have faced the same issue with Android Devices of SonyXperia and HTC. I have developing hybrid application where i am validating Amount text field by reading event.keyCode() of the entered char on keydown event from text field, so that i can allow only numbers and dot(.) char to be entered. I tried but it doesn't worked, returning always 0 in these devices.
Later i came with other solution with keyup event and char matching through Regular Expression:
$("#AmountField").keyup(function (e) {
var regex = /^[0-9\.]$/;
var str = $(this).val();
var subStr = str.substr(str.length - 1);
if(!regex.test(subStr)) {
if(str.length >0){
$(this).val(str.substr(0, (str.length - 1)));
}else{
$(this).val();
}
}
});
Hope this can help for the people who facing this issue. Good Luck.
<input type="text" id="char" size="15" onblur="showKeyCode()" value="a">
<input type="button" value="Show Key Code" onclick="showKeyCode();">
<script>
function showKeyCode()
{
var character = document.getElementById ( "char" ).value.substr(this.length - 1);
var code = character.charCodeAt();
var stringall = document.getElementById ( "char" ).value;
var msg = "The Key Code for the \""+character+"\" character is "+code+".";
alert(msg);
}
</script>
For reference
If anybody still digging it.Problem appears on stock Samsung keyboard for
android devices.
Instead use onkeyup.
change the type of the input to tel : <input type="tel">
this will let you log the keyCode but it doesnt log the backspace, and it might force the keyboard on mobile to only numbers.
So in most Android browser if u use keydown or keyup you wont be able to get the data from key or keyCode or which or code
You can use event.data(Inserted data key) and event.inputType(backspace or del in mobile)
In order to achieve the functionality you need you have to apply condition based on user agent for android mobile
if (navigator.userAgent.match(/Android/i)) {
node.addEventListener('input', handleInput, false);
} else {
node.addEventListener('keydown', handleKeyDown, false);
}
const handleKeyDown = event => {
event.preventDefault();
if (!event.key) {
return false;
}
genericFunctionHandleThings(event.key, event.code === 'Backspace');
};
const handleInput = event => {
event.preventDefault(); // Here event.preventDefault doesn't stop user from typing
genericFunctionHandleThings(event.data, event.inputType === 'deleteContentBackward');
node.value = storedOrProcessedValue;
};
Here I have used node.value = storedOrProcessedValue because if we want to make some restriction for user typing we need to process and re assign it to the input
You can use this with Input type text,url,email,tel these I have tested rest I need to check
Need to use charCode instead of keyCode
<input type="text" onKeyPress="return funName(this,event)" />
<script language="javascript">
function funName(th,ev)
{
alert(ev.charCode);
}
</script>

Jquery detect input focus

I am creating a conversion web app to teach myself Javascript. The user can input data with a number pad (basically a calculator without the operators). I also set up a function to detect keystrokes (1-9) which insert data just like the number pad. And also character 'c' which clears all data
My problem is that I also have a search field (which uses auto complete to enable the user to search for other conversions). I dont' want the user to search for something using the 'c' or number keys, and have it enter data into both the number pad, and search field.
My idea was to create a if statement to determine if the search field was active (focused), and if it was to change a variable (enabled) to false, thus disabling the keystroke detection.
The problem I am having is that the function holding the if statement with the focus attribute is not working.
If my rambling made no sense hopefully the code will clear things up.
Here is the if statement with the focus attribute
$(document).ready(function(){
if($(':focus').attr('#searchInput') == 'input')){
enabled === false;
}
});
Here is the code for key stroke detections (I omitted the redundant parts to save space
document.onkeydown = function(event){
var key = event.charCode || event.keyCode;
if(enabled === true){
if(key === 67){
clearInput(input); //Clears form input (input is my form ID)
}else if(key === 48){
writeInput(input, zero); //Zero is a var equaling 0
}
...
}else{
return false; //if enabled is false don't detect keystrokes
}
};
Any help would be greatly appreciated. If anything doesn't make sense I will be happy to explain (or edit the post.)
$(document).keyup(function(e){
if($('#searchInput').is(':focus')) {
return ; // search field is focused, ignore other part of function
}
var key = e.which;
// do your code here
});

how to accept only alphabetical pressed keys ( for "autocomplete" purpose )

am wondering ... how to only accept alphabetical pressed keys from the keyboard .. i am using the jQuery .keypress method ... now i wanna know how to filter the passed key ...
i am trying to build a simple autocomplete plugin for jQuery ...i know a about jQuery UI, but i want to do it myself ...
thanks in advance :)
You can bind a function to the field that replaces anything that's not in the a-z range.
<input name="lorem" class="alphaonly" />
<script type="text/javascript">
$('.alphaonly').bind('keyup blur',function(){
$(this).val( $(this).val().replace(/[^a-z]/g,'') );
});
</script>
Source: Allow text box only for letters using jQuery?
In your callback, you can check the event's keyCode property. If you want to disallow the key being entered, simply return false. For example:
$('#element').keypress(function(e)
{
if(e.which < 65 || e.which > 90) //65=a, 90=z
return false;
});
Note that this won't really work very well. The user could still paste in other text, or use a mouse-based entry device, or any number of other things.
I've edited this based on Tim Down's comment and replaced keyCode with which, which is correct across keydown, keyup, and keypress events.
The following will prevent any character typed outside of a-z and A-Z from registering.
$("#your_input_id").keypress(function(e) {
if (!/[a-z]/i.test(String.fromCharCode(e.which))) {
return false;
}
});
This won't prevent pasted or dragged text appearing. The surest way to do that is the change event, which is only fired once the input has lost the focus:
$("#your_input_id").change(function(e) {
this.value = this.value.replace(/[^a-z]+/gi, "");
});
This worked for me, it only accepts letters no special characters or numbers
$("#your-input-here").keypress(function (e) { return validateAlphaKeyPress(e); });
function validateAlphaKeyPress(e) {
if (e.keyCode >= 97 && e.keyCode <= 122) {
return true;
}
return false;
}

Categories

Resources