web-dev-qa-db-fra.com

Comment simuler des pressions de touches ou un clic avec JavaScript?

J'ai écrit une Google Chrome et le site sur lequel je veux utiliser mon extension m'oblige à cliquer ou à taper sur une zone de texte (car je pense qu'il exécute la vérification javaScript "onClick" uniquement). Je peux obtenir le texte dans la boîte avec mon extension en utilisant:

document.getElementById("input1").value = 'test';

Mais quand je clique sur soumettre, il pense que je n'ai rien entré dans la zone de texte "input1" car je n'ai jamais cliqué dessus ni tabulé dessus.

Quelqu'un peut-il m'aider à contourner ce problème?

38
milan

Simuler un clic de souris

Je suppose que la page Web écoute le sourd plutôt que le clic (ce qui est mauvais pour l'accessibilité car lorsqu'un utilisateur utilise le clavier, seuls le focus et le clic sont déclenchés, pas le sourd). Vous devez donc simuler le mousedown, le click et le mouseup (ce qui, soit dit en passant, est ce que font l'iPhone, l'iPod Touch et l'iPad lors des événements tactiles ).

Pour simuler les événements de souris, vous pouvez utiliser cet extrait de code pour les navigateurs qui prennent en charge Événements DOM 2 . Pour une simulation plus infaillible, remplissez la position de la souris en utilisant initMouseEvent à la place.

// DOM 2 Events
var dispatchMouseEvent = function(target, var_args) {
  var e = document.createEvent("MouseEvents");
  // If you need clientX, clientY, etc., you can call
  // initMouseEvent instead of initEvent
  e.initEvent.apply(e, Array.prototype.slice.call(arguments, 1));
  target.dispatchEvent(e);
};
dispatchMouseEvent(element, 'mouseover', true, true);
dispatchMouseEvent(element, 'mousedown', true, true);
dispatchMouseEvent(element, 'click', true, true);
dispatchMouseEvent(element, 'mouseup', true, true);

Lorsque vous déclenchez un événement de clic simulé, le navigateur déclenche en fait l'action par défaut (par exemple, accédez au href du lien ou soumettez un formulaire).

Dans IE, l'extrait équivalent est le suivant (non vérifié car je n'ai pas IE). Je ne pense pas que vous puissiez donner la position de la souris au gestionnaire d'événements.

// IE 5.5+
element.fireEvent("onmouseover");
element.fireEvent("onmousedown");
element.fireEvent("onclick");  // or element.click()
element.fireEvent("onmouseup");

Simulation de la pression sur la touche et de la touche

Vous pouvez simuler les événements keydown et keypress, mais malheureusement dans Chrome ils ne déclenchent que les gestionnaires d'événements et n'effectuent aucune des actions par défaut. Je pense que c'est parce que le projet de travail DOM 3 Events décrit ce funky ordre des événements clés :

  1. keydown (a souvent une action par défaut telle que le déclic, l'envoi ou les événements textInput)
  2. appuyez sur la touche (si la touche n'est pas seulement une touche de modification comme Shift ou Ctrl)
  3. (keydown, keypress) avec repeat = true si l'utilisateur maintient le bouton enfoncé
  4. actions par défaut de keydown !!
  5. keyup

Cela signifie que vous devez (tout en peignant les brouillons HTML5 et Événements DOM ) simuler une grande partie de ce que le navigateur ferait autrement. Je déteste quand je dois faire ça. Par exemple, voici comment simuler une pression de touche sur une entrée ou une zone de texte.

// DOM 3 Events
var dispatchKeyboardEvent = function(target, initKeyboradEvent_args) {
  var e = document.createEvent("KeyboardEvents");
  e.initKeyboardEvent.apply(e, Array.prototype.slice.call(arguments, 1));
  target.dispatchEvent(e);
};
var dispatchTextEvent = function(target, initTextEvent_args) {
  var e = document.createEvent("TextEvent");
  e.initTextEvent.apply(e, Array.prototype.slice.call(arguments, 1));
  target.dispatchEvent(e);
};
var dispatchSimpleEvent = function(target, type, canBubble, cancelable) {
  var e = document.createEvent("Event");
  e.initEvent.apply(e, Array.prototype.slice.call(arguments, 1));
  target.dispatchEvent(e);
};

var canceled = !dispatchKeyboardEvent(element,
    'keydown', true, true,  // type, bubbles, cancelable
    null,  // window
    'h',  // key
    0, // location: 0=standard, 1=left, 2=right, 3=numpad, 4=mobile, 5=joystick
    '');  // space-sparated Shift, Control, Alt, etc.
dispatchKeyboardEvent(
    element, 'keypress', true, true, null, 'h', 0, '');
if (!canceled) {
  if (dispatchTextEvent(element, 'textInput', true, true, null, 'h', 0)) {
    element.value += 'h';
    dispatchSimpleEvent(element, 'input', false, false);
    // not supported in Chrome yet
    // if (element.form) element.form.dispatchFormInput();
    dispatchSimpleEvent(element, 'change', false, false);
    // not supported in Chrome yet
    // if (element.form) element.form.dispatchFormChange();
  }
}
dispatchKeyboardEvent(
    element, 'keyup', true, true, null, 'h', 0, '');

Je ne pense pas qu'il soit possible de simuler des événements clés dans IE.

75
yonran

vous pouvez déclencher l'événement click sur un élément en faisant

// this must be done after input1 exists in the DOM
var element = document.getElementById("input1");

if (element) element.click();

Exemple ici

9
Russ Cam

Ou encore plus court, avec uniquement du Javascript moderne standard:

var first_link = document.getElementsByTagName('a')[0];
first_link.dispatchEvent(new MouseEvent('click'));

Le new MouseEvent le constructeur prend un nom de type d'événement requis, puis un objet facultatif (au moins dans Chrome). Ainsi, vous pouvez, par exemple, définir certaines propriétés de l'événement:

first_link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true}));
7
chbrown

Pour simuler des événements de clavier dans Chrome:

Il existe un bogue connexe dans le kit Web qui fait que les événements clavier, lorsqu'ils sont initialisés avec initKeyboardEvent, obtiennent un keyCode et un charCode incorrects de 0: https://bugs.webkit.org/show_bug.cgi?id=16735

Une solution de travail pour cela est publiée dans this SO answer .

5
tanushree

L'accent pourrait être ce que vous recherchez. En tabulant ou en cliquant, je pense que vous voulez dire que l'élément doit être mis au point. Même code que Russ (Désolé, je l'ai volé: P) mais en tirant un autre événement.

// this must be done after input1 exists in the DOM
var element = document.getElementById("input1");

if (element) element.focus();
0
Mark Baijens