chrome extension: how to send 'keydown' event to page's input?

I have a test web page that alerts if i hit a key in it's input field:

<!doctype html>
<html>
<head>
  <script type="text/javascript" src="jquery-1.9.1.min.js"></script>
  <script>
    $( document ).ready( function() {
      $( '#foo' ).keydown( function() { alert( "debug" ); } );
    });
  </script>
</head>
<body>
  <input id='foo' type='type'/>
</body>
</html>

And i have this chrome extension that modifies input text and fires keydown event:

$( document ).ready( function() {
  window.setTimeout( function() {
    $( '#foo' ).val( "foo" );
    $( '#foo' ).keydown();
  }, 2000 );
});

If i install extension, after 2 seconds (as expected) text is modified - but alert is not displayed, so i can suggest that keydown event is not passed from extension sandbox into page javascript handler. Is it possible to modify my code somehow so extension can emulate keydown that javascript on the page can see? I'm automating a third-party website via chrome extension, and one of the inputs requires keyup to detect value change (the page i'm automating is written badly - but i don't have any control other it's source code).


Solution 1:

Your code is not working because jQuery's keydown() method does not actually trigger a "real" keydown event. Instead, jQuery looks up the "bound" event handlers in jQuery.cache, and calls the corresponding functions.

Since your content script's jQuery object differs from the page's jQuery object, invoking .keydown() doesn't cause any action.

In your case, I suggest to inject your code in the page, so that your code runs in the same context as the page. Then, calling $('#foo').keydown() will use the page's jQuery object, and result in the expected behaviour.

A general solution, which doesn't depend on any library is to use the KeyboardEvent constructor (defined in DOM4) to trigger the event:

var event = new KeyboardEvent('keydown');
document.querySelector('#foo').dispatchEvent(event);