function on every keypress - javascript

I want to run the following block on every keypress of right arrow (39):
$(document).ready(function() {
$(document).keydown(function(e) {
var pos = 10;
if (e.keycode = 39) {
if (pos > 10) {
pos + 10;
}
$(".mario").css('left', pos);
}
});
});
The goal is I am setting a variable, pos, and referencing it in a css() method to move it across the screen in increments of 10, every time the key is pressed the expected behavior is on every right arrow key hit, the object moves across the screen in increments of 10.
It works successfully once, then will not continue to increment. My console is empty/free of errors. I have also tried using keypress:
$(document).ready(function() {
$(document).keypress(function(e) {
var pos = 10;
if (e.keycode = 39) {
if (pos > 10) {
pos + 10;
}
$(".mario").css('left', pos);
}
});
});
To elaborate on this, I also want to add an option to check if the left key is pressed and if so, set it back flush against the screen. I went about this by adding the below block under the closing of the first if statement:
else if (e.keycode = 37) {
$(".mario").css('left', '0');
}
I researched on MDN and it simply states: "The keydown event is fired when a key is pressed down." https://developer.mozilla.org/en-US/docs/Web/Events/keydown
Reading that, what I'm not understanding is why is my event only firing once? How come adding a second condition for the left arrow key doesn't register as an event, if the event is fired every time a key is pressed?
See fiddle here: https://jsfiddle.net/c2fr7rsd/1/
EDIT/UPDATE: As many pointed out, I was/am using an assignment operator = and not a comparison === - I initially tried comparison it doesn't work. Assignment - it works, but now all the keycodes register as 39! Howcome in this instance, the comparison operator doesn't reference the keycode?
UPDATE #2 - using e.which is the correct way to handle keydown events, and using the correct comparison === works

The pos variable should be declared as a global.(outside the function).
Right now, each time that function is called, the variable is set back to 10.
Also logic for checking that variable should be
if(pos >= 10)
And setting the variable should be
pos += 10
Also capitalize C in keyCode and the == will work
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
This shows why your logic for if(e.keycode = 39) was returning true
https://www.w3schools.com/js/js_mistakes.asp
Correct code example
$(document).ready(function() {
var pos = 10;
$(document).keypress(function(e) {
if (e.keyCode == 39) {
if (pos >= 10) {
pos += 10;
}
$(".mario").css('left', pos);
}
});
});

Related

addEventListener('keydown') JavaScript bug?

I'm trying to create a game in HTML5 and I've come to the point where I need to enable keyboard input.
So Here's my code:
window.addEventListener('keydown', function(e) {
let key = e.keyCode;
console.log(key);
if (key == 37) {
canvas.player.x -= 5;
}
if (key == 38) {
canvas.player.y -= 5;
}
if (key == 39) {
canvas.player.x += 5;
}
if (key == 40) {
canvas.player.y += 5;
}
}, false);
Where canvas is the canvas object and canvas.player the player object. It works, but not very well... Let's say I'm pressing (and holding down) the right arrow key (39) and than press the down arrow key (40) the player is not moving to the right anymore since we last pressed the down arrow key. Works fine. Until I only release the down arrow key while still pressing down the right arrow key. So I never released the right arrow key. Than the player stops and the browser doesn't seem to understand that I'm pressing the right arrow key.
You can easily see this in the console log of this fiddle.
Does anybody has a solution for this problem? A way to detect the keycode anyways?
Keyboard IO.
Generally IO events like the mouse, touch, and keyboards should only be used to get the current state of the devices they are listening to. The job of reacting to input is done in your game.
one way to handle keyboard input is as follows
// this defines what keys you are listening to and
// holds the current state of the key true for down false for up
const keys = {
ArrowUp : false, // list the keyboard keys you want to listen to
ArrowDown : false,
ArrowLeft : false,
ArrowRight : false,
};
// the event listener listens for key events
function keyEvents(e){
if(keys[e.code] !== undefined){ // check if its a key we are listening for
keys[e.code] = event.type === "keydown" ; // set the state up or down
e.preventDefault(); // stop default action
}
}
addEventListener("keyup",keyEvents); // set up the listeners
addEventListener("keydown",keyEvents);
Then in your game's main loop or called from there check the key state and perform the action that the state requires..
if (keys.ArrowDown) { player.y += 5 }
if (keys.ArrowUp) { player.y -= 5 }
if (keys.ArrowLeft) { player.x -= 5 }
if (keys.ArrowRight) { player.x += 5 }
It may be a bug, I thought that it used keyboard events but on mac it seems to repeat the character when held but when typing normally on a mac holding down a key doesn't do that.
I have done a workaround before using a combination of keydown and keyup to set booleans for each of the keys. Then an interval using something like setInterval which checks each of the booleans for each of the keys. If they are true then I carry out the action for that key.

why is the if statement not working in js

window.addEventListener("keyup", addkey);
function addkey(){
var x = event.which || event.keyCode;
var wkey = 0;
var op = 0;
if(x == 87){
wkey += 1;
}
if(wkey == 1 && op == 0){
alert("your doing good!");
op = op + 1;
}
}
What im trying to get to happen here is getting the alert statement to run once and only once but i cant get it to work either way. I tried using a true or false numberical system (the op variable) but that dident work either. What i see happening is when the code runs and the keyup event fires the wkey variable updates once and stays 1 even know it should be going up a numeral each time the w key is pressed. Anyway i am making this code to go along with a tutorial for the game im making. Any and all suggestions i am open to.
This happens because you re-initialize op to 0 every time the function gets called. You can simply delcare op outside of addkey and it will work:
window.addEventListener("keyup", addkey);
var op = 0;
var wkey = 0;
function addkey(event){
var x = event.which || event.keyCode;
if(x == 87){
wkey += 1;
}
if(wkey == 1 && op == 0){
alert("your doing good!");
op += 1;
}
}
You'll also need to pull the declaration of wkey out of the function if you want to successfully count how many times it was pressed.
That's because you define wkey and op on each function run, you should define them out of the function, to make it work as expected.
Each time the function is called,
wkey gets set to 0,
and then 1 is added,
so it will always end up being equal to 1
Try defining wkey as 0 outside of the function.
Or having
if(wkey == null) var wkey = 0;
instead.
If you use this method op is unnecessary. (Unless of course you're using it's value elsewhere.)

How can I know a 2 last pressed key on a keyboard

Is it possible to know, what 2 last keys was pressed on keyboard?
How can I do it?
I need to compare this keys, and if they are the same - make some function.
As example, if someone press Enter - this is a first function, if after Enter he press a SPACE- this is a second function. If after the ENTER he press a Ctrl - this is a third function.
So, I hink that only onw way to do it - is make a 2 var with current and previous key value, and make a IF ELSE IF function
:-)
This is a way, how I get a current key value
$('#text').keydown(function(event) {
$('#show').text(event.keyCode);
});
Or, the BETTER question! (I saw it right now)
Directly in this editor, after I press doublespace - it jump to anothe line in live-preview.
How it works? I'm not sure, but I thinks that I need is almost the same.
Thank you very much!
I think storing the last key pressed and checking both the old and new keyCode in the event handler is a good way to do this.
$('#text').keydown((function() {
var lastKey = undefined;
return function(event) {
// here you have both the old and new keyCode
lastKey = event.keyCode;
};
})());
Also, the two spaces thing is Markdown interpretation.
You could start with a very simple jQuery plugin:
(function($) {
$.fn.keyWatcher = function() {
return this.keydown(function(evt){
var $this = $(this);
var prevEvt = $this.data('prevEvt');
$this.trigger('multikeydown',[prevEvt,evt]);
$this.data('prevEvt',evt);
});
};
})(jQuery);
This will raise a new event (multikeydown) whenever a keydown event is usually raised. This will either provide just the keydown event from the current key press, or if there is a previous one it will provide that too.
Usage could be something like:
$(document).keyWatcher().bind('multikeydown',function(evt,prevKey,currKey){
alert('prevKey = ' + ((prevKey) ? String.fromCharCode(prevKey.keyCode) : '(none)'));
alert('currKey = ' + String.fromCharCode(currKey.keyCode));
});
Live example (press keys on the lower right hand pane in jsfiddle): http://jsfiddle.net/9VMUy/1/
The event provided in prevKey and currKey parameters to the event handler contain the original keydown events, so you have full access to the keyCode, the ctrlKey and shiftKey properties etc.
This is probably not the best solution but see if you can use it or parts of it
jsFiddle
var clicks = 0
$("#text").one("keypress", function () {
clicks = 1;
var KeyCode1 = event.keyCode;
$('#result').text(KeyCode1);
$("#text").one("keypress", function () {
clicks = 2;
var KeyCode2 = event.keyCode;
$('#result').text(KeyCode1 + "\n" + KeyCode2);
});
});

More efficient to check if a variable is set, then set it, or just constantly set it?

Making a game... More efficient to do this?
if (37 in keysDown) { //left arrow
if (sprite.state != 'left') sprite.state = 'left';
}
or this?
if (37 in keysDown) { //left arrow
sprite.state = 'left';
}
This is being called in my game's update function (constantly, as fast as possible).
Sidenote:
here is my input key checking code.
//input
var keysDown = {};
window.addEventListener('keydown', function(e) {
keysDown[e.keyCode] = true;
});
window.addEventListener('keyup', function(e) {
delete keysDown[e.keyCode];
});
"We should forget about small efficiencies, say about 97% of the time: Premature optimization is the root of all evil."
http://c2.com/cgi/wiki?PrematureOptimization
Those two ways share the same complexity, setting\changing a four chars variable won't be the bottle-neck in your app.
The only things I'm concerned here is the readability of your code, if either way you want sprite.state to have the value left why do you need to check what was the previous value?
(ohh, and it saves like 20 bits of bandwidth which is just like the performance gain here...)
Wouldn't something like this be a lot faster than looping through the keys? You can continuously check a variable very quickly.
var keyleft=false;
window.onkeydown = keydown;
window.onkeyup = keyup;
function keydown(event)
{
var keyCode = ('which' in event) ? event.which : event.keyCode;
if (keyCode==37) keyleft=true;
}
function keyup(event)
{
var keyCode = ('which' in event) ? event.which : event.keyCode;
if (keyCode==37) keyleft=false;
}
No guarantees this code will work, I've forgotten how to do things without jQuery

Keys pressed at the same time

Can I know the number of keys pressed at the same time in Javascript?
If so, how can I have an array of their keyCode?
You can listen for keydown and keyup events.
var keys = { length: 0 };
document.onkeydown = function(e){
if(!keys[e.keyCode]) {
keys[e.keyCode] = true;
keys.length++;
}
}
document.onkeyup = function(e){
if(keys[e.keyCode]) {
keys[e.keyCode] = false;
keys.length--;
}
}
Then all the keys that are true are the ones that are pressed currently.
Fiddle demo thanks to #Esailija: http://jsfiddle.net/maniator/Gc54D/
This should do the trick. It is similar to Neal's, but should fix a few issues, including the leaving-the-window bug and the negative-numbers-of-keys bug. I also streamlined the message writing code a bit. I replaced the timer loop for writing the number of keys message with an on-demand system, added a safety mechanism for decrementing the length index, and added the clearKeys to switch all keys to up when the user leaves the window. The code still has two bugs: it will not recognize keys that are still held down after a new window has been opened and closed (they must be released and re-pushed), and I can't get it to recognize more then six keys (I suspect this isn't related to this code, but the computer/browser...).
var keys = {
length: 0
};
window.onkeydown = function(e) {
if (!keys[e.keyCode]) {
keys[e.keyCode] = true;
keys.length++;
document.body.innerHTML = "You are pressing " + keys.length + " keys at the same time.";
}
}
window.onkeyup = function(e) {
if (keys[e.keyCode]) {
keys[e.keyCode] = false;
if (keys.length) {
keys.length--;
}
document.body.innerHTML = "You are pressing " + keys.length + " keys at the same time.";
}
}
function clearKeys() {
for (n in keys) {
n = false
};
keys.length = 0;
document.body.innerHTML = "You are pressing " + 0 + " keys at the same time.";
}
document.body.innerHTML = "You are pressing 0 keys at the same time.";
window.onblur = clearKeys;
Since you want the number of keys pressed at the same time and an array of their key codes I suggest you use the following function:
var getKeys = function () {
var keys = [];
window.addEventListener("blur", blur, false);
window.addEventListener("keyup", keyup, false);
window.addEventListener("keydown", keydown, false);
return function () {
return keys.slice(0);
};
function blur() {
keys.length = 0;
}
function keyup(event) {
var index = keys.indexOf(event.keyCode);
if (index >= 0) keys.splice(index, 1);
}
function keydown(event) {
var keyCode = event.keyCode;
if (keys.indexOf(keyCode) < 0)
keys.push(keyCode);
}
}();
When you call getKeys it will return an array of all the keys pressed at the same time. You can use the length property of that array to find the number of keys pressed at the same time. Since it uses addEventListener it works cooperatively with other code on the page as well.
I tested the above function and it always returns the correct keys pressed even when you switch to another window while holding down a key (it removes that key from the array). If you hold a key and switch back then it recognizes that a key is pressed and it pushes in onto the array. Hence I can testify that there are no bugs in the above code. At least not on the browser I tested it on (Opera 12.00).
I was able to press 8 keys at the same time (A, S, D, F, J, K, L and ;). This number seems OS specific as I can only press 4 left hand keys and 4 right hand keys at the same time. For example after I press A, S, D and F, and then I press another left hand (let's say G) then it won't recognize the last key. This is probably because the OS knows how humans type and so it only allows four interrupts for each of the left and right hand keys. The OS I am using is Ubuntu 12.04.
You can see the code in action on this fiddle. I used a Delta Timer instead of setInterval to display the results after every 50 ms. You may also wish to read the following answer as well.

Categories