是否可以在JavaScript中以编程方式模拟按键事件?


当前回答

对于那些感兴趣的人,您可以可靠地重新创建键盘输入事件。为了更改输入区域中的文本(移动游标,或通过输入字符移动页面),必须严格遵循DOM事件模型:http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents

该模型应该做到:

焦点(使用目标设置在DOM上分派)

然后对于每个字符:

keydown(在DOM上分派) Beforeinput(如果它是一个文本区域或输入,在目标分派) 按键(在DOM上分派) 输入(如果是文本区域或输入,则在目标处分派) 改变(如果它是一个选择,在目标分派) keyup(在DOM上分派)

然后,可选的大多数:

模糊(随目标设置在DOM上分派)

这实际上是通过javascript改变页面中的文本(不修改值语句),并适当地设置任何javascript侦听器/处理程序。如果你把顺序弄乱了,javascript就不会按适当的顺序触发,输入框中的文本不会改变,选择不会改变,或者光标不会移动到文本区域的下一个空格。

不幸的是,代码是为雇主写的,所以我不能分享它,但这绝对是可能的,但你必须以正确的顺序为每个元素重新创建整个关键输入“堆栈”。


编辑:我不是这个答案的原始海报,但我已经测试过了,我不能让它更新输入字段。下面是一个代码片段,其中的代码供其他人尝试或查看

let element = document.querySelector('input'); element.onkeydown = e => console.log('keydown on element: ' + e.key); document.onkeydown = e => console.log('keydown on document: ' + e.key + " " + e.target); dispatchButton.onclick = () => dispatchKey(element, 'a') dispatchKey = (target, key) => { let dom = document; // focus (dispatched on the DOM with the target set) let ev = new Event('focus', {target: target}); // this part seems to not work? when logging the // target in the onkeypress function it shows `document` instead of `input` // I also tried these and got the same behavior // ev.target = target; // and // Object.defineProperty(ev, 'target', {writable: false, value: target}); dom.dispatchEvent(ev); // keydown (dispatched on the DOM) dom.dispatchEvent(new KeyboardEvent('keydown', {'key': key, target: target})); // beforeinput (dispatched at the target if it's a textarea or input) target.dispatchEvent(new Event('beforeinput')); // keypress (dispatched on the DOM) dom.dispatchEvent(new KeyboardEvent('keypress', {'key': key})); // input (dispatched at the target if it's a textarea or input) target.dispatchEvent(new Event('input')); // change (dispatched at the target if it's a select) // keyup (dispatched on the DOM) dom.dispatchEvent(new KeyboardEvent('keyup', {'key': key})); // Then, optionally for most: // blur (dispatched on the DOM with the target set) dom.dispatchEvent(new Event('blur', {target: target})); console.log('dispatched'); } <input/> <button id="dispatchButton">Press to dispatch events </button>

其他回答

您可以创建和分派键盘事件,它们将触发相应的已注册事件处理程序,但是,如果分派到input元素,则不会产生任何文本。

要完全模拟文本输入,您需要生成一系列键盘事件,并显式地设置input元素的文本。事件的顺序取决于模拟文本输入的彻底程度。

最简单的形式是:

$('input').val('123');
$('input').change();

只需使用CustomEvent

Node.prototype.fire=function(type,options){
     var event=new CustomEvent(type);
     for(var p in options){
         event[p]=options[p];
     }
     this.dispatchEvent(event);
}

4 ex想模拟ctrl+z

window.addEventListener("keyup",function(ev){
     if(ev.ctrlKey && ev.keyCode === 90) console.log(ev); // or do smth
     })

 document.fire("keyup",{ctrlKey:true,keyCode:90,bubbles:true})

基于@aljgom的回答:

这对我来说很有效。而不是像aljgom建议的那样将事件分派给元素,而是将它分派给文档。

document.dispatchEvent(new KeyboardEvent("keydown", { key: "c" }));

这就是我在chrome中使用js/typescript所做的尝试。多亏了 这是灵感的答案。

var x = document.querySelector('input');

var keyboardEvent = new KeyboardEvent("keypress", { bubbles: true });
// you can try charCode or keyCode but they are deprecated
Object.defineProperty(keyboardEvent, "key", {
  get() {
    return "Enter";
  },
});
x.dispatchEvent(keyboardEvent);

{ // example document.querySelector('input').addEventListener("keypress", e => console.log("keypress", e.key)) // unfortunatelly doesn't trigger submit document.querySelector('form').addEventListener("submit", e => { e.preventDefault(); console.log("submit") }) } var x = document.querySelector('input'); var keyboardEvent = new KeyboardEvent("keypress", { bubbles: true }); // you can try charCode or keyCode but they are deprecated Object.defineProperty(keyboardEvent, "key", { get() { return "Enter"; }, }); x.dispatchEvent(keyboardEvent); <form> <input> </form>

你可以用下面的代码模拟输入密码:

铬测试100%工作

DoCustomEvent('password', '#loginpin');



function DoCustomEvent(ct, elem){
var key;
var pressEvent = document.createEvent("CustomEvent");
pressEvent.initCustomEvent("keypress", true, false);

for (var i =0; i < ct.length; ++i)
{
    key                     = ct.charCodeAt(i);
    pressEvent.bubbles      = true;
    pressEvent.cancelBubble = false;
    pressEvent.returnValue  = true;
    pressEvent.key          = ct.charAt(i);
    pressEvent.keyCode      = key;
    pressEvent.which        = key;
    pressEvent.charCode     = key;
    pressEvent.shiftKey     = false;
    pressEvent.ctrlKey      = false;
    pressEvent.metaKey      = false;

    document.querySelector(elem).focus();

    //keypress //beforeinput //input //sendkeys //select
    setTimeout(function() {
        var e = new window.KeyboardEvent('keypress', pressEvent);
        document.activeElement.dispatchEvent(e);
        e = new window.KeyboardEvent('input', pressEvent);
        document.activeElement.dispatchEvent(e);

    }, 0);

    document.querySelector(elem).value = document.querySelector(elem).value + ct.charAt(i);
}