web-dev-qa-db-fra.com

Comment puis-je éviter les événements auto-répétés de keydown en JavaScript?

Si l'utilisateur maintient la touche enfoncée, plusieurs événements keydown sont déclenchés. Pour des raisons de convivialité, je dois utiliser Keydown, pas Keyup, mais je veux éviter cette situation. Mon code pertinent est le suivant:

$(document).keydown(function(e) { 
        var key = 0;


        if (e == null) { key = event.keyCode;}  
        else {  key = e.which;} 


        switch(key) {
            case config.keys.left:                
              goLeft();
              break;
            case config.keys.up:                        
              goUp();
              break;
            case config.keys.right:                     
              goRight();
              break;
            case config.keys.down:                
              goDown();
              break;
            case config.keys.action:              
              select();
              break;
        }     
      });

Ainsi, lorsque l'utilisateur appuie sur la touche bas, par exemple, goDown () est déclenché plusieurs fois. Je voudrais qu'il ne soit déclenché qu'une seule fois, même si l'utilisateur maintient la touche enfoncée.

24
agente_secreto

Utilisez event.repeat pour détecter si l'événement se répète ou non. Vous pouvez alors attendre "keyup" avant de permettre au gestionnaire de s'exécuter une seconde fois.

var allowed = true;

$(document).keydown(function(event) { 
  if (event.repeat != undefined) {
    allowed = !event.repeat;
  }
  if (!allowed) return;
  allowed = false;
  //...
});

$(document).keyup(function(e) { 
  allowed = true;
});
$(document).focus(function(e) { 
  allowed = true;
});
37
4esn0k

Un autre ajustement simple à la réponse acceptée pour permettre le scénario à plusieurs clés:

var keyAllowed = {};

$(document).keydown(function(e) {
  if (keyAllowed [e.which] === false) return;
  keyAllowed [e.which] = false;
  // code to be executed goes here
});

$(document).keyup(function(e) { 
  keyAllowed [e.which] = true;
});

$(document).focus(function(e) { 
  keyAllowed = {};
});
7
mattybrad

Donc, si la solution existante semble douteuse (elle ne considère pas le cas où 2 boutons ou plus sont enfoncés simultanément), je suggère une autre solution qui en tient compte.

L'objet _prevKeyDown sert à stocker les touches actuellement enfoncées.

    _prevKeyDown = {}

    function _downKey( event )
    {
        var wh = event.which;
        var kC = event.keyCode;

        if( _prevKeyDown[ wh ] == null )
        {
            _prevKeyDown[ wh ] = {};
        }

        _prevKeyDown[ wh ][ kC ] = true;
    };

    function _upKey( event )
    {
        var wh = event.which;
        var kC = event.keyCode;

        if( _prevKeyDown[ wh ] != null )
        {
            _prevKeyDown[ wh ][ kC ] = null;
        }               
    };

    function _isKeyDown( event )
    {
        var wh = event.which;
        var kC = event.keyCode;

        var result = false;

        if( this._prevKeyDown[ wh ] != null )
        {
            if( this._prevKeyDown[ wh ][ kC ] == true )
            {
                result = true;
            }
        }

        return result;
    }

    // now your keydown/keyup handlers
    function keydown( event )
    {
        if( !_isKeyDown( event ) )
        {
            // your once-keydown handler here
            _downKey( event );
        }    
    }

    function keyup( event )
    {
        _upKey( event );
    }
3
sergzach

(Copié d'une autre question qui s'est révélée être une copie de celle-ci.)

dmaurolizer - Bibliothèque KeyPress permet de contrôler avec précision tous les événements du clavier. Vous fournissez des fonctions de rappel pour les événements. L'événement keydown envoie un paramètre isRepeat facultatif afin que vous puissiez ignorer les répétitions automatiques. Voici un exemple utilisant cette fonctionnalité pour le contrôle de poussée dans un jeu vidéo:

var my_combos = listener.register_many([
    {
        "keys"          : "up",
        "on_keydown"    : function(e, num, isRepeat) {
            if (isRepeat) return ;
            thrust = 0.1;
        },
        "on_keyup"      : function() {
            thrust = 0;
        }
    }
]);
0
Juan Tomas