質問

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.

役に立ちましたか?

解決

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.

他のヒント

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/

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top