44

I wrote a Google Chrome extension and the site that I want to use my extension on requires me to click or tab onto a text box (because I think it runs javaScript verification "onClick" only). I can get the text in the box with my extension using:

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

But when I click submit, it thinks I did not enter anything in the "input1" text box because I never clicked it or tabbed on it.

Can someone help me get around this?

Adinia
  • 3,722
  • 5
  • 40
  • 58
milan
  • 2,179
  • 9
  • 24
  • 34

5 Answers5

82

Simulating a mouse click

My guess is that the webpage is listening to mousedown rather than click (which is bad for accessibility because when a user uses the keyboard, only focus and click are fired, not mousedown). So you should simulate mousedown, click, and mouseup (which, by the way, is what the iPhone, iPod Touch, and iPad do on tap events).

To simulate the mouse events, you can use this snippet for browsers that support DOM 2 Events. For a more foolproof simulation, fill in the mouse position using initMouseEvent instead.

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

When you fire a simulated click event, the browser will actually fire the default action (e.g. navigate to the link's href, or submit a form).

In IE, the equivalent snippet is this (unverified since I don't have IE). I don't think you can give the event handler mouse positions.

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

Simulating keydown and keypress

You can simulate keydown and keypress events, but unfortunately in Chrome they only fire the event handlers and don't perform any of the default actions. I think this is because the DOM 3 Events working draft describes this funky order of key events:

  1. keydown (often has default action such as fire click, submit, or textInput events)
  2. keypress (if the key isn't just a modifier key like Shift or Ctrl)
  3. (keydown, keypress) with repeat=true if the user holds down the button
  4. default actions of keydown!!
  5. keyup

This means that you have to (while combing the HTML5 and DOM 3 Events drafts) simulate a large amount of what the browser would otherwise do. I hate it when I have to do that. For example, this is roughly how to simulate a key press on an input or textarea.

// 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, '');

I don't think it is possible to simulate key events in IE.

yonran
  • 18,156
  • 8
  • 72
  • 97
  • In case anyone bumps into this looking for a **framework agnostic** way to fire any HTML and Mouse event (and set some options, if needed), have a look here: http://stackoverflow.com/questions/6157929/how-to-simulate-mouse-click-using-javascript/6158050#6158050 – TweeZz May 27 '11 at 23:14
  • @TweeZz, To be clear, I also did not rely on any libraries. But I do like the way you combined it all into one function. – yonran Jun 01 '11 at 02:04
  • :) Personally (if possible) I prefer an answer that I can just paste in my code to try it out :) – TweeZz Jun 01 '11 at 02:11
  • 6
    I have tried it (in Chrome Extension) and does not working... log from created Event show up that "which", "charCode" and "keyCode" are 0 instead of proper character/key code. Does anybody have the same problem? – hamczu Sep 17 '11 at 21:41
  • I'm having the same problem as @hamczu has someone already solved this? – ElHacker Oct 18 '11 at 21:21
  • 3
    @hamczu This [SO answer](http://stackoverflow.com/questions/10455626/keydown-simulation-in-chrome-fires-normally-but-not-the-correct-key/10520017#10520017) has a workaround for charCode = 0 issue. It is a [known bug in webkit](https://bugs.webkit.org/show_bug.cgi?id=16735) - has been open for around 5 years! – tanushree Dec 24 '12 at 16:01
  • @TweeZz looks like your framework agnostic method doesn't provide a way to do key events as this answer does, yes? – Michael Aug 15 '13 at 17:22
  • @Michael Yea, it does NOT support key events. – TweeZz Aug 15 '13 at 17:46
  • In Firefox, the document.createEvent('KeyboardEvents') call gives me an "Operation is not supported" exception in Firefox; furthermore the Mozilla documentation says that this method is deprecated in favor of event constructors... Looks like it should be "KeyboardEvent" (singular). – Michael Aug 15 '13 at 18:14
  • The initKeyBoardEvent function is not found in the latest Firefox. There is initKeyEvent ("Gecko specific"?) but that function doesn't take the same number of parameters. – Michael Aug 15 '13 at 18:21
  • Any solution for dispatching keyboard events in a Chrome Extension? – David Da Silva Contín Oct 21 '13 at 16:27
  • 1
    This code does not work anymore in the newest version of chrome as of 2016-09-17 – Samul Sep 17 '16 at 13:40
  • 2
    This code does not work anymore in the newest version of chrome as of 2017-01-08, this answer needs update! –  Jan 08 '17 at 20:47
8

you can raise the click event on an element by doing

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

if (element) element.click();

Example here

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
7

Or even shorter, with only standard modern Javascript:

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

The new MouseEvent constructor takes a required event type name, then an optional object (at least in Chrome). So you could, for example, set some properties of the event:

first_link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true}));
chbrown
  • 11,865
  • 2
  • 52
  • 60
5

For simulating keyboard events in Chrome:

There is a related bug in webkit that keyboard events when initialized with initKeyboardEvent get an incorrect keyCode and charCode of 0: https://bugs.webkit.org/show_bug.cgi?id=16735

A working solution for it is posted in this SO answer.

Community
  • 1
  • 1
tanushree
  • 763
  • 1
  • 7
  • 20
0

Focus might be what your looking for. With tabbing or clicking I think u mean giving the element the focus. Same code as Russ (Sorry i stole it :P) but firing an other event.

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

if (element) element.focus();
Mark Baijens
  • 13,028
  • 11
  • 47
  • 73
  • Thanks, I tried this also, along with the click, but the site still thinks I am not typing anything in.... – milan Nov 11 '10 at 21:12