Est-il possible de simuler des événements clés de presse de façon programmatique?

est-il possible de simuler des événements clés de presse de manière programmatique en JavaScript?

264
demandé sur Cœur 2009-02-27 23:17:12

18 réponses

une version non-jquery qui fonctionne à la fois dans webkit et gecko:

var keyboardEvent = document.createEvent("KeyboardEvent");
var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";


keyboardEvent[initMethod](
                   "keydown", // event type : keydown, keyup, keypress
                    true, // bubbles
                    true, // cancelable
                    window, // viewArg: should be window
                    false, // ctrlKeyArg
                    false, // altKeyArg
                    false, // shiftKeyArg
                    false, // metaKeyArg
                    40, // keyCodeArg : unsigned long the virtual key code, else 0
                    0 // charCodeArgs : unsigned long the Unicode character associated with the depressed key, else 0
);
document.dispatchEvent(keyboardEvent);
143
répondu Philip Nuzhnyy 2012-08-29 22:18:11

si vous êtes d'accord pour utiliser jQuery 1.3.1:

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

$(function() {
  $('body').keypress(function(e) {
    alert(e.which);
  });

  simulateKeyPress("e");
});
65
répondu alex2k8 2009-03-05 01:18:44

Ce que vous pouvez faire est de déclencher par programmation keyevent auditeurs par le feu keyevents . Il est logique de permettre cela du point de vue de la sécurité. En utilisant cette capacité, vous pouvez alors appliquer un typique observateur-modèle . On pourrait appeler cette méthode "simulation".

ci-dessous est un exemple de la façon d'accomplir ceci dans la norme DOM W3C avec jQuery:

function triggerClick() {
  var event = new MouseEvent('click', {
    'view': window,
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.querySelector('input[type=submit][name=btnK]'); 
  var canceled = !cb.dispatchEvent(event);
  if (canceled) {
    // preventDefault was called and the event cancelled
  } else {
    // insert your event-logic here...
  }
}

cet exemple est adapté de: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

En jQuery:

jQuery('input[type=submit][name=btnK]')
  .trigger({
    type: 'keypress',
    which: character.charCodeAt(0 /*the key to trigger*/)      
   });

mais depuis peu, il n'y a pas de moyen [DOM] de déclencher des événements clés en sortant du bac à sable du navigateur. et tous les principaux fournisseurs de navigateurs adhéreront à ce concept de sécurité.

comme pour les plugins comme Adobe Flash - qui sont basés sur le NPAPI-, et permettent de contourner le bac à sable: ce sont élimination progressive ; Firefox .

Explication Détaillée:

vous ne pouvez pas et vous ne devez pas pour des raisons de sécurité (comme Pekka l'a déjà souligné). Vous aurez toujours besoin d'une interaction utilisateur entre les deux. En outre, imaginez la chance des vendeurs de navigateur obtenir poursuivi par les utilisateurs, comme divers programmateurs clavier événements ont conduit à des attaques par usurpation.

de cette post pour des alternatives et plus de détails. Il y a toujours le copier-coller flash. Voici un élégant exemple . En même temps c'est un témoignage pourquoi le web s'éloigne des vendeurs de plugin.

il existe un État d'esprit similaire en matière de sécurité appliqué dans le cas de la Politique opt-in CORS pour accéder au contenu à distance par programmation.

la réponse est:

il n'y a aucun moyen de déclencher programmatiquement des touches d'entrée dans l'environnement sandboxed browser dans des circonstances normales .

Bottomline: Je ne dis pas que ce ne sera pas possible à l'avenir, sous des modes de navigateur et/ou des privilèges spéciaux vers le but final du jeu, ou des expériences utilisateur similaires. Cependant avant d'entrer ces en mode, l'Utilisateur sera invité à fournir des permissions et des risques, similaires au Fullscreen API model .

utile: dans le contexte de KeyCodes, cet outil et la cartographie de keycode sera pratique.

Divulgation: La réponse est basée sur la réponse ici .

39
répondu Lorenz Lo Sauer 2018-07-15 17:54:39

vous pouvez utiliser dispatchEvent() :

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

Je ne l'ai pas testé, mais il est adapté du code sur dispatchEvent()'s documentation . Vous voudrez probablement lire à travers cela, et aussi les docs pour createEvent() et initKeyEvent().

18
répondu Plutor 2018-08-10 10:09:43

vous pouvez créer et envoyer des événements clavier, et ils déclencheront des gestionnaires d'événements enregistrés appropriés, mais ils ne produiront pas de texte , s'ils sont envoyés à l'élément d'entrée par exemple.

pour simuler complètement l'entrée de texte, vous devez produire une séquence d'événements clavier plus explicitement définir le texte de l'élément d'entrée. La séquence des événements dépend de la façon dont vous voulez simuler l'entrée de texte.

le forme la plus simple serait:

$('input').val('123');
$('input').change();
15
répondu Alex Burtsev 2013-07-04 17:28:48

vous pouvez envoyer des événements clavier sur un élément comme celui-ci

element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));
14
répondu aljgom 2017-06-02 07:08:07

en S'appuyant sur la réponse d'alex2k8, voici une version révisée qui fonctionne dans tous les navigateurs que jQuery supporte (le problème était dans les arguments manquants à jQuery.événement.trigger, qui est facile à oublier en utilisant cette fonction interne).

// jQuery plugin. Called on a jQuery object, not directly.
jQuery.fn.simulateKeyPress = function (character) {
  // Internally calls jQuery.event.trigger with arguments (Event, data, elem).
  // That last argument, 'elem', is very important!
  jQuery(this).trigger({ type: 'keypress', which: character.charCodeAt(0) });
};

jQuery(function ($) {
  // Bind event handler
  $('body').keypress(function (e) {
    alert(String.fromCharCode(e.which));
    console.log(e);
  });
  // Simulate the key press
  $('body').simulateKeyPress('x');
});

vous pouvez même pousser plus loin et le laisser non seulement simuler l'événement, mais en fait insérer le caractère (si c'est un élément d'entrée), mais il ya beaucoup de cross-browser gotcha en essayant de le faire. Mieux utiliser un plugin plus élaboré comme SendKeys .

12
répondu Krinkle 2017-05-07 02:25:39

cette approche prend en charge le navigateur croisé changeant la valeur de code clé . Source

var $textBox = $("#myTextBox");

var press = jQuery.Event("keypress");
press.altGraphKey = false;
press.altKey = false;
press.bubbles = true;
press.cancelBubble = false;
press.cancelable = true;
press.charCode = 13;
press.clipboardData = undefined;
press.ctrlKey = false;
press.currentTarget = $textBox[0];
press.defaultPrevented = false;
press.detail = 0;
press.eventPhase = 2;
press.keyCode = 13;
press.keyIdentifier = "";
press.keyLocation = 0;
press.layerX = 0;
press.layerY = 0;
press.metaKey = false;
press.pageX = 0;
press.pageY = 0;
press.returnValue = true;
press.shiftKey = false;
press.srcElement = $textBox[0];
press.target = $textBox[0];
press.type = "keypress";
press.view = Window;
press.which = 13;

$textBox.trigger(press);
6
répondu Ata Iravani 2014-03-21 17:41:14

pour ceux qui sont intéressés, vous pouvez, en fait, recréer des événements d'entrée de clavier de manière fiable. Afin de changer le texte dans la zone d'entrée (déplacer curseurs, ou la page via un caractère d'entrée), vous devez suivre de près le modèle D'événement DOM: http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents

le modèle devrait faire:

  • focus (expédié sur le DOM avec l'objectif fixé)

Puis pour chaque caractère:

  • keydown (répartis sur les DOM)
  • avant l'entrée (expédiée à la cible si c'est un textarea ou input)
  • keypress (expédié sur le DOM)
  • "151970920 d'entrée" (envoyé à la cible si ses un textarea ou d'entrée)
  • le changement (envoyé à la cible si ses select)
  • keyup (expédié sur le DOM)

, Puis, éventuellement, pour la plupart:

  • flou (envoyé sur le DOM avec la cible fixée)

cela modifie réellement le texte dans la page via javascript (sans modifier les énoncés de valeur) et déclenche n'importe quels auditeurs/gestionnaires javascript de manière appropriée. Si vous gâchez la séquence, javascript ne se déclenchera pas dans l'ordre approprié, le texte dans la boîte de saisie ne changera pas, les sélections ne changeront pas ou le curseur sera ne pas passer à l'espace suivant dans la zone de texte.

malheureusement, le code a été écrit pour un employeur sous une NDA donc je ne peux pas le partager, mais il est certainement possible, mais vous devez recréer la totalité de l'entrée clé "stack" pour chaque élément dans le bon ordre.

5
répondu Trevor 2014-05-30 22:40:40

il suffit d'utiliser CustomEvent

Node.prototype.fire=function(type,options){
     var event=new CustomEvent(type);
     for(var p in options){
         event[p]=options[p];
     }
     this.dispatchEvent(event);
}

4 ex veux simuler les touches ctrl+z

window.addEventListener("keyup",function(ev){
     if(ev.ctrlKey && ev.keyCode === 90) console.log(ev); // or do smth
     })

 document.fire("keyup",{ctrlKey:true,keyCode:90,bubbles:true})
5
répondu bortunac 2017-04-13 10:35:59

dans certains cas keypress événement ne peut pas fournir funtionality requis, généralement, les événements est combiné à partir des deux événements par conséquent tiré keydown , et le suivant it keyup pour la même clé. Il suffit donc de générer les événements un par un:

element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'}));
element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));
5
répondu Малъ Скрылевъ 2018-01-23 21:17:09

Voici une bibliothèque qui aide vraiment: https://cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js

je ne sais pas d'où il vient, mais il est utile. Il ajoute une méthode .simulate() à window.KeyEvent , donc vous l'utilisez simplement avec KeyEvent.simulate(0, 13) pour simuler un enter ou KeyEvent.simulate(81, 81) pour un 'Q' .

Je l'ai eu à https://github.com/ccampbell/mousetrap/tree/master/tests .

3
répondu fiatjaf 2014-09-10 23:18:48

cela a fonctionné pour moi et il ne simule un keyup pour mon textaera. si vous le voulez pour la page entière vient de mettre le KeySimulation() sur <body> comme ceci <body onmousemove="KeySimulation()"> ou si pas onmousemove alors onmouseover ou onload fonctionne aussi.

<script>
function KeySimulation()
{
var e = document.createEvent("KeyboardEvent");
if (e.initKeyboardEvent) {  // Chrome, IE
    e.initKeyboardEvent("keyup", true, true, document.defaultView, "Enter", 0, "", false, "");
} else { // FireFox
    e.initKeyEvent("keyup", true, true, document.defaultView, false, false, false, false, 13, 0);
}
document.getElementById("MyTextArea").dispatchEvent(e);
}
</script>

<input type="button" onclick="KeySimulation();" value=" Key Simulation " />
<textarea id="MyTextArea" rows="15" cols="30"></textarea>
3
répondu SeekLoad 2018-01-15 02:29:27

Voici une solution qui fonctionne en Chrome et Chrome (n'ont testé que ces plates-formes). Il semble que Chrome ait un bug ou sa propre approche pour gérer les codes clés, de sorte que cette propriété doit être ajoutée séparément au clavier Event.

function simulateKeydown (keycode,isCtrl,isAlt,isShift){
    var e = new KeyboardEvent( "keydown", { bubbles:true, cancelable:true, char:String.fromCharCode(keycode), key:String.fromCharCode(keycode), shiftKey:isShift, ctrlKey:isCtrl, altKey:isAlt } );
    Object.defineProperty(e, 'keyCode', {get : function() { return this.keyCodeVal; } });     
    e.keyCodeVal = keycode;
    document.dispatchEvent(e);
}
1
répondu Soren 2018-03-31 19:14:52

dès que l'utilisateur appuie sur la touche en question, vous pouvez stocker une référence à ce même et l'utiliser sur n'importe quel autre élément HTML:

EnterKeyPressToEmulate<input class="lineEditInput" id="addr333_1" type="text" style="width:60%;right:0%;float:right" onkeydown="keyPressRecorder(event)"></input>
TypeHereToEmulateKeyPress<input class="lineEditInput" id="addr333_2" type="text" style="width:60%;right:0%;float:right" onkeydown="triggerKeyPressOnNextSiblingFromWithinKeyPress(event)">
Itappears Here Too<input class="lineEditInput" id="addr333_3" type="text" style="width:60%;right:0%;float:right;" onkeydown="keyPressHandler(event)">
<script>
var gZeroEvent;
function keyPressRecorder(e)
{
  gZeroEvent = e;
}
function triggerKeyPressOnNextSiblingFromWithinKeyPress(TTT)
{
  if(typeof(gZeroEvent) != 'undefined')  {
TTT.currentTarget.nextElementSibling.dispatchEvent(gZeroEvent);
keyPressHandler(TTT);
  }
}
function keyPressHandler(TTT)
{
  if(typeof(gZeroEvent) != 'undefined')  {
TTT.currentTarget.value+= gZeroEvent.key;
event.preventDefault();
event.stopPropagation();
  }
}
</script>

vous pouvez définir le keyCode si vous créez votre propre événement, vous pouvez copier les paramètres existants à partir de n'importe quel événement de clavier réel (ignorant les cibles depuis son travail de dispatchEvent) et:

ta = new KeyboardEvent('keypress',{ctrlKey:true,key:'Escape'})
0
répondu yan bellavance 2018-03-25 07:14:32

Une seule ligne à la vanille web Javascript inspecteur guy prêt pour le console dans un copier+coller (ce mec est déjà attrayante pour la plupart des devs, donc, ne pas essayer d'embellir lui - il est censé être unique.. en ligne)

var pressthiskey = "q"/* <--- :) !? q for example */; var e = new Event("keydown"); e.key=pressthiskey; e.keyCode=e.key.charCodeAt(0); e.which=e.keyCode; e.altKey=false; e.ctrlKey=true; e.shiftKey=false; e.metaKey=false; e.bubbles=true; document.dispatchEvent(e); 
0
répondu K. Kilian Lindberg 2018-07-19 00:26:18

c'est Ce que j'ai réussi à trouver:

function createKeyboardEvent(name, key, altKey, ctrlKey, shiftKey, metaKey, bubbles) {
  var e = new Event(name)
  e.key = key
  e.keyCode = e.key.charCodeAt(0)
  e.which = e.keyCode
  e.altKey = altKey
  e.ctrlKey = ctrlKey
  e.shiftKey = shiftKey
  e.metaKey =  metaKey
  e.bubbles = bubbles
  return e
}

var name = 'keydown'
var key = 'a'

var event = createKeyboardEvent(name, key, false, false, false, false, true)

document.addEventListener(name, () => {})
document.dispatchEvent(event)
0
répondu Konowy 2018-09-25 07:56:30

vous devriez utiliser une certaine lib JS avec le soutien pour emballer le modèle D'événement DOM. À partir de là, vous pouvez tirer et tester vos maîtres.

-4
répondu skrat 2009-10-19 10:40:20