Is there any way to determine in javascript whether shift key is pressed on mobile keyboard, and distinguish it from the caps lock(twice pressed shift key)
Some Facts
First, let's look at some facts about iOS keyboards I assume you already know:
When you enter the keyboard mode, the shift key is always activated
Caps Lock must be activated manually (I guess this is not used too widely)
iPhone Shift Key Handling
I investigated a bit into this issue, and here's what I found:
The shift Key triggers no key Event
There is no special iPhone Browser API to detect whether the shift key is pressed or not, except in an iOS App (duh)
The keydown, keypress, keyup event triggered by iOS look normal, except they do not indicate shiftKey usage, and apart from their timestamp and type cannot be distinguished.
You cannot manually dispatch a Keyboard Event in iOS because of this issue, keyCode and which are readonly and always set to 0. Retriggering a Keyboard event to get some indication about the shift key still being on is impossible.
Actually, The iPhone treats the shift key like some sort of Short Term Caps Lock key. The difference is that normally, you activate it once, and it deactivates automatically.
What can be done
I assume you want to indicate on an input field whether the user should be careful about having Shift/Caps Lock pressed (a password field, for example). What I came up with is some sort of a workaround, but I think it's better than nothing.
You can also test the jsfiddle here.
DOM Setup
<div id="wrapper">
<label for="test">ENTER SOMETHING HERE</label>
<input type="text" name="test" id="test"/>
</div>
<div id="warning"></div>
Javascript
This checks wheter the user did enter capitalized input, and it assumes the user is using caps lock if two capitalized letters where entered.
var isCaps = false,
isUppercase = false,
str = '',
test = document.getElementById('test'),
warning = document.getElementById('warning');
function capsDetection(e) {
// Since where on iOS, we at least don't have to care
// about cross-browser stuff
var s = String.fromCharCode(e.which);
isCaps = isUppercase;
// if the char doesn't match its lower case friend, and the shift key is
// not pressed (which is always the case on iOS, but we leave it there
// for readability), we have uppercase input
isUppercase = (s.toUpperCase() === s && s.toLowerCase() !== s && !e.shiftKey);
// if its the second uppercase input in a row, we may have caps lock input
isCaps = isCaps && isUppercase;
// set the warning
if (isUppercase && !isCaps) {
str = 'You where using the shift key';
}
else if (isCaps) {
str = 'Caps lock seems to be activated';
} else {
str = '';
}
warning.innerHTML = str;
}
// the right event properties are only available on keypress
test.addEventListener('keypress', capsDetection);
As I said, better than nothing, but not a solution if you need to know the shift key is pressed without the user doing any input. That seems to be impossible right now.
I don't think that this is possible with Javascript. It is possible with objective C though.
http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html
Related
For context: this is a JavaScript app running in the Xbox One. All of this is happening through the Xbox's virtual keyboard. Keep in mind that since I have figured out how the events are being fired, this shouldn't matter anymore, just how to deal with the two events at once.
It's not really multiple keys, what is happening is when I turn on CAPS for my app, I am getting two events keys at once: shift and whatever key I am actually pressing. The problem this is causing is that shift seems to be overriding whatever I am trying to spell, and no key is displayed in my input boxes.
I currently have a global function which takes care of all special events in the app, and I would like to handle this issue from over there but am not sure how to go about this issue.
Here is what I currently have:
// this is the global function where I would like to solve the issue
onStartup(function () {
var $html = $('html')
$html.on('keydown', function (evt) {
if (evt.isDefaultPrevented()) return
console.warn('key being pressed:', evt.keyCode)
if (evt.keyCode === 16) { // Note: 16 is shift's keycode
// do something to prevent shift from overriding the actual key I want to press.
return
}
})
})
When I press a key without CAPS being turned on, say a, which has the keyCode of 65, we have the following output:
key being pressed: 65
If however I try to do a capital a (or A), this is what happens:
key being pressed: 16
key being pressed: 65
What can I do to stop the shift from preventing me from actually typing the capital keys?
I figured it out! All I had to do was when shift was fired, to call evt.stopImmediatePropagation().
So basically, for my code:
// ...
if (keycodeControls.is('shift', evt)) {
evt.stopImmediatePropagation()
}
I want to know if ctrl,space,alt,capslock,shift like keys are pressed in my keyboard.
When i do
String.fromCharCode(e.keyCode)
,it returns blank value for these keys but when I do
alert($.trim(String.fromCharCode(e.keyCode))=='')
Then it return false for all keys except space bar.So it would be great if someone may tell me to get the keydown event of these keys
Vanilla JavaScript:
For other constants, see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
window.onkeydown = function (e) {
switch (e.keyCode) {
case KeyboardEvent.DOM_VK_SPACE:
alert('space bar!');
break;
case KeyboardEvent.DOM_VK_CAPS_LOCK:
alert('CAPS LOCK!');
break;
case KeyboardEvent.DOM_VK_CONTROL:
alert('control!');
break;
case KeyboardEvent.DOM_VK_SHIFT:
alert('shift!');
break;
case KeyboardEvent.DOM_VK_ALT:
alert('alt!');
break;
}
};
UPDATED FOR REQUIREMENT TO AVOID CASES:
Per the following test, the only numeric values that will, after trimming (and not including numbers not corresponding to the average keyboard), be reduced to an empty string are 9,10,11,12,13,32. Looking at https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Virtual_key_codes , the only ones that correspond are tab, clear, return, and space .
// Run in Firefox where trim() is supported (without need for jQuery):
var arr = [];
for (var i=0; i < 0xFFFF; i++) {
if (String.fromCharCode(i).trim() == '') {
arr.push(i);
}
}
In other words, your own test is not going to catch all cases.
So you have to use numeric comparisons based on the info at https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Virtual_key_codes and BASED ON EXACTLY WHAT CHARACTERS YOU NEED TO INCLUDE (or exclude).
For example, if you consider the cancel key, help key, back space, tab, etc. all to be of the type you mentioned, you can do:
window.onkeydown = function (e) {
if (e.keyCode < 0x30) {
alert('Special key pressed!');
}
};
As you can see, this allows for us to find a whole group of characters within a short amount of code (e.g., without using case). (But if we don't know exactly which characters you want to include or exclude, we can't give you a more precise answer.)
NOTE:
charCode is never set in the keydown and keyup events. In these cases, keyCode is set instead.
you can try
$(window).keydown(function (e){
if (e.ctrlKey) { there are e.altKey & e.shiftKey also.
for other keys use hardcoded integer values.
alert("control");
}
});
I'm not sure about the support of keyIdentifier but if you are using the keyup, keydown or keypress events, but you could possibly do the following. However there are no cross-browser guarantees where charcode is not defined or is zero. Not using jquery to keep things as small as possible, and only detecting the keys that you specified. See article.
Javascript
/*jslint maxerr: 50, indent: 4, browser: true */
(function () {
"use strict";
function addEvent(elem, event, fn) {
if (typeof elem === "string") {
elem = document.getElementById(elem);
}
function listenHandler(e) {
var ret = fn.apply(null, arguments);
if (ret === false) {
e.stopPropagation();
e.preventDefault();
}
return ret;
}
function attachHandler() {
window.event.target = window.event.srcElement;
var ret = fn.call(elem, window.event);
if (ret === false) {
window.event.returnValue = false;
window.event.cancelBubble = true;
}
return ret;
}
if (elem.addEventListener) {
elem.addEventListener(event, listenHandler, false);
} else {
elem.attachEvent("on" + event, attachHandler);
}
}
function checkKeys(e) {
if ("Alt,Shift,Control,CapsLock,U+0020".indexOf(e.keyIdentifier) !== -1) {
alert(e.keyIdentifier);
}
console.log(e.keyIdentifier);
}
addEvent(window, "keydown", checkKeys);
}());
On jsfiddle
Update: reading a bit furter, keyIdentifier is not supported by all browsers and so is not fullly cross-browser friendly.
3.4. New Standard Key and Character Events
The DOM3 standard abandons all hope of creating order among
event.keyCode, event.which and event.charCode, and instead defines new
values for keydown and keyup events. For a while it deprecated the
keypress event and replaced it with the textInput event, but that was
undone. Only a few browsers implemented the first version, and, so
far, no browsers have implemented the newest version. Earlier versions
of the specification defined attributes named event.keyIdentifier and
event.keyLocation. The keyIdentifier was a string that in most cases
looked like "U+0041" where the "0041" part is the unicode value of the
character sent by the key when it is typed without modifiers, in this
case the letter "A". For keys that didn't send unicode characters, or
where the unicode value is not standardized, it was a string like
"Enter", "Shift", "Left" or "F9". The keyLocation attribute gave
values to distinguish among multiple keys that had the same
identifier, like the left and right shift keys, or the keypad number
keys. It was 0 for standard keys, 1 or 2 for left or right versions of
a keys like Shift which appear twice on the keyboard, and 3 for keys
on the numeric keypad.
WebKit implemented support for keyIdentifier and got it mostly right.
Older versions conformed to an older version of the standard and
returned two extra zeros (eg, "U+000041") but this was corrected in
version 525. Windows versions of Safari and Linux versions of Chrome
return bad keyIdentifier values for all of the non-number symbol keys
(WebKit Bug 19906 reported in July 2008). The keyLocation attribute is
always 0 or 3, so it does not distinguish between left and right
modifier keys.
Konqueror returns keyIdentifier values like "Shift" and "Enter"
correctly, but instead of returning the Unicode values, it returns the
typed character itself, "a" or "A" instead of "U+0041". All
keyLocation values are zero, except for modifiers key, which are
always one, regardless of whether the left or right one was pressed.
We cannot, however expect any more browsers to implement that
standard, since it has now changed. The DOM 3 standard no longer
mentions event.keyIdentifier or event.keyLocation. Instead we have
event.key, event.char, event.location.. So far as I know, no browser
has yet implemented this new version of the DOM 3 standard.
In this standard event.char is defined only when you type a printable
character, or another character with a defined code (like tab or
backspace). It's basically like event.charCode except that it is the
character, not the character code and can be any unicode character not
just an ASCII code. Event.key is the same as event.char for printable
keys. For other keys, even ones like tab or backspace that have
character encodings, it is a string like 'Tab', 'Left' or 'F9'. These
values are supposed to be the same on keypress events as they are on
keyup and keydown events, though keypress would not be fired for those
cases where event.char is null.
Note that neither of these pretends to be a keycode identifying a
particular physical key on the keyboard. If you press the /? key on a
US keyboard while shift is off, but press the shift key before
releasing the /? key, then then on keydown you'll get event.key=='/'
and on keyup you'll get event.key=='?'. The only way your Javascript
program will know that those two events go together is if it happens
to know that those two characters are on the same key. There is an
event.locale value that is supposed to give you some clue on what type
of keyboard is being used, but figuring out what keys go with what on
a particular keyboard is up to you.
Clearly this abandonment of the idea of keycodes is going to cause
problems, but is still probably justified. In many (most?) operating
systems, I don't think the browser can actually tell which key was
pressed. In the browser source code I've seen, the keycodes are
generated from the the character codes, not vice versa, by simply
assuming that the character came from a US keyboard. So the keycode
values never really worked for non-US keyboards.
So while the keycode concept was a handly one, it isn't really
practically extensible in the real world. If you want a keycode in the
DOM 3 universe, you'll have to go on using the legacy event.keyCode
value, which, standards or no standards, isn't going away. The DOM 3
standard seems to recognize this, and reluctantly provides an appendix
with some standards for event.keyCode and the like. It casts a rather
weak vote for what I called "IE keycodes" above.
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>
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
});
I have a form field for entering a user id. The user id is always 6 characters so the field is limited to a maxlength of 6 characters.
The field has an onkeyup() event to call a function that looks up the user id and fills in several other form fields if the user id is valid. Most people I know have used onblur() for something like this but I never liked how a user has to tab to or click on another field before the autofilling AJAX goes off.
The function right now will return w/o doing anything if the field length is < 6 characters or if the key that was pressed is a left or right cursor field.
There's one flaw left I haven't been able to think around. Since the field is limited to 6 characters, if 6 characters are already entered and another key is pressed, the value of the field will not change but the function will fire and validate the field (un-necessary validation/db-query).
Is there anyway to prevent the function from going off in this case? I'm thinking it's not possible but wanted to check. I had a thought if the field length was 6 I could check the last key pressed against the 6th character of the field, but if someone typed something like 'a' as the 6th character and then 'a' again, it wouldn't work. I guess that could eliminate all possibilities except for the one case though one case (not perfect but better).
(rails) <%= f.text_field :uid, :size => 10, :maxlength => 6, :class => 'validate_text', :onkeyup => uid_lookup (event)', :autocomplete => :off %>
<script type="text/javascript">
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
}
</script>
<script type="text/javascript">
uid_lookup = function(e){
var unicode=e.keyCode? e.keyCode : e.charCode;
if (unicode == 37 || unicode == 39) { // ignore a left or right arrow press
return
}
var uid= $('uid').value;
uid = uid.trim();
$('uid).value = uid; //uid's have no spaces, go ahead and remove if typed
if (uid.length != 6) {
return
}
// db lookup & form autofill
}
</script>
The solution is not to use onkeyup. The correct event to use is HTML5's oninput, which is supported by almost every major browser out there. The one browser lacking support is—of course—Internet Explorer 8, but we can emulate the event using IE's proprietary onpropertychange event which will fire whenever an input element's value property changes.
I'm not familiar with rails, but the best way to apply the event is using JavaScript so that you can gracefully degrade if oninput isn't supported:
var el = document.getElementById("myEl");
// Check support
if ("onpropertychange" in el && !("oninput" in el)) {
el.onpropertychange = function () {
if (event.propertyName == "value")
uuid_lookup.call(this, event);
}
}
else
el.oninput = uuid_lookup;
The other great thing about this event is that it only fires when the value changes - much like onchange but more real-time. This means you can do away with your key detection for left and right arrows in the uuid_lookup function.
Can you not use another variable to store the previous value of the field the last time the validation function was fired? Then you can simply return if uid.value = lastValue.
Not perfect, but it would save some processing.