mybuddymichael
mybuddymichael

Reputation: 1710

Iterating over a JavaScript object to bind keys

Considering the following code:

controls = {
  'w': 'up',
  's': 'down',
  'a': 'left',
  'd': 'right'
};

keysPressed = [];

for (control in controls) {
  direction = controls[control];
  $(document).bind('keydown', control, function() {
    keysPressed.push(direction);
  });
}

Only the right direction gets bound, and it is bound to all four keys. This is obviously not intended, but what am I missing about JavaScript that prevents all the properties from being bound appropriately?

EDIT:

For clarification, I'm using jQuery.hotkeys to handle key names. And this is a snippet; you can assume all variables have been declared. Also, code is in a safety function wrapper.

SOLUTION:

I solved it with this modification:

controls = {
  'w': 'up',
  's': 'down',
  'a': 'left',
  'd': 'right'
};

keysPressed = [];

addToKeyPressArray = function(value) {
  return function() {
    keysPressed.push(value);
  };
};

removeFromKeyPressArray = function(value) {
  return function() {
    keysPressed = keysPressed.filter(value);
  };
};

for (control in controls) {
  direction = controls[control];
  $(document).bind('keydown', control, addToKeyPressArray(direction));
  $(document).bind('keyup', control, removeFromKeyPressArray(direction));
}

That's an odd JavaScript quirk.

Upvotes: 2

Views: 145

Answers (3)

Marcel Jackwerth
Marcel Jackwerth

Reputation: 54762

You didn't declare the direction variable (using var), so it will be in global scope. This means the for-loop will run and then direction will be set to right.

All keys are bound, but all call

keysPressed.push(direction);
// and that is:
keysPressed.push("right");

Also I recommend to read Jani's post (and the related article) as you could have walked into that issue as well.

Upvotes: 0

Šime Vidas
Šime Vidas

Reputation: 185933

This is how I would do it:

$( document ).keypress( function ( e ) {
    var char = String.fromCharCode( e.keyCode );

    if ( controls[ char ] ) {
        keysPressed.push( controls[ char ] );
    }
});

Upvotes: 1

Jani Hartikainen
Jani Hartikainen

Reputation: 43243

Seems to me like it's probably the basic "closure in for loop" issue that many people trip up on with JS.

An explanation and solution is easy to find via google, here's one for example: http://www.mennovanslooten.nl/blog/post/62

Upvotes: 2

Related Questions