2

I'm trying to create this event to navigate through the website with arrow keys. The problem that I'm facing is that if someone holds one of the keys, the function (in this case console.log) will trigger repeatedly which may cause some undesirable behaviour with complex functions.

I want console.log to be triggered only once for each keydown.

window.addEventListener('keydown', function (e) {
    switch (e.key) {
        case 'ArrowLeft':
            console.log('left');
            break;
        case 'ArrowRight':
            console.log('right');
            break;
    }
});

I ended up using this:

let allowKey = true;

window.addEventListener('keydown', function (e) {
    switch (e.key) {
        case 'ArrowLeft':
            if (allowKey) {
                console.log('Left');
                allowKey = false;
            }
            break;
        case 'ArrowRight':
            if (allowKey) {
                console.log('Right');
                allowKey = false;
            }
            break;
    }
});
window.addEventListener('keyup', function(e) {
    switch (e.key) {
        case 'ArrowLeft':
            allowKey = true;
            break;
        case 'ArrowRight':
            allowKey = true;
            break;
    }
});

Thank you.

Aziza Kasenova
  • 1,501
  • 2
  • 10
  • 22
Eloi
  • 323
  • 1
  • 7
  • 16
  • 4
    Check for [`!e.repeat`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat). – Sebastian Simon Mar 31 '21 at 13:21
  • 1
    Does this answer your question? [Prevent JavaScript keydown event from being handled multiple times while held down](https://stackoverflow.com/questions/6087959/prevent-javascript-keydown-event-from-being-handled-multiple-times-while-held-do) – Sebastian Simon Mar 31 '21 at 13:22
  • e.repeat doesn't work for me, it looks like the OS occasionally will send multiple 'keydown' signals when holding a key. – Eloi Mar 31 '21 at 15:25
  • Which OS does this? – Sebastian Simon Mar 31 '21 at 16:27
  • Windows, I tested it again. And is a very frequent behaviour on Chrome, on Firefox it happen more rarely. So logging the value of 'e.repeat' holding a key, listening to the event 'keydown', it should log once 'false' and then multiple 'true' until you release the key. The abnormal behaviour is that you can see, sometimes only, 2 'false' logged and then the multiple 'true' in the log. – Eloi Mar 31 '21 at 18:49

3 Answers3

1

You could make a variable that checks if the key went up. Like this:

var isKeyDown = false;

window.addEventListener('keydown', function(e) {
    if (!isKeyDown) {
      isKeyDown = true;
    } else {
      return
    }
    switch (e.key) {
        case 'ArrowLeft':
            console.log('left');
            break;
        case 'ArrowRight':
            console.log('right');
            break;
    }
});

window.addEventListener('keyup', function(e) {
  isKeyDown = false;
});
Wimanicesir
  • 4,606
  • 2
  • 11
  • 30
  • Thank you, I think this is the best solution. I wrote a slightly different code inspired by this. – Eloi Mar 31 '21 at 15:10
0

you can use the event.repeat to check if the key is already been pressed

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat

window.addEventListener('keydown', function(e) {
            
            if (e.repeat) return;

              //your code 
            switch (e.key) {
              
                case 'ArrowLeft':
                    console.log('left');
                    break;
                case 'ArrowRight':
                    console.log('right');
                    break;
            }
        });
Andrew Nic
  • 108
  • 1
  • 11
  • I tried this with 'keydown' but unfortunately, this doesn't work as intended, it looks like the OS occasionally will send multiple 'keydown' signals when holding a key. * 'keyup' is not very responsive so I won't consider it. – Eloi Mar 31 '21 at 15:13
  • `repeat` doesn’t make sense with `keyup`. Use `keydown` instead. – Sebastian Simon Mar 31 '21 at 16:29
  • yes sorry, i mistyped it should have been keydown – Andrew Nic Mar 31 '21 at 16:44
-1

change 'keydown' to 'keyup'. that will only run when the key is released, so its foolproof. Like so:

window.addEventListener('keyup', function(e) {
            switch (e.key) {
                case 'ArrowLeft':
                    console.log('left');
                    break;
                case 'ArrowRight':
                    console.log('right');
                    break;
            }
        });
  • 1
    I didn't downvote, but to be clear. The console log does not happen whenever a user presses down a button. Only when they release the key again. This could be annoying timing wise.. – Wimanicesir Mar 31 '21 at 13:27
  • 'keyup' is not very responsive so I won't consider it. – Eloi Mar 31 '21 at 15:18