1

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?

Pavlin Petkov
  • 1,022
  • 3
  • 17
  • 38
  • _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._ this is the intended behavior in every browser and it's by design like that. – briosheje Apr 30 '19 at 09:29
  • Possible duplicate of [How to detect if multiple keys are pressed at once using JavaScript?](https://stackoverflow.com/questions/5203407/how-to-detect-if-multiple-keys-are-pressed-at-once-using-javascript) – briosheje Apr 30 '19 at 09:29
  • @briosheje it is not a duplicate as I have stated in my question that the provided answer there is not what I am looking for. – Pavlin Petkov Apr 30 '19 at 09:30
  • There are more people looking for duplicates than trying to actually answer the question. Jesus... – Pavlin Petkov Apr 30 '19 at 09:31
  • @PavlinPetkov What's wrong with the (correct) duplicates? If there's already an answer, why anybody would have to bother to write a new answer ..? – Teemu Apr 30 '19 at 09:34
  • Because they are old questions and the people who asked them were perfectly happy with the answers they got. It doesn't work for me, there is different use case and different goal in mind, so - I ask another question where I explicitly state that the answers in the other question are not what I am looking for. But as always - there are more people looking for duplicates than trying to help. – Pavlin Petkov Apr 30 '19 at 09:36
  • @PavlinkPetkov Marking a duplicate does not imply that the question **is** a duplicate. In my opinion, it's a duplicate of that question, there will be other persons reading that and trying to answer your question and eventually not marking it as a duplicate or retracting my vote. It's my opinion about that question specifically which, to me, is a duplicate of another, since it relies on the same concept. The events behavior is working as expected. Still, I will (as many other will) of course try to answer your question properly as many of us always do ;) – briosheje Apr 30 '19 at 09:36
  • The emphasis on the word __correct__ ... What comes to the question, the array/object is the way to go, unless you're not going to sit on the keyboard. – Teemu Apr 30 '19 at 09:38
  • 1
    @PavlinkPetkov - to get back on topic - I'm afraid going the array way is your only solution. Maybe you just need to consider the cases it might not update the array properly. What comes into my mind right now is when the browser window loses focus. So maybe just clear the array if that happens. – obscure Apr 30 '19 at 09:42
  • Can't you try something like having a boolean variable to track key down or key up event.When key is pressed making it true and on keyup event make it false. Untill then don't respond to any keydown or keyup event or (event.preventDefault) – Deepankar Singh Apr 30 '19 at 10:05
  • Notice, that in the array/object solution, "the required cycle" is your actual programflow, the events are used to mark the pressed keys in the array/object only, they're not for the program logic. – Teemu Apr 30 '19 at 10:16
  • Okay, is there a way to refresh the `keydown` event? Meaning that after `keyUp` is activated if I have something in the array I could hit `keyDown` again manually and I want it to stay this way as long as `keyUp` is not triggered again (removing the key from the array) – Pavlin Petkov Apr 30 '19 at 12:09
  • Edited the question with new findings and made it more descriptive – Pavlin Petkov Apr 30 '19 at 12:22

0 Answers0