6

i want to create a simple event handler for a game, here's my code

     $(document).keydown(function(e){
      switch(e.keyCode){
        case 65: //left (a)

          console.log('left');
          break;

        case 68: //right (d)

          console.log('right');
          break;

      }
    });

the problem is that if i press and hold a key, after a little it triggers multiple times. how can i prevent this behaviour? i'm running my code on google chrome

MrColly
  • 63
  • 1
  • 1
  • 5
  • 1
    **keydown** Fires when the user depresses a key. It repeats while the user keeps the key depressed. **keypress** Fires when an actual character is being inserted in, for instance, a text input. It repeats while the user keeps the key depressed. **keyup** Fires when the user releases a key, after the default action of that key has been performed. http://stackoverflow.com/a/13127566/297641 – Selvakumar Arumugam Oct 29 '13 at 18:35
  • `.keyup()` would be the right choice 4 sure.... – Jai Oct 29 '13 at 18:36
  • @Jai: `keyup` is *part* of the solution, but just switching from `keydown` to `keyup` would probably be unpopular with users. – T.J. Crowder Oct 29 '13 at 18:39
  • Also take a look at throttle/debounce plugin http://benalman.com/projects/jquery-throttle-debounce-plugin/ for more handling features. – Selvakumar Arumugam Oct 29 '13 at 18:41

2 Answers2

9

This is key repeat. You can defeat it if you want to, by remembering that you already know the key is down:

// A map to remember in
var keysdown = {};

// keydown handler
$(document).keydown(function(e){

  // Do we already know it's down?
  if (keysdown[e.keyCode]) {
      // Ignore it
      return;
  }

  // Remember it's down
  keysdown[e.keyCode] = true;

  // Do our thing
  switch(e.keyCode){
    case 65: //left (a)

      console.log('left');
      break;

    case 68: //right (d)

      console.log('right');
      break;

  }
});

// keyup handler
$(document).keyup(function(e){
  // Remove this key from the map
  delete keysdown[e.keyCode];
});

Side note: I think when you're using jQuery, e.which is the more reliable property, as it's normalized for you by jQuery.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Nice solution. Just as a heads up, left/right arrow keys are 37/39 on the mac I am on. Not sure all the stipulations of cross OS keyCodes, but figured it was worth mentioning. – Don Boots Oct 29 '13 at 18:40
  • @DonBoots: Ah, yes, the [madness that is JavaScript keyboard stuff](http://unixpapa.com/js/key.html). – T.J. Crowder Oct 29 '13 at 18:44
4
var keyPressed = false;

$(document).on('keydown', function(e) {
  var key;
  if (keyPressed === false) {
    keyPressed = true;
    key = String.fromCharCode(e.keyCode);

    //this is where you map your key
    if (key === 'X') {
      console.log(key);
      //or some other code
    }
  }
  $(this).on('keyup', function() {
    if (keyPressed === true) {
      keyPressed = false;
      console.log('Key no longer held down');
      //or some other code
    }
  });
});
xandrw
  • 331
  • 2
  • 8