'How do I change the value of a boolean property of an object in an array?
I'm super new to coding in general and I'm learning javascript to start with so forgive me if I have the wrong idea about anything. I've done a pretty good job so far at teaching myself basics but I've hit a wall trying to figure out how to detect multiple keypresses at once. I've seen a couple of apporaches to this but it looks like the general idea is to flag keypresses on 'keydown' and 'keyup'. The problem is, I cant figure out how to make my keyBoard['w'].pressed = true.
const keyBoard = {
w: {pressed: false}
}
document.addEventListener('keyDown', (e) => {
keyBoard[e.key].pressed = true
});
if(keyBoard['w'].pressed){
alert("success!")
}
This is a very simple test case I made to get my head around the logic and through trial and error I know the issue is with making my w.pressed be true. I know I need to add a 'keyup' listener to set it to false but for now all I need to know how to do is what's described. Thank you!
Solution 1:[1]
You just need to put your IF statement inside your listener function - AND use 'keydown' not 'keyDown'. Also, I added a line which adds each key pressed into your object.
const keyBoard = {
w: {
pressed: false
}
}
document.addEventListener('keydown', (e) => {
keyBoard[e.key] = keyBoard[e.key] ? ? {}
keyBoard[e.key].pressed = true;
console.log(keyBoard)
if (keyBoard['w'].pressed) {
console.log("success!")
}
});
Solution 2:[2]
First things first, the event you are using has a typo. The proper name is keydown, not keyDown. You can read about it here Document: keydown event
Now moving into you code:
This is not way it is not working, but this will help you in the future. The function for the event lister is looking for a key e.key in your object keyBoard without declaring them first. In JavaScript this is not a problem if your JSON does not have the key, then it will be added. The problem here is that you are trying to add a value of true to an attribute pressed on a key that does not exist. This will raise an error
Cannot set properties of null (setting 'pressed')
To see this, press F12 to open the console in your browser.
Why? Well as mentioned before, the key can be added to object keyBoard, but the type of that key is not defined! when you do keyBoard[e.key].pressed = true you are telling the interpreter that the object keyBoard has an object of the value e.key which is also an object and it has a key called pressed. You need to specify that whatever is going into keyBoard[e.key] is an object. You can solve this as follows:
document.addEventListener('keydown', (e) => {
keyBoard[e.key] = keyBoard[e.key] == undefined ? {} : keyBoard[e.key]
keyBoard[e.key].pressed = true
});
Adding that extra line will specify that keyBoard[e.key] is an object and it will allow you to assign the value of true to the attribute pressed.
Now moving to the actual solution:
Everything in your script gets executed right when the page is loading. This means that your if statement will never be true because you will press any key after load, in other words, after the script has already finished. If you want an alert to pop every time w is pressed then you need to add that as part of the functionality of the event you already created. The event will stay alive even after the script finished listening for keystrokes and performing the code you wrote in it. Here is a way to get what you want. This will popup an alert every time w is pressed.
document.addEventListener('keydown', (e) => {
if (e.key === 'w') {
alert("success")
}
});
Solution 3:[3]
Going step by step through three blocks of your code:
- declaring a constant with an object
- attaching event to the document
- checking the state of the object
It seems to be ok, but attaching an event does not stop code execution until it happens. The main thread goes on so the keyBoard object is not changed in 3th step.
To get it worked it should check the variable in the loop, ie.
setInterval(() => {
if (keyBoard['w'].pressed){
alert("success!")
}
}, 10);
but it is not very needed in this case.
The proper way is to let your code to execute some method every time key is down or up:
const keyBoard = {
w: {pressed: false}
}
document.addEventListener('keydown', e => {
keyBoard[e.key] ||= {};
keyBoard[e.key].pressed = true
doImportantStuff();
});
document.addEventListener('keyup', e => {
keyBoard[e.key] ||= {};
keyBoard[e.key].pressed = false; // or better `delete keyBoard[e.key];`
doImportantStuff();
});
function doImportantStuff() {
console.log(Object.entries(keyBoard));
}
If you want to keep ONLY pressed state for each key your code could be a bit simpler if you omit pressed property:
const keyBoard = {}
document.addEventListener('keydown', e => {
keyBoard[e.key] = true
doImportantStuff();
});
document.addEventListener('keyup', e => {
keyBoard[e.key] = false; // or better `delete keyBoard[e.key];
doImportantStuff();
});
function doImportantStuff() {
console.log(Object.keys(keyBoard).filter(key => keyBoard[key]));
// console.log(Object.keys(keyBoard)); if you delete keys from keyBoard when they up
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Kinglish |
| Solution 2 | |
| Solution 3 |
