web-dev-qa-db-fra.com

Keydown Simulation in Chrome se déclenche normalement mais pas la bonne clé

Je veux simuler des événements de keydown sur un élément textarea donné dans une page html. Depuis que j'utilise Chrome, j'ai appelé initKeyboardEvent sur ma variable et j'ai passé le keyCode que je veux taper dans la zone de texte. Voici ce que j'ai essayé:

var keyEvent = document.createEvent('KeyboardEvent');
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0);
inputNode.dispatchEvent(keyEvent);

Dans ce code, je tape la lettre m mais la zone de texte ne reçoit que le keyCode 13 qui est la touche Enter. J'ai donc essayé un code de remplacement que j'ai vu en ligne qui définit la valeur sur keyCodeVal, mais sans succès

var keyEvent = document.createEvent('KeyboardEvent');
Object.defineProperty(keyEvent, 'keyCode', { 
                         get : function() {
                                 return this.keyCodeVal;
                         }
                        });
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0);
keyEvent.keyCodeVal = 77;
inputNode.dispatchEvent(keyEvent);

Quelqu'un at-il une idée de la façon de définir la valeur keyCode?

27
fabricemarcelin

Donc très très proche ...

Vous aviez juste besoin de remplacer la propriété 'which'. Voici un exemple de code:

Podium = {};
Podium.keydown = function(k) {
    var oEvent = document.createEvent('KeyboardEvent');

    // Chromium Hack
    Object.defineProperty(oEvent, 'keyCode', {
                get : function() {
                    return this.keyCodeVal;
                }
    });     
    Object.defineProperty(oEvent, 'which', {
                get : function() {
                    return this.keyCodeVal;
                }
    });     

    if (oEvent.initKeyboardEvent) {
        oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, k, k);
    } else {
        oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, k, 0);
    }

    oEvent.keyCodeVal = k;

    if (oEvent.keyCode !== k) {
        alert("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ")");
    }

    document.dispatchEvent(oEvent);
}

Exemple d'utilisation:

Podium.keydown(65);

Remarque: ce code n'est pas conçu pour fonctionner dans IE, Safari ou d'autres navigateurs. Eh bien, peut-être avec Firefox. YMMV.

80
Orwellophile

La solution d'Orwellophile fonctionne.

  • Premièrement: "keyCode", "charCode" et "which" est en lecture seule dans Safari et IE9 + (au moins).
  • Deuxièmement: initKeyboardEvent est un peu désordonné. Tous les navigateurs l'implémentent d'une manière différente. Même dans les webkits, il existe plusieurs implémentations différentes d'initKeyboardEvent. Et il n'y a pas de "bon" moyen pour initKeyboardEvent dans Opera.
  • Troisièmement: initKeyboardEvent est obsolète. Vous devez utiliser le constructeur initKeyEvent ou KeyboardEvent.

Ici, j'ai écrit fonction initKeyboardEvent multi-navigateur (Gist):

Exemple:

var a = window.crossBrowser_initKeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey)

Et voici mon polyfill DOM Keyboard Event Level avec le constructeur KeyboardEvent multi-navigateur.

Exemple:

var a = new KeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey)

Exemple 2

exemple

Remarque importante 1: charCode, keyCode et quelles propriétés sont obsolètes. Donc, ni mon constructeur crossBrowser_initKeyboardEvent no KeyboardEvent ne sont absolument garantis des valeurs correctes de ces propriétés dans certains navigateurs. Vous pouvez utiliser les propriétés "key" et "char" à la place ou modifier my Gist pour forcer l'utilisation d'initEvent dans les navigateurs avec charCode en lecture seule, keyCode et quelles propriétés.

Remarque importante 2: l'événement keypress est obsolète et pour l'instant non pris en charge dans mon Polyfill Keyboard Event Level . Cela signifie que les propriétés de clé et de caractère dans l'événement keypress peuvent avoir des valeurs aléatoires. Je travaille pour résoudre ce problème de compatibilité descendante.

14
termi

Pour que le script de @ Orwellophile fonctionne sur Google Chrome 26.0.1410.65 (sur Mac OS X 10.7.5, si cela importe), j'ai dû changer une ligne: son script semble avoir les paramètres de initKeyboardEvent dans un ordre différent de documentation MDN pour initKeyboardEvent .

La ligne modifiée ressemble à ceci:

oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, k, k, "", "", false, "");
4
Dave Land

Eh bien, les solutions ci-dessus ont fonctionné, également grâce à @dland pour la pointe des paramètres. Voici quelque chose que j'ai trouvé utile, si vous ne parvenez pas à déclencher les événements au bon endroit.

Le script de @ Orwellophile déclenche l'événement sur le document. Il est possible que l'écouteur d'événements ne soit pas toujours enregistré sur document. J'ai changé la dernière ligne en suivant et maintenant cela fonctionne à peu près à chaque fois.

document.activeElement.dispatchEvent(oEvent);

Le document.activeElement déclenche toujours l'événement sur l'élément sur lequel l'utilisateur se concentre actuellement.

3
Ankit

Toutes les solutions ci-dessus fonctionnent, mais j'ai trouvé un cas où elles ne fonctionneront pas.

Si Dart est utilisé, le code Dart qui utilise KeyboardEvents ne fonctionnera pas sur un événement général.

Vous obtiendrez quelque chose comme get $ keyCode n'est pas défini.

après m'être cogné la tête pendant des heures à ce sujet, j'ai trouvé l'astuce suivante:

function __triggerKeyboardEvent(el, keyCode)
{
   var eventObj = document.createEventObject ?
       document.createEventObject() : document.createEvent("Events");

   var tempKeyboardObj = document.createEvent("KeyboardEvents");

   if(eventObj.initEvent){
      eventObj.initEvent("keydown", true, true);
   }
   eventObj.___Dart_dispatch_record_ZxYxX_0_ = tempKeyboardObj.___Dart_dispatch_record_ZxYxX_0_
   eventObj.keyCode = keyCode;
   eventObj.which = keyCode;

   el.dispatchEvent ? el.dispatchEvent(eventObj) : el.fireEvent("onkeydown", eventObj);

} 

Tromper l'intercepteur Dart pour que notre événement soit en fait un événement KeyboardEvent, a fait l'affaire.

Laissez-le ici, pour le pauvre gars qui essaie de tester l'application Dart sur un navigateur basé sur un kit Web.

0
Fruch