JavaScript : Simulate Key Events into Textbox/Input

13,888

Solution 1

I'm pretty certain that this is a "security" thing, as I've run into the same thing when trying to simulate key presses before.

Q: How can I type programatically then?
A: Getting/setting selectionStart, selectionEnd, etc, as well as using these in combination with String methods like slice to insert characters. (See HTMLTextAreaElement reference)

Q: Why would you still use this kind of event then?
A: All of the event listeners will work as if it was a real key event.


Reduced functionality for arrows/home/end can be achieved thusly DEMO

function homeKey(elm) {
    elm.selectionEnd =
        elm.selectionStart =
            elm.value.lastIndexOf(
                '\n',
                elm.selectionEnd - 1
            ) + 1;
}

function endKey(elm) {
    var pos = elm.selectionEnd,
        i = elm.value.indexOf('\n', pos);
    if (i === -1) i = elm.value.length;
    elm.selectionStart = elm.selectionEnd = i;
}

function arrowLeft(elm) {
    elm.selectionStart = elm.selectionEnd -= 1;
}

function arrowRight(elm) {
    elm.selectionStart = elm.selectionEnd += 1;
}

function arrowDown(elm) {
    var pos = elm.selectionEnd,
        prevLine = elm.value.lastIndexOf('\n', pos),
        nextLine = elm.value.indexOf('\n', pos + 1);
    if (nextLine === -1) return;
    pos = pos - prevLine;
    elm.selectionStart = elm.selectionEnd = nextLine + pos;
}

function arrowUp(elm) {
    var pos = elm.selectionEnd,
        prevLine = elm.value.lastIndexOf('\n', pos),
        TwoBLine = elm.value.lastIndexOf('\n', prevLine - 1);
    if (prevLine === -1) return;
    pos = pos - prevLine;
    elm.selectionStart = elm.selectionEnd = TwoBLine + pos;
}

Q: Where does it go wrong?
A: If lines are long enough to be wrapped, it will treat them as if unwrapped.

Solution 2

Sending keys to the browser can be achieved via Selenium: http://docs.seleniumhq.org/

It provides a driver for each browser that can be programmed. It usually starts with opening a URL then your script will act as a remote control to the browser. Thus allowing you to send actual keys rather than simulating them which is not possible programatically within the browser.

You could for instance achieve this using http://webdriver.io/

Share:
13,888
lexasss
Author by

lexasss

Updated on July 26, 2022

Comments

  • lexasss
    lexasss almost 2 years

    Despite many article on SO on how to simulate key presses (keydown/keypress) in JS, no one solution seems to be working with the browsers I'm using (Firefox ESR 17.0.7, Chrome 28.0.1500.72, IE 10). The solutions I have tested were taken from here, here, and here.

    What I'm trying to do is to simulate ANY keystroke in a textarea / input. While I can append / delete characters directly changing "value", I see no option but input simulation for the keys like "Up", "Down", "Home", and some others.

    According to the documentation, it should be simple. For example:

    var e = document.createEvent("KeyboardEvent");
    if (e.initKeyboardEvent) {  // Chrome, IE
        e.initKeyboardEvent("keydown", true, true, document.defaultView, "Enter", 0, "", false, "");
    } else { // FF
        e.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, 13, 0);
    }
    document.getElementById("text").dispatchEvent(e);
    

    indeed fires the "Enter" keydown event, and my handler can catch it. However, it does not affect the textarea in any way - a new line does not appear. Same for other key-codes: characters do not appear, arrows do not change the caret's location, etc.

    I have extended the code by Orwellophile and posted it to http://jsfiddle.net/npF3d/4/ , so anyone can play with the code. In my browsers, no button produces any effect on the textarea in any condition.

    I would appreciate any help on this issue.

  • lexasss
    lexasss almost 11 years
    OK, I had the same feeling that this could be done intentionally for security reasons. As of Q/A: editing text is not a problem, the problem is to simulate "Up", "Down", "Home" and the like...
  • Paul S.
    Paul S. almost 11 years
    those could possibly be implemented if you re-create the textarea/input as a block node containing inline nodes for each character with matching wrapping, size and styling, then calculating all the different rects to find where you want to end up. I can't imagine it being easy to implement... perhaps a cleaner way would be use a monospace font, work out where the previous new line character was and then just count characters.
  • lexasss
    lexasss almost 11 years
    Thanks. However, I simulate the input on third pages, like google.com. My virtual keyboard is implemented as a Chrome extension and must be capable to allow users type and modify text in forms on any page using only this keyboard. It would be a great disappointment if some functionality must be dropped.
  • lexasss
    lexasss almost 11 years
    Thanks for this solution, @Paul S, I was thinking about same but you made my task easier. I'll try next to update your solution so that it works even if a line is wrapped, but with a little hope.
  • mommomonthewind
    mommomonthewind over 9 years
    The solution is great, but can I simulate the typing? Could you give an example such as typing "abc" to the textbox? Thanks so much