There is a strange behaviour with JS events and in particular keydown
event.
For simplicity I will use jQuery
because with it you can run the code in the console of the browser and investigate the issue.
function keyDown(e){
console.log(`Pressed ${e.key}`)
}
function keyUp(e){
console.log(`Released ${e.key}`)
}
$(document).on('keydown', keyDown)
$(document).on('keyup', keyUp)
If you now copy-paste this into the console of your browser and you hold the button A
for example you will notice how if you hold it - the event is refreshed over and over. That is perfectly fine.
If you were, however, to press and hold another button (lets use B
) you would notice that B
is now refreshing, but A
isn't even though you are holding both.
If you are now to release B
it would say Released B
and no other events would trigger...even though you are still holding A
Then when you release A
it will fire that you released it.
Is there a way to go around this while still using the events
?
Basically I do not wish to have an array to keep all pressed and then whenever something is released to remove it from it. Reason being is that such solution requires a cycle to perform actions constantly until the array is empty. If for whatever reason the array doesn't get emptied - the cycle never stops and this can cause big issues.
So I wish to use the events instead, but in such fashion that the event is triggered until I release the button, no matter how many other buttons I have pressed.
Is there a way to do that?
EDIT - Again, I am not looking for a solution with an array to hold the values and remove them, but to keep the event refreshing for both, so my question in fact is not the duplicate of other questions to which the only answer is that one.
EDIT - So I came up with a solution that uses the array holding all button pressed and came up with this
let pressed = new Set();
function reset(){
let iterator = pressed.values();
if(!iterator){
console.log('Nothing Pressed');
return
}
let firstPressed = iterator.next().value;
if(!firstPressed){
return;
}
let e = jQuery.Event('keydown');
e.key = firstPressed;
$(document).trigger(e)
}
function trigger(){
pressed.forEach(key => {
let e = jQuery.Event( 'keyhold', {pressed: key});
$(document).trigger(e)
})
}
function keyDown(e){
let key = e.key ? e.key : e;
console.log(`Pressed ${key}`);
pressed.add(key);
trigger()
}
function keyUp(e){
console.log(`Released ${e.key}`);
pressed.delete(e.key);
}
function keyHold(key){
console.log(`Pressed ${key.pressed}`);
}
$(document).on('keydown', keyDown);
$(document).on('keyup', keyUp);
$(document).on('keyhold',keyHold);
The improvement here is that if you press A
and then S
now the event for S
will also call A
but with custom event so it wont overlap and create stackoverflow (hue hue hue).
So the console should look like
* Presses A *
Pressed A
Pressed A
* Presses S *
Pressed S
Pressed A
* Releases A *
Released A
Pressed S
...
Pressed S
* Releases S *
Released S
However if I was to Press A
and then S
and then stopped pressing S
- it would stop, even though I am still pressing A
(still in the array as well)
I decided to add trigger()
to keyUp
but that doesn't do it, since that is only fired once.
If I am to manually trigger the event - it wont work and I do need it to be timed by the event.
So - can I trigger keydown
event in such fashion that it continues until another button is pressed?
Basically reseting it as it was before I pressed S
?