web-dev-qa-db-fra.com

Est-il possible de simuler des événements de presse clés par programmation?

Est-il possible de simuler des événements de presse clés par programmation en JavaScript?

287
tan

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);
152
Philip Nuzhnyy

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");
});
67
alex2k8

Ce que vous pouvez faire est de déclencher par programme des écouteurs keyevent en activant keyevents . Il est logique de permettre cela du point de vue de la sécurité dans un bac à sable. En utilisant cette capacité, vous pouvez ensuite appliquer un modèle-observateur typique. Vous pouvez appeler cette méthode "simuler".

Vous trouverez ci-dessous un exemple de procédure à suivre dans le standard 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

Dans jQuery:

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

Mais ces derniers temps, il n'y a pas de moyen [DOM] de déclencher des événements de clé quittant le navigateur - sandbox. Et tous les principaux fournisseurs de navigateurs adhéreront à cette sécurité. concept.

En ce qui concerne les plugins tels qu'Adobe Flash - basés sur NPAPI - et permettant de contourner le bac à sable: il s'agit de suppression 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 le risque que les éditeurs de navigateurs soient poursuivis par les utilisateurs, car divers événements programmés au clavier auront conduit à des attaques d'usurpation d'identité.

Voir ceci 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, cela montre pourquoi le Web s'éloigne des vendeurs de plug-ins.

Un état d'esprit de sécurité similaire est appliqué dans le cas où politique de CORS opt-in pour accéder au contenu distant par programme.

La réponse est:
Il n'y a aucun moyen de déclencher par programme des clés d'entrée dans l'environnement du navigateur en mode bac à sable dans des circonstances normales .

Bottomline: Je ne dis pas que ce ne sera plus possible à l'avenir, avec des modes de navigateur et/ou des privilèges spéciaux pour atteindre l'objectif final du jeu, ou des expériences utilisateur similaires. Cependant, avant d'entrer dans de tels modes, des autorisations et des risques, similaires à ceux de Modèle d'API Fullscreen , seront demandés à l'utilisateur.

Utile: Dans le contexte des KeyCodes, this le mappage des outils et des codes clés sera très utile.

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

49
Lorenz Lo Sauer

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 n'ai pas testé cela, mais il est adapté du code de la documentation de dispatchEvent () . Vous voudrez probablement lire à travers cela, ainsi que la documentation pour createEvent () et initKeyEvent ().

19
Plutor

Vous pouvez créer et distribuer des événements de clavier, qui déclencheront les gestionnaires d’événements enregistrés appropriés. Toutefois, ils {ne produira aucun texte}, s’ils sont envoyés à l’élément d’entrée, par exemple.

Pour simuler complètement la saisie de texte, vous devez générer une séquence d'événements de clavier et définir explicitement le texte de l'élément d'entrée. La séquence des événements dépend de la profondeur à laquelle vous souhaitez simuler la saisie de texte.

La forme la plus simple serait:

$('input').val('123');
$('input').change();
17
Alex Burtsev

Vous pouvez distribuer des événements de clavier sur un élément comme celui-ci. 

element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));
16
aljgom

Sur la base de la réponse de alex2k8, voici une version révisée qui fonctionne dans tous les navigateurs pris en charge par jQuery (le problème tenait au manque d’arguments dans jQuery.event.trigger, qui est facile à oublier lors de l’utilisation de 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 ceci plus loin et le laisser non seulement simuler l'événement mais aussi insérer le caractère (s'il s'agit d'un élément d'entrée), mais il y a de nombreux pièges entre navigateurs lorsque vous essayez de le faire. Mieux vaut utiliser un plugin plus élaboré comme SendKeys .

12
Krinkle

Pour ceux que cela intéresse, vous pouvez effectivement recréer les événements d'entrée au clavier de manière fiable. Pour modifier le texte dans la zone de saisie (déplacer les curseurs ou la page via un caractère de saisie), vous devez suivre de près le modèle d'événement DOM: http://www.w3.org/TR/DOM-Level-3- Événements/# h4_events-inputevents

Le modèle devrait faire:

  • focus (distribué sur le DOM avec la cible définie)

Puis pour chaque personnage:

  • keydown (distribué sur le DOM)
  • beforeinput (distribué à la cible s'il s'agit d'une zone de texte ou d'une entrée)
  • pression du clavier (distribué sur le DOM)
  • input (distribué à la cible s'il s'agit d'une zone de texte ou d'une entrée)
  • change (envoyé à la cible si c'est un select)
  • keyup (distribué sur le DOM)

Ensuite, éventuellement pour la plupart:

  • flou (distribué sur le DOM avec la cible définie)

Cela change en fait le texte de la page via javascript (sans modifier les déclarations de valeur) et désactive les écouteurs/gestionnaires javascript. Si vous gâchez la séquence, javascript ne se déclenchera pas dans l'ordre approprié, le texte de la zone de saisie ne changera pas, les sélections ne changeront pas ou le curseur ne se déplacera pas vers l'espace suivant dans la zone de texte.

Malheureusement, le code a été écrit pour un employeur sous un NDA. Je ne peux donc pas le partager, mais c'est tout à fait possible, mais vous devez recréer la "pile" d'entrée de clé entière pour chaque élément dans le bon ordre.

8
Trevor

Dans certains cas, keypress event ne peut pas fournir la fonctionnalité requise, généralement, les événements sont combinés à partir des deux événements déclenchés en conséquence, keydown, et le suivant, 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'}));

Cette approche prend en charge plusieurs navigateurs en modifiant 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
Ata Iravani

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 veulent simuler 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
bortunac

Cela a fonctionné pour moi et simule un keyup pour mon textoera. si vous le souhaitez pour toute la page, il suffit de mettre la KeySimulation() sur <body> comme ceci <body onmousemove="KeySimulation()"> ou sinon, onmousemove, alors onmouseover ou onload fonctionne également.

<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
SeekLoad

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ù ça vient, mais c'est utile. Il ajoute une méthode .simulate() à window.KeyEvent; vous l'utilisez donc simplement avec KeyEvent.simulate(0, 13) pour simuler une enter ou KeyEvent.simulate(81, 81) pour un 'Q'.

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

3
fiatjaf

Un inspecteur Web Javascript Vanilla à une seule rangée prêt pour le console dans un copier + coller/ (ce type est déjà attrayant pour la plupart des développeurs, alors n'essayez pas de le rendre plus beau - il est censé être célibataire .. ramé) 

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); 
1

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)
1
Konowy

Voici une solution qui fonctionne sous Chrome et Chromium (seuls ces plateformes ont été testées). Il semble que Chrome ait un bogue ou une approche propre à la gestion des codes de clé. Cette propriété doit donc être ajoutée séparément à KeyboardEvent.

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
Soren

dès que l'utilisateur appuie sur la touche en question, vous pouvez stocker une référence à cette 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 code de clé si vous créez votre propre événement, vous pouvez copier les paramètres existants à partir de tout événement de clavier réel (en ignorant les cibles car c'est le travail de dispatchEvent) et

ta = new KeyboardEvent('keypress',{ctrlKey:true,key:'Escape'})
0
yan bellavance

Pour que cela fonctionne, il est essentiel de réaliser que charCode, keyCode et which sont toutes les méthodes obsolètes . Par conséquent, si le code qui traite l'événement de pression de touche utilise l'un de ces trois facteurs, il recevra une réponse fictive (par exemple, une valeur par défaut de 0).

Tant que vous accédez à l'événement de frappe avec une méthode non dépréciée, telle que key, vous devriez être OK.

Pour terminer, j'ai ajouté le code Javascript de base permettant de déclencher l'événement:

const rightArrowKey = 39
const event = new KeyboardEvent('keydown',{'key':rightArrowKey})
document.dispatchEvent(event)
0
Jack Kinsella

JavaScript natif avec la solution supportée par TypeScript:

Tapez le keyCode ou la propriété que vous utilisez et transcrivez-le en KeyboardEventInit.

Exemple

const event = new KeyboardEvent("keydown", {
          keyCode: 38,
        } as KeyboardEventInit);
0
eugen sunic

Je sais que la question demande un moyen javascript de simuler une pression de touche. Mais pour ceux qui recherchent un moyen jQuery de faire les choses:

var e = jQuery.Event("keypress");
e.which = 13 //or e.keyCode = 13 that simulates an <ENTER>
$("#element_id").trigger(e); 
0
Srinidhi Shankar