web-dev-qa-db-fra.com

Déclenchement d'un événement de clavier en JavaScript

J'essaie de simuler un événement de clavier dans Safari en utilisant JavaScript.

J'ai essayé ceci:

var event = document.createEvent("KeyboardEvent");
event.initKeyboardEvent("keypress", true, true, null, false, false, false, false, 115, 0);

... et aussi ceci:

var event = document.createEvent("UIEvents");
event.initUIEvent("keypress", true, true, window, 1);
event.keyCode = 115;

Après avoir essayé les deux approches, cependant, j'ai le même problème: une fois le code exécuté, les propriétés keyCode/which de l'objet événement sont définies sur 0, ne pas 115.

Est-ce que quelqu'un sait comment créer et envoyer de manière fiable un événement de clavier dans Safari? (Je préférerais le réaliser en JavaScript si possible.)

70
Steve Harrison

Je travaille sur polyfill de niveau 3 d'événement de clavier DOM . Dans les derniers navigateurs ou avec ce polyfill, vous pouvez faire quelque chose comme ceci:

element.addEventListener("keydown", function(e){ console.log(e.key, e.char, e.keyCode) })

var e = new KeyboardEvent("keydown", {bubbles : true, cancelable : true, key : "Q", char : "Q", shiftKey : true});
element.dispatchEvent(e);

//If you need legacy property "keyCode"
// Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari)
delete e.keyCode;
Object.defineProperty(e, "keyCode", {"value" : 666})

MISE À JOUR:

Maintenant, mon polyfill supporte les propriétés héritées "keyCode", "charCode" et "which"

var e = new KeyboardEvent("keydown", {
    bubbles : true,
    cancelable : true,
    char : "Q",
    key : "q",
    shiftKey : true,
    keyCode : 81
});

Exemples ici

De plus, initKeyboardEvent inter-navigateur est séparé de mon polyfill: (Gist)

Polyfill démo

32
termi

Avez-vous envoyé l'événement correctement?

function simulateKeyEvent(character) {
  var evt = document.createEvent("KeyboardEvent");
  (evt.initKeyEvent || evt.initKeyboardEvent)("keypress", true, true, window,
                    0, 0, 0, 0,
                    0, character.charCodeAt(0)) 
  var canceled = !body.dispatchEvent(evt);
  if(canceled) {
    // A handler called preventDefault
    alert("canceled");
  } else {
    // None of the handlers called preventDefault
    alert("not canceled");
  }
}

Si vous utilisez jQuery, vous pouvez faire:

function simulateKeyPress(character) {
  jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}
27
tyronegcarter

Ceci est dû à un bug dans Webkit.

Vous pouvez contourner le bogue Webkit en utilisant createEvent('Event') plutôt que createEvent('KeyboardEvent'), puis en affectant la propriété keyCode. Voir cette réponse et cet exemple .

15
John

Le Mozilla Developer Network fournit l'explication suivante:

  1. Créer un événement en utilisant event = document.createEvent("KeyboardEvent")
  2. Init the Keyevent

en utilisant:

event.initKeyEvent (type, bubbles, cancelable, viewArg, 
       ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, 
           keyCodeArg, charCodeArg)
  1. envoie l'événement en utilisant yourElement.dispatchEvent(event)

Je ne vois pas le dernier dans votre code, c'est peut-être ce qui vous manque. J'espère que cela fonctionne dans IE aussi ...

8
Javache

Je ne suis pas très bon avec ça mais KeyboardEvent => voir KeyboardEvent est initialisé avec initKeyEvent.
Voici un exemple d'émission d'événement sur <input type="text" /> élément

document.getElementById("txbox").addEventListener("keypress", function(e) {
  alert("Event " + e.type + " emitted!\nKey / Char Code: " + e.keyCode + " / " + e.charCode);
}, false);

document.getElementById("btn").addEventListener("click", function(e) {
  var doc = document.getElementById("txbox");
  var kEvent = document.createEvent("KeyboardEvent");
  kEvent.initKeyEvent("keypress", true, true, null, false, false, false, false, 74, 74);
  doc.dispatchEvent(kEvent);
}, false);
<input id="txbox" type="text" value="" />
<input id="btn" type="button" value="CLICK TO EMIT KEYPRESS ON TEXTBOX" />
1
vutar