Detect decimal (dot) key from numeric keypad - javascript

I need to detect whether the user has pressed the dot key in the numeric keypad. I've written this first draft that works for me:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript"><!--
(function($){
var knownCodes = [
[110, 46], // Firefox, IE, Chrome
[78, 46] // Opera
];
var pressedCodes = [null, null];
$.fn.comma = function(){
this.live("keydown", function(e){
pressedCodes = [e.which, null];
}).live("keypress", function(e){
pressedCodes[1] = e.which;
for(var i=0, len=knownCodes.length; i<len; i++){
if(pressedCodes[0]==knownCodes[i][0] && pressedCodes[1]==knownCodes[i][1]){
$("#log").append("<li>Decimal key detected</li>");
break;
}
}
});
return this;
};
$(function(){
$('<ol id="log"></ol>').appendTo("body");
});
})(jQuery);
jQuery(function($){
$(".comma input:text, .comma textarea").css("border", "1px solid black").comma();
});
//--></script>
</head>
<body>
<form action="" method="get" class="comma" size="20">
<p><input type="text"></p>
<p><textarea rows="3" cols="30"></textarea></p>
</form>
</body>
</html>
However, I can only test it in a Windows XP box with a Spanish keyboard. My questions are:
Is it safe to read from e.which? I'm using it because both e.keyCode and e.charCode return undefined in at least one browser.
Does the operating system affect these numeric codes in some manner or it's only a browser stuff?
Do these codes depend on the keyboard layout?
Background info: I couldn't find a jQuery plugin to remap numeric keypad so I'm writing my own.
Update
I'll explain my exact need. Spanish keyboards that have a numeric keypad feature a . key. However, the decimal separator in Spanish is ,. That makes it annoying to type numbers in web applications. Some desktop apps like MS Excel remap this key so it inserts a comma. I'm trying to mimic that.
I've adapted a little script I've been using to post it here. That's how I got the values for the knownCodes arrays:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript"><!--
(function($){
$.fn.showKeyCodes = function(){
var log = function(e){
$("<li></li>").text(e.type + "(): [keyCode, charCode, which]=[" + e.keyCode + ", " + e.charCode + ", " + e.which + "]").appendTo("#log");
}
this.live("keydown", function(e){
log(e);
}).live("keypress", function(e){
log(e);
}).live("keyup", function(e){
log(e);
});
return this;
};
$(function(){
$('<ol id="log"></ol>').appendTo("body");
});
})(jQuery);
jQuery(function($){
$(".showKeyCodes input:text, .showKeyCodes textarea").css("border", "1px solid black").showKeyCodes();
});
//--></script>
</head>
<body>
<form action="" method="get" class="showKeyCodes" size="20">
<p><input type="text"></p>
<p><textarea rows="3" cols="30"></textarea></p>
</form>
</body>
</html>
Type the . key in your numeric keypad (or whatever key replaces it in your keyboard layout) and the key that corresponds to the same character in the alphabetical keypad. The goal is to detect you clicked the first one and not the second one.

Is it safe to read from e.which?
Normally in IE no, you only get keyCode (though on keypress it's actually a character code not a key code). Your code can read which because behind the scenes jQuery copies the keyCode value into which on IE. Without jQuery, you need property-sniffing code to know which one to pick. (You can't always read keyCode on keypress because it's not guaranteed to be provided and it's 0 on Firefox.)
Please note I don't want to detect a character: I want to detect a key.
You can't do that in keypress, which only gives you a character code (46, ASCII for .). You would instead have to trap keydown, which gives you access to a real key code (in the keyCode property, and also in browsers that aren't IE, in which).
The keyCode reported for the numeric keypad ./, button is 110 (ASCII for lower-case N). Except on opera where it's 78, ASCII for upper-case N and thus indistinguishable from pressing the N button.
So you could claim the keydown event and store a flag when key 110 or 78 was being depressed, then claim keypress. If the flag from the last keydown was set and the which (charCode) property is 46, return false to prevent the keypress going through, and then insert a , at the focus point instead. (This isn't quite reliable if there are multiple keys being pressed at once and autorepeat going on, though.)
Note that inserting a character at focus is itself non-trivial; see many previous questions here. You'll need branching code for IE (document.selection.createRange().text=...) and other modern browsers (changing the input's value based on selectionStart/selectionEnd). Older and mobile or niche browsers may not support either method of editing, so detect the lack of these properties and leave the keyboard alone if you can't do it.
Does the operating system affect these numeric codes in some manner or it's only a browser stuff?
Do these codes depend on the keyboard layout?
In general yes, though not in a way that will affect you here. Key events are in general still hugely variable cross-browser, cross-keyboard and cross-platform; they are best avoided if you can.
Personally I think the proper solution to a bad keyboard layout choice like Spanish's numpad decimal point would be to modify the layout using MSKLC.

Your code doesn't do anything on my end, so I'd say it probably does depend on keyboard layout. A quick check confirms that the output on my finnish qwerty keyboard is keycode 44, instead of the expected 46.

Some time after asking this question, I finally found a jQuery plugin that does exactly this: numpad-decimal-separator

Related

Why does CraftyJS/Chrome limit the number of concurrent key press events?

I'm trying to develop a game using CraftyJS. I'm using
Crafty 0.7.1
Chrome 50.0.2661.94
Windows 10
A 2016 Dell XPS15.
I'm noticing some oddities in how keyboard events are being handled.
I'm guessing that a lot of this has to do with Chrome or maybe even
my physical keyboard, and that Crafty is only relevant in that I'm
using it's API.
First, here's my SSCCE. This code adds a key to the keys array when it's pressed, removes it when it's released, and logs out the array every second.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>keyTest</title>
<script src="../crafty.js"></script>
<script>
window.onload = function(){
Crafty.init(window.innerWidth, window.innerHeight, document.getElementById('game'));
var keys = [];
var keyDown = function(e){
console.log("KeyDown " + e.key);
keys.push(e.key);
};
var keyUp = function(e){
console.log("KeyUp " + e.key);
keys.splice(keys.indexOf(e.key), 1);
};
Crafty.e("Keyboard").bind("KeyUp", keyUp).bind("KeyDown", keyDown);
Crafty.e("Delay").delay(function(){console.log(keys)}, 1000, -1);
};
</script>
</head>
<body>
<div id="game"></div>
</body>
</html>
I'm noticing some odd behavior:
First, It looks like Crafty will only recognize four letter-key presses at once, unless they can be typed using both the right and left hand. For example holding down ASDFE at once results in: [65, 83, 68, 70] The E key remains unrecognized no matter how much I bash on it. But, if for example I hold down ASDFJKL, then I see: [65, 83, 68, 70, 74, 75, 76].
Only two arrow keys will be recognized at once unless the third one is the down arrow. For example pressing LEFT, UP, RIGHT results in: [37, 38] But LEFT DOWN RIGHT results in: [37, 39, 40]
What on earth is up with this? My guess is that someone between my fingers and my JS is trying to cleverly correct for errant key presses (typos), but I don't know who, and I don't know what rules govern this.
EDIT: I suspect that it's my keyboard itself (or the OS) that is failing to send these keyboard events. But I'm still looking for a good way to confirm this.
As #David has figured out, the issue is called keyboard ghosting:
"Ghosting" is the problem that some keyboard keys don't work when multiple keys are pressed simultaneously. The key presses that don't show up on the computer or seem to have disappeared are said to have been "ghosted". On most keyboards, even some that are explicitly marketed as "Anti-Ghosting," this happens with many three key combinations. Imagine playing your favorite video game and not being able to, say, run diagonally and fire your weapon at the same time (say pressing a, w, and g simultaneously). This is a result of the internal design of most existing keyboards...
Since not every consumer has a gaming keyboard (which particularly don't suffer from this issue), I guess the only thing you can do is to design your game around not requiring pressing three or more keys at the same time.

Is it possible to generate a virtual keyboardEvent (tab) in IE8 with Javascript

I want to generate a virtual keyboardEvent(tab). I did some research on the same and got few usefully answers, however it not working for me. I understand that Javascript is event driven programming language so User should press require key, but I also want to understand that can we generate an keyboard event through JavaScript.
function fnGenerateTabKeyEvent() {
var e = document.createEventObject("KeyboardEvent");
e.keyCode = 9; // tab's ASCII
document.getElementsByName("someTxtBox").fireEvent("onkeyup", e);
}
<input type="text" id="someTxtBox"/>
It's not working in IE8 and I'm not getting any error either. I just want that whenever I can this function it should an keyboardevent(tab) from that text box.
Source1,Source2. Any suggestion will be helpful.
I think you were too hasty, as your code works on my machine:
<html>
<body>
<input type="text" id="someTxtBox" onkeyup="window.alert(event.keyCode)"/>
<script type='text/javascript'>
function fnGenerateTabKeyEvent() {
var e = document.createEventObject("KeyboardEvent");
e.keyCode = 9; // tab's ASCII
document.getElementById("someTxtBox").fireEvent("onkeyup", e);
}
fnGenerateTabKeyEvent();
</script>
</body>
</html>
There're of course some "issues" (like - accessing elements via getElementsByName, maybe having the script called before the <input>, but let's blame that on copy-pasting ;)) As such, on my IE, running in document mode 8 the alert successfully displays 9.

how to predict if DOM keydown will cause a character input

Given a keydown event in the browser, how can I predict whether that key event will result in character input? For example, hitting the left arrow doesn't input characters but hitting the a key inputs an A (unless ctrl or alt is down).
I don't need to know what character will be input, just whether the key event will result in an input.
I'm targeting Chrome. Bonus points if your solution works in an IME.
Note: I'm asking about the keydown event, not a downstream event like keypress or oninput.
There's an HTML 5 event: input. MDN: https://developer.mozilla.org/en-US/docs/Web/Reference/Events/input. Other than that there's no proper solution.
Ok, I think I have a solution. I don't know how good it is but it works. Have a look: http://jsfiddle.net/tLPsL/
It's basically saving the value of the input onkeydown and checking it in onkeyup.
$('#sattar').keydown(function() {
window.SATTAR = $(this).val();
});
$('#sattar').keyup(function() {
if(window.SATTAR !== $(this).val()) {
alert("changed");
}
});
[updated]
use this
$(document).keydown(function(event){
console.log(event.which);
});
and filter the value of the event.which according to your needs using the ascii values and exclude the numbers that appear with unwanted buttons
for example (this example demonstrates accepting small letters only):
$(document).keydown(function(event){
var x = event.which;
if (x <= 90 && x >=65) console.log('accepted');
else console.log('not accepted');
});
JSFiddle
[update] :
If you don't like this method you can use another that detects an input to any textfield or textarea :
$('input,textarea').change(function(){
console.log('input detected!');
});
$(document).keyup(function(event){
var x = $(event.target);
if (x[0].nodeName == 'INPUT' || x[0].nodeName == 'TEXTAREA'){ //you can filter the backspace if you don't want to consider it a change on the input by anding it with the whole argument here using the key number explained above
x.blur().focus();
}
});
DEMO
note: The first method works for all languages as the same keyboard keys are used for inputs of different characters but they still can type.
Sources && tips:
I saw the characters keydata list in this site.
-To make it crossplatform and crossbrowser, I suggest you to watch this site
-You can test the keydown event here.
-Jquery also suggest to use key which because it normalizes keycode and charcode (i think this can be usefull for the crossbrowser part but I didn't find a table like the one I posted before for keycode), see details here.
To the end, a personal thought: I wouldn't appear rude by telling this so please, try to understand, you had 3 clear and working answer, should be your interest to improve details to make it working as you need, especially because, for many reason, (like time, hardware disponibility, no one pay us, freelancer site is elsewhere, etc etc), who are helping you, maybe, can't do your entirely work.
EDIT
Considering your needs, I wrote this code, keeps in mind that combination key are hard to handle, so, you should test this example before to re-use it. fiddle
<!DOCTYPE html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
$(document).keydown(
function(event){
if(event.target!='[object HTMLBodyElement]'){//Are we in an input?
if(!event.ctrlKey && !event.altKey){//Are we using a combo ctrl or alt?
if(event.keyCode==13 || event.keyCode==8 || event.keyCode==32 || (event.keyCode>45 && event.keyCode<91) || event.keyCode==188 || (event.keyCode>189 && event.keyCode<193) || (event.keyCode>218 && event.keyCode<222)){
//It is a char?
document.getElementById('valid').innerHTML+=event.keyCode+' ';
document.getElementById('idlast').innerHTML=event.target.id;
}
}
}
}
);
</script>
</head>
<body>
<input id="a" type="text"></input>
<textarea id="b">a</textarea>
<div id="c" contenteditable="true">a</div>
<div id="d" style="width:200px;height:200px;background-color:red">a</div>
last keydown in: <span id="idlast"></span><br>
for keypress in input:<span id="valid"></span><br>
</body>
</html>
END EDIT
For first if the focus is on an object that is not an input(textarea,contenteditable...) you are targeting the body. So if the target is the body, for sure you are not writing somewhere.
Then I suggest you to see this example, keypress is probably usefull for your aim, because it seems to don't register keys that aren't an input.
<!DOCTYPE html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
$(document).keypress(
function(event){
if(event.target!='[object HTMLBodyElement]'){
document.getElementById('valid').innerHTML=document.getElementById('valid').innerHTML+event.keyCode+' ';
document.getElementById('idlast').innerHTML=event.target.id;
}else{
document.getElementById('out').innerHTML=document.getElementById('out').innerHTML+event.keyCode+' ';
}
}
);
$(document).keydown(function(e){document.getElementById('down').innerHTML=document.getElementById('down').innerHTML+e.keyCode+' ';});
</script>
</head>
<body>
<input id="a" type="text"></input>
<textarea id="b">a</textarea>
<div id="c" contenteditable="true">a</div>
<div id="d" style="width:200px;height:200px;background-color:red">a</div>
last keypress input id: <span id="idlast"></span><br>
for keypress in input:<span id="valid"></span><br>
for keypress out:<span id="out"></span><br>
for keydown:<span id="down"></span><br>
</body>
</html>

Multiple key presses in JavaScript only working in IE

I have the following code:
function handle_paste_keydown(key)
{
if(key.keyCode == 86 && key.ctrlKey) // Ctrl + V
{
alert("Test...");
}
}
This works in IE, but none of the other browsers. My reason for doing this is that I have finished creating a rich-text editor, but I need to handle the onpaste event carefully because formatted text is able to make it in to my editor, which could pose a minor risk to security, but also butchers my layout if malicious <span>s and <div>s make it in.
My current method is to give focus to an off-screen textarea, which means all code will be pasted in to that (which removes formatting); then I immediately grab the textarea.value and insert it at the current caret position in my contentEditable <div>.
So anyway, how do I get the Ctrl+V to work in all browsers and why doesn't it work in its current state?
Thank you.
If it works in IE but nowhere else you did something wrong.
Use the keypress event rather than keydown.
http://jsfiddle.net/Lxvgr/1/
document.getElementById('foo').onkeypress = function(e) {
if(e.charCode == 118 && e.ctrlKey) alert('pasted');
};
#Eric Sites: "use jQuery" isn't the answer to every javascript question. including an entire external framework to solve a simple 4byte issue like this is ridiculous.

Forcing Javascript keyboard event inside a textarea on IE

I'm trying to force a keypress inside a textfield using Javascript. This has to work specifically on IE but it simply doesn't work.
Can anyone help me?
My test script is this one:
<html>
<body>
<input type="text" id="txtfld">
<input type="button" onclick="go()">
<script>
function go() {
var q = document.getElementById('txtfld');
q.style.backgroundColor='yellow';
q.focus();
var evObj = document.createEventObject();
evObj.keyCode = 84; // [T] key
q.fireEvent('onkeypress', evObj);
}
</script>
</body>
</html>
It's not a good idea to try to drive browsers' default-event-actions by faking events. In as much as it can be done at all it is browser-specific and unreliable.
If you want to add a letter ‘t’ to the field, say so:
q.value+= 't';
In more complicated cases like if you want to insert a letter at the current cursor position, you need branching code for document.selection (IE) and field.selectionStart/End (others).

Categories