Channel72
Channel72

Reputation: 24719

Forwarding an event in Javascript

Is there a simple way to "forward" an event in Javascript? My ultimate objective here is to enhance UI responsiveness in the following manner: I have a website with a single input text field that submits a query to a backend database. If the user presses a key when the input field is not in focus, I'd like to capture the keypress event at the document level, and forward it to the input field. (This seems like a fairly common way to enhance UI responsiveness, for example, Google does this with their main search site.)

So I have a text input field like this:

<input id="query" onkeydown="f(event)">

And I attempt to forward the event like this:

function handler(ev)
{
    var query = document.getElementById("query");
    query.dispatchEvent(ev);
}

document.addEventListener("keydown", handler, false);

Now, ignoring the cross-browser issues with addEventListener and dispatchEvent, this doesn't even work on Firefox which supports both of those functions. The Javascript interpreter throws an exception: Error: uncaught exception: [Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsIDOMEventTarget.dispatchEvent]"

So, is it even possible to forward events like this? Or do I need to create a new event using initKeyEvent and then dispatch that event to the input element?

Upvotes: 8

Views: 8178

Answers (3)

Erik Koopmans
Erik Koopmans

Reputation: 2422

Following up on @Bergi's answer, the solution that works for me is to simply redirect the focus - that way the event will go where you want it to! For instance:

document.addEventListener('keydown', function(evt) {
    document.getElementById('query').focus();
}, false);

This redirects all keydown events to the query element.

Upvotes: 1

Wilk
Wilk

Reputation: 8113

Here's an example of keyboard events:

HTML file (index.html):

<!DOCTYPE html>
<html>
    <head>
        <title>Stackoverflow</title>
        <script type="text/javascript" src="sof.js"> </script>
    </head>
    <body>
        <input id="query" onkeydown="f(event);"/>
    </body>
</html>

Javascript file (sof.js):

function simulateKeyDown () {
    // DOM Level 3 events
    var evt = document.createEvent ("KeyboardEvent");
    // DOM Level 3 events
    evt.initKeyboardEvent ("keydown", false, false, null, false, false, false, false, 0, 0);
    var query = document.getElementById ('query');
    query.dispatchEvent (evt);
}

window.onload = function () {
    document.addEventListener ('keydown', simulateKeyDown, false);
}

function f (ev) {
    console.log ('ciao');
}

As you can see, when the window is loaded it attaches a new handler to the keydown event of the document. When a key is pressed, a new KeyboardEvent event is created, intialized (with 'keydown') and then dispatched to the input element. Yes, it's a little complex and intricate but it works ;)

For further infos:

  1. Create Event
  2. Event initKeyEvent

Upvotes: 3

Bergi
Bergi

Reputation: 664434

I'm not sure about forwarding, but I think you can't. Yet, my solution to the initial problem is

document.addEventListener("keydown", function(e) {
    if (e.target.oMatchesSelector("form *, fieldset *, input, textarea"))
        return; // Opera-specific, but I think you get the point of MatchesSelector
    if (e.metaKey || e.ctrlKey)
        return;
    if (e.keyCode < 46 || e.keyCode > 90)
        return;
    document.getElementById("query").focus();
}, false);

The keydown event is not repsonsible for the chararcter input, so focusing the input will be enough onkeydown - the character will appear onkeyup.

Upvotes: 1

Related Questions