Mootools: numpad keyup and keydown events returns different key values on the same key - mootools

Can anyone shed some light on why numpad keyup and keydown events return different key values?
Consider this:
<input type="text" />
<script>
document.getElement('input').addEvents({
'keydown':function(e){
console.log('keydown: code:' + e.code + ', key:' + e.key);
},
'keyup':function(e){
console.log('keyup : code:' + e.code + ', key:' + e.key + '\n');
}
});
</script>
I was expecting each event to return the same key value for both keydown and keyup but instead, I got the output below (after pressing 0,1,2,8 and 9):
keydown: code:96, key:0
keyup : code:96, key:`
keydown: code:97, key:1
keyup : code:97, key:a
keydown: code:98, key:2
keyup : code:98, key:b
keydown: code:104, key:8
keyup : code:104, key:h
keydown: code:105, key:9
keyup : code:105, key:i
Normally I would use keypress, and as such, have never had any problems. I came across this when highlighting numpad representative buttons on the screen when the corresponding numpad key was pressed on the keyboard (highlight on down, and remove highlight on up).
Any ideas?

There is a big mess in how different browsers implement keydown, keypress and keyup events, even the keyCode values in keydown and keyup events are not yet standardized across browsers.
Currently the event object has three properties that contain information about the pressed key:
charCode - the Unicode value of a character key pressed
keyCode - a number representing the key that user pressed
which - the keyCode or charCode number for an alphanumeric key pressed
The value of pressed key is stored in either keyCode or charCode property, but never both, keyCode is always set in the keydown and keyup events, charCode is set in the keypress event.
So, for example, if you press 'e':
keydown and keyup reports:
charCode=0, keyCode=69, which=69 - caracter at number 69 is capital letter E
keypress reports:
charCode=101, keyCode=0, which=101 - caracter at number 101 is small letter e
And if you press number 9 in numpad:
keydown and keyup reports:
charCode=0, keyCode=105, which=105 - caracter at number 105 is small letter i
keypress reports:
charCode=57, keyCode=0, which=57 - caracter at number 57 is digit 9
Mootools
Mootools tries to standardise things by adding event.code and event.key properties:
event.code = event.which || event.keyCode;
event.key = String.fromCharCode(code).toLowerCase();
It also converts keyCodes for the numbers on the numpad, but only for keydown event ( version 1.4.5 ), and not for keyup. I don't know if this is intentionally or not, but keyup event can be easily modified to have the same behaviour by replacing the line 1163 in mootools-core-1.4.5-full-nocompat.js from:
if (type == 'keydown') {
to:
if (type == 'keydown' || type == 'keyup') {
That way keyCodes in keyup event will be also converted.
Interestingly, the Mozilla Developer Network says:
'charCode', 'keyCode' and 'which' is deprecated, you should use 'char' or 'key' instead, if available.
But I don't see that implementation in Firefox or Chrome yet. And jQuery adds ‘key’ property to an event object, but it is always 'undefined' ( probably depends on browser implementation ).

Use e.code rather than e.key when listening to keydown and keyup events. e.key is only reliable with keypress events.
See:
http://mootools.net/docs/core/Types/DOMEvent
http://www.quirksmode.org/js/keys.html

Related

navigate buttons using arrows in html [duplicate]

I've noticed an problem when trying to catch keyboard shortcut: CTRL + an arrow.
I've handled keydown event. Now when I hold CTRL key then keydown event is fired once. If I hold an arrow (so that now I'm holding CTRL + an arrow) it doesn't fire another event. Is it forbidden from any reason? I guess I've already encountered this problem in Opera a few years ago and there was an option for it in browser.
My results:
holding CTRL, press an arrow -- fires event for CTRL and doesn't fire an event for an arrow
press CTRL + an arrow at once -- fires one event but only with keycode of CTRL.
holding CTRL, press a letter (eg. S) -- works as expected
press CTRL + letter (eg. S) -- works as expected
(Results are identical in Chrome and Firefox. Is the behaviour described above a standard?)
I'm using:
function OnKeyDown(e) { }
e.ctrlKey, e.which properties of event
The question is: what might be the problem?
You should check if the event.ctrlKey flag is true, something like this:
document.getElementById('element').onkeydown = function (e) {
e = e || window.event;
var keyCode = e.keyCode || e.which,
arrow = {left: 37, up: 38, right: 39, down: 40 };
if (e.ctrlKey) {
switch (keyCode) {
case arrow.left:
//... handle Ctrl-LeftArrow
break;
//...
}
}
};
Check an example here.

Action Script 3, How to disable keys?

If there's too many functions, so It is very hard to "removeEventListener" each one,
Is there any way to disable all keys temporarily?
Thank you.
"Is there any way to disable all keys temporarily?"
Can you not just use .removeEventListener(KeyboardEvent.KEY_DOWN...?
Either your Stage or some MovieClip is listening for key press event, right? eg:
stage.addEventListener(KeyboardEvent.KEY_DOWN, handle_KeyPress);
Where your handle_KeyPress function, which handles all key presses, looks like:
function handle_KeyPress ( evt:KeyboardEvent ) : void
{
//# RIGHT ARROW or numpad 6 (arrow)
if ( evt.keyCode == 39 || evt.keyCode == 54 || evt.keyCode == 102)
{
//do something if Right arrow
}
//# SPACE BAR
if ( evt.keyCode == 32)
{
//do something if Space bar
}
}
PS:
Show an example of code with "too many functions" (eg: give small example how they're spread out it). It's possible you need to re-think / re-structure your code if it's not currently flexible.
If your goal is just to temporarily "pause" the event handlers, you could throw in a simple boolean:
var eventsHandled:Boolean = true;
And inside the event handler functions you would use it as a condition:
function buttonClicked(evt:KeyboardEvent):void{
if(eventsHandled){
//do stuff
This is just a simple bandage. VC.One's answer is probably hinting into your actual problem and in some point you'll have to face it.

Redirect ENTER key to different command (AS3)

I have a textbox for which I want the space key to be executed every time a person hits the enter key INSTEAD OF adding an extra line. I am using the following code but to no avail:
txtVerbs.addEventListener(KeyboardEvent.KEY_DOWN, enterkey);
function enterkey(event:KeyboardEvent):void{
if (event.keyCode == 13){event.keyCode == 32}}
Try this:
txtVerbs.addEventListener(KeyboardEvent.KEY_DOWN, enterkey);
function enterkey(event:KeyboardEvent):void{
if (event.keyCode == Keyboard.ENTER){ // you should use the Keyboard constants instead of the hard value
event.preventDefault();
event.stopImmediatePropagation();
txtVerbs.text += ' ';
}
}
stopImmediatePropagation() prevents the event from traveling any further, so it will stop any other KEY_DOWN event further down the line and should (at least from what I remember) stop the KEY_UP from firing as well.
preventDefault() cancels the default behavior of an event, if it is possible to be cancelable. If memory serves, the key being pressed is cancelable. If it isn't, however, you could also do a RegEx replace.
txtVerbs.addEventListener(KeyboardEvent.KEY_UP, enterkey);
function enterkey(event:KeyboardEvent):void{
if (event.keyCode == Keyboard.ENTER){ // you should use the Keyboard constants instead of the hard value
txtVerbs.text = txtVerbs.text.replace(/\r?\n/gm, ' ');
}
}
That should match any newline character (it is \r\n on some systems and just \n on others) and replace it with a space

AS3: Multiple options in one key and preventing multiple key presses

I have a "pause function" in my AS3 code, the problem is that i can't figure the logic necessary to give the letter "P" the capacity to pause and unpause and at the same time limit the number of presses to one at a time. My code so far (working ,yes, but without the "one press at a time" limit).
public function PauseDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.P)
{
pause = true;
trace ("apreté pausa");
pausa();
}
}
public function pausa():void
{
trace ("pausa");
if (pause == true && paused == false)
{
paused = true;
backgroundLvL1.removeEventListener(Event.ENTER_FRAME,update);
}
else if(pause == true && paused == true)
{
paused = false;
backgroundLvL1.addEventListener(Event.ENTER_FRAME,update);
}
}
Your 'PauseDown' function should probably be called something else, because it's going to be called whenever ANY key is pressed; Something like 'keyPressed' is probably more descriptive.
If you want to have only ONE key acknowledged as the most recently pressed key, I would set a variable (eg _currentKeyCode) to the event.keyCode in the 'keyPressed' function. Then, in your game loop function you can check the value of _currentKeyCode and have the game respond accordingly.
In the 'keyPressed' function you could also still include your test to see if 'P' has been pressed.
Note that you should also have a 'keyReleased' function, triggered on a KeyBoardEvent.KEY_UP event. This could check if _currentKeyCode == the event.keyCode and, if so, set _currentKeyCode to -1. Then, in your game loop, -1 would signify no key presses.
One last, slightly irrelevant, thing: In the 'pausa' function you don't need to check if 'pause == true' because the pausa function is only called when pause == true.

AS3 TextField - unwanted carriage return when setting value to ""

I have an input TextField and have a KeyboardEvent.KEY_DOWN even listener on the stage to listen for the Keyboard.ENTER event. The event listener adds the entered text to an array or whatever, and then clears the TextField. The problem is that when the Enter key event fires and the TextField value is set to "", it leaves a carriage return in the TextField and the cursor positioned on the second line. WTF? I've been coding AS2 and AS3 for a LONG time and have never ran into this before. Am I losing my mind? Please help, people! :-)
Example:
var myTextArray:Array = new Array();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
function onKeyDown(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.ENTER){
if(_inputText.text != null){
myTextArray.push(_inputText.text);
}
_inputText.text = "";
}
}
Simply replace KEY_DOWN with KEY_UP. It fixes the problem (for me at least)
Use KEY_DOWN -> Your code -> KEY_UP -> empty Field
An example (nasty code):
Message.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.ENTER)
{
// Your code...
}
});
Message.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.ENTER)
{
Message.text = "";
}
});
If you are able to enter a carriage return, it means the TextField is multiline, isn't?
Have you tried to empty your input text in a KeyboardEvent.KEY_UP event listener callback function?
Are you hitting enter with text field in focus? In that case, it might be that onKeyDown is called before the text field's value is updated by the keyboard action. You set the textfield to empty string in the onKeyDown, and then flash adds a new line to it.
Add a text input event listener to the text field and add trace statements to both event handlers to know the order of events.
If you are in Flash authoring mode (in the IDE), you need to uncheck Control -> Disable Keyboard Shortcuts while testing. Also try making a "cleanup" handler for KEY_UP.
inputfield.addEventListener(Event.CHANGE, onChange);
private function onChange(e:Event):void {
if ( inputfield.text.charCodeAt(inputfield.text.length - 1) == 13 ) {
inputfield.text = inputfield.text.substr(0, inputfield.text.length - 1);
}
}
I know it is a very old question, still thought of sharing my solution. I disabled multiline feature of textbox in fla file. After that I don't get any carriage return in textbox.
This does seem to be some kind of bug - I get it too. If you just set textField.text = "" in your constructor (or where-ever) it seems to resolve the problem.