Traduire la touche JavascriptCode dans charCode pour la disposition du clavier non-US (c.-à-azerty)

Contexte rapide:

  • Lorsqu'une touche est pressée dans un navigateur, trois événements sont générés: keyDown , keyPress et keyUp .
  • KeyDown et keyUp ont une propriété keyCode qui est approximativement la touche physique enfoncée.
  • KeyPress a également un ensemble de propriétés charCode qui prend en compte les touches de modification et la disposition du clavier (A et A ont le même code de clé mais un code de caractères différent).
  • Les trois événements ont des propriétés qui indiquent les touches de modification utilisées lors de ces événements.

Je suis le développeur principal de noVNC et j'ai un problème difficile: noVNC a besoin de la valeur charCode traduite sans utiliser l'événement keyPress pour les raisons suivantes:

  • NoVNC doit envoyer les événements keyDown et keyUp séparément au serveur VNC (sinon ce n'est pas un client VNC complètement fonctionnel).
  • Plus important encore, noVNC doit empêcher les actions par défaut du clavier pendant qu'il est connecté, ce qui signifie appeler la méthode preventDefault () de l'événement keyDown . Cela a pour effet secondaire d'empêcher également le déclenchement de l' événement keyPress .

En raison des différences dans les mises en page du clavier (c.-à-d. Différents modes de code à caractères chiffrés) j'ai déterminé que noVNC aura besoin d'une table de consultation pour différentes configurations de clavier.

Mais voici le vrai problème: sur d'autres mises en page, certaines touches physiques différentes ont la même clé de code. Par exemple, avec une disposition de clavier azerty (française), les touches de soulignement '-' (dash) et '_' génèrent la cléCode 189. Ack !!!

Alors … comment puis-je obtenir correctement keyCode à charCode cartographie et empêcher les actions par défaut du navigateur en même temps?

BTW, je soupçonne que la solution sera applicable à d'autres applications Web interactives et à des jeux HTML5 car vous souhaitez souvent connaître toutes les informations sur la touche appuyée sans déclencher de réponse supplémentaire du navigateur à cette touche.

Liens utiles:

  • Voici une page de test utile qui montre les trois événements et d'autres propriétés utiles.
  • Résumé de l'état folle des événements clés en Javascript (Merci @Tim)
  • Quirksmode Détection des touches
  • Quirksmode Events – événements clés
  • Problème de noVNC avec plus de discussion sur le problème.

Solution : voir mon message ci-dessous.

J'ai résolu ma propre question. Ce n'est pas une solution à 100%, mais cela devrait couvrir la plupart des besoins. Espérons qu'il y aura une solution plus propre lorsque les fournisseurs de navigateurs commenceront à intégrer les événements DOM Level 3 .

Juste pour ré-itérer les principales contraintes:

  1. Les événements de la clé et de la clé doivent être signalés / envoyés au moment où ils se produisent réellement. C'est-à-dire envoyer une clé vers le bas et la clé ensemble pendant l'événement KeyPress est insuffisant.
  2. De nombreuses combinaisons de touches doivent être entièrement traitées lors de l'événement keyDown, soit parce qu'elles ne déclenchent jamais un événement KeyPress (c'est-à-dire la touche Ctrl), soit parce que l'action par défaut doit être arrêtée dans keyDown (WebKit), ce qui empêche l'événement keyPress de se produire.
  3. La clé descendante et les événements clés doivent signaler le code de caractère traduit et non la valeur KeyCode.

Sans une épiphanie excitante, les implémentations actuelles du navigateur semblent empêcher toutes les trois contraintes d'être complètement remplies. J'ai donc décidé de relâcher la contrainte n ° 3 un peu.

  • Sur l'événement keyDown du navigateur, ajoutez l'événement à une liste déroulante et vérifiez s'il s'agit d'une combinaison de touches sûres (sans comportement par défaut du navigateur indésirable)

    • Sûr : ne faites rien avant que la touche ne presse.

    • Inseguro : signaler / envoyer un événement clé vers le bas immédiatement. C'est là que la contrainte n ° 3 est décontractée car ces combinaisons de touches limitées ne sont pas traduites dans un code de caractère (beaucoup d'entre elles n'en ont pas encore).

  • Sur la touche du navigateur Appuyez sur l' événement (ce qui se produit immédiatement après l'événement keyDown) vérifiez s'il s'agit d'une combinaison de touches sûres:

    • Safe : signaler / envoyer un événement clé en bas. Mettre à jour la liste déroulante en utilisant le code de caractère traduit (event.which).

    • Inseguré : ne faites rien car il a déjà été signalé / envoyé pendant KeyDown.

  • Sur l'événement KeyUp du navigateur, recherchez et supprimez l'événement correspondant de la liste déroulante et utilisez le code traduit pour signaler / envoyer l'événement clé.

Quelques liens supplémentaires pour ceux intéressants:

  • Le noVNC s'engage avec la modification.
  • Quelques notes de wiki sur les problèmes liés à noVNC.
  • Cette solution a été adoptée dans le projet Broadway de RedHat (HTML5 GTK + backend) .

C'est un champ de mines absolu et je vous exhorte à ne pas essayer cela si vous pouvez l'éviter. Non seulement il existe un historique long et enchevêtrement des constructeurs de navigateurs qui ne sont pas d'accord sur le comportement des événements clés, mais aussi qu'ils ne sont toujours pas d'accord et changent régulièrement le comportement clé de leurs navigateurs.

Voici le meilleur que je peux offrir et la ressource définitive sur les événements clés du navigateur: http://unixpapa.com/js/key.html

Si vous devez le faire, je pense que vous allez vous retrouver avec beaucoup de tableaux de cartographie de code clé qui seront dépassés très rapidement. Bonne chance.