是否可以通过编程方式模拟按键事件?

时间:2009-02-27 20:17:12

标签: javascript javascript-events

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

23 个答案:

答案 0 :(得分:159)

适用于webkit和gecko的非jquery版本:

var keyboardEvent = document.createEvent("KeyboardEvent");
var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";


keyboardEvent[initMethod](
                   "keydown", // event type : keydown, keyup, keypress
                    true, // bubbles
                    true, // cancelable
                    window, // viewArg: should be window
                    false, // ctrlKeyArg
                    false, // altKeyArg
                    false, // shiftKeyArg
                    false, // metaKeyArg
                    40, // keyCodeArg : unsigned long the virtual key code, else 0
                    0 // charCodeArgs : unsigned long the Unicode character associated with the depressed key, else 0
);
document.dispatchEvent(keyboardEvent);

答案 1 :(得分:68)

如果你可以使用jQuery 1.3.1:

function simulateKeyPress(character) {
  jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}

$(function() {
  $('body').keypress(function(e) {
    alert(e.which);
  });

  simulateKeyPress("e");
});

答案 2 :(得分:45)

您可以通过触发 keyevents 以编程方式触发 keyevent侦听器。从沙盒安全角度来看,允许这样做是有意义的。使用此功能,您可以应用典型的observer-pattern。您可以将此方法称为“模拟”。

以下是如何在W3C DOM标准和jQuery中实现此目的的示例:

function triggerClick() {
  var event = new MouseEvent('click', {
    'view': window,
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.querySelector('input[type=submit][name=btnK]'); 
  var canceled = !cb.dispatchEvent(event);
  if (canceled) {
    // preventDefault was called and the event cancelled
  } else {
    // insert your event-logic here...
  }
}

此示例改编自:https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

在jQuery中:

jQuery('input[type=submit][name=btnK]')
  .trigger({
    type: 'keypress',
    which: character.charCodeAt(0 /*the key to trigger*/)      
   });

但是最近,没有[DOM]方法实际触发离开浏览器沙箱的关键事件。并且所有主要的浏览器供应商都会遵守这个安全概念。

对于基于NPAPI的Adobe Flash等插件,允许绕过沙箱:这些是phasing-out; Firefox

详细说明:

你不能也不能出于安全原因(正如Pekka已经指出的那样)。您将始终需要用户之间的互动。此外,想象一下浏览器供应商被用户起诉的可能性,因为各种程序化的键盘事件都会导致欺骗攻击。

有关替代方案和更多详细信息,请参阅此post。总有基于闪存的复制粘贴。这是一个优雅的example。与此同时,它也证明了网络正在逐渐远离插件供应商。

如果opt-in CORS policy以编程方式访问远程内容,则应用类似的安全思维模式。

答案是:
在正常情况下,无法以编程方式触发沙盒浏览器环境中的输入键

底线:我并不是说将来无法通过特殊的浏览器模式和/或特权来实现游戏的最终目标或类似的用户体验。但是,在输入此类模式之前,系统会要求用户提供权限和风险,类似于Fullscreen API model

有用:在KeyCodes的上下文中,this工具和键码映射会派上用场。

披露:答案基于答案here

答案 3 :(得分:21)

您可以使用dispatchEvent()

function simulateKeyPress() {
  var evt = document.createEvent("KeyboardEvent");
  evt.initKeyboardEvent("keypress", true, true, window,
                    0, 0, 0, 0,
                    0, "e".charCodeAt(0))
  var body = document.body;
  var canceled = !body.dispatchEvent(evt);
  if(canceled) {
    // A handler called preventDefault
    alert("canceled");
  } else {
    // None of the handlers called preventDefault
    alert("not canceled");
  }
}

我没有对此进行测试,但它是根据dispatchEvent()'s documentation上的代码改编的。您可能想要阅读它,以及createEvent()和initKeyEvent()的文档。

答案 4 :(得分:21)

您可以在像这样的元素上调度键盘事件

element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));

答案 5 :(得分:20)

您可以创建和发送键盘事件,它们将触发相应的已注册事件处理程序,但是如果将分配给输入元素,将不会生成任何文本

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

最简单的形式是:

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

答案 6 :(得分:13)

基于alex2k8的答案,这是一个修订版本,适用于jQuery支持的所有浏览器(问题在于缺少jQuery.event.trigger的参数,在使用该内部函数时很容易忘记)。 p>

// jQuery plugin. Called on a jQuery object, not directly.
jQuery.fn.simulateKeyPress = function (character) {
  // Internally calls jQuery.event.trigger with arguments (Event, data, elem).
  // That last argument, 'elem', is very important!
  jQuery(this).trigger({ type: 'keypress', which: character.charCodeAt(0) });
};

jQuery(function ($) {
  // Bind event handler
  $('body').keypress(function (e) {
    alert(String.fromCharCode(e.which));
    console.log(e);
  });
  // Simulate the key press
  $('body').simulateKeyPress('x');
});

你甚至可以进一步推动它,让它不仅模拟事件,而且实际插入角色(如果它是一个输入元素),但是在尝试这样做时有许多跨浏览器的问题。更好地使用更精细的插件,如SendKeys

答案 7 :(得分:8)

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

该模型应该:

  • 焦点(在具有目标集的DOM上调度)

然后为每个角色:

  • keydown(在DOM上发送)
  • beforeinput(如果是textarea或输入,则在目标处调度)
  • keypress(在DOM上发送)
  • 输入(如果是textarea或输入,则在目标处调度)
  • 更改(如果选择,则在目标处调度)
  • keyup(在DOM上发送)

然后,可选择大多数:

  • 模糊(使用目标集在DOM上调度)

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

不幸的是,代码是根据NDA为雇主编写的,因此我无法共享,但它绝对可以,但您必须以正确的顺序为每个元素重新创建整个键输入“堆栈”。

答案 8 :(得分:8)

在某些情况下,keypress事件无法提供所需的功能,通常情况下,事件会从两个因此触发的事件keydown中合并,并且对于相同的键,其后跟keyup 。所以只需逐个生成事件:

element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'}));
element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));

答案 9 :(得分:7)

此方法支持跨浏览器更改密钥代码的值。 Source

var $textBox = $("#myTextBox");

var press = jQuery.Event("keypress");
press.altGraphKey = false;
press.altKey = false;
press.bubbles = true;
press.cancelBubble = false;
press.cancelable = true;
press.charCode = 13;
press.clipboardData = undefined;
press.ctrlKey = false;
press.currentTarget = $textBox[0];
press.defaultPrevented = false;
press.detail = 0;
press.eventPhase = 2;
press.keyCode = 13;
press.keyIdentifier = "";
press.keyLocation = 0;
press.layerX = 0;
press.layerY = 0;
press.metaKey = false;
press.pageX = 0;
press.pageY = 0;
press.returnValue = true;
press.shiftKey = false;
press.srcElement = $textBox[0];
press.target = $textBox[0];
press.type = "keypress";
press.view = Window;
press.which = 13;

$textBox.trigger(press);

答案 10 :(得分:7)

只需使用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})

答案 11 :(得分:4)

这是一个真正有用的库:https://cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js

我不知道它来自哪里,但它很有帮助。它为.simulate()添加了window.KeyEvent方法,因此您只需使用KeyEvent.simulate(0, 13)来模拟enterKeyEvent.simulate(81, 81) 'Q'。< / p>

我在https://github.com/ccampbell/mousetrap/tree/master/tests得到了它。

答案 12 :(得分:4)

这对我有用,它确实模拟了我的textaera的键盘。如果您想要整个页面,只需将KeySimulation()放在<body> <body onmousemove="KeySimulation()">上,如果不是onmousemove,那么onmouseoveronload就可以了太

<script>
function KeySimulation()
{
var e = document.createEvent("KeyboardEvent");
if (e.initKeyboardEvent) {  // Chrome, IE
    e.initKeyboardEvent("keyup", true, true, document.defaultView, "Enter", 0, "", false, "");
} else { // FireFox
    e.initKeyEvent("keyup", true, true, document.defaultView, false, false, false, false, 13, 0);
}
document.getElementById("MyTextArea").dispatchEvent(e);
}
</script>

<input type="button" onclick="KeySimulation();" value=" Key Simulation " />
<textarea id="MyTextArea" rows="15" cols="30"></textarea>

答案 13 :(得分:3)

我想模拟一个“ Tab”按键...扩展Trevor的答案,我们可以看到确实按下了一个特殊的键(如“ tab”),但没有看到“ tab”按键的实际结果。有...

尝试为“ activeElement”和全局文档对象都调度这些事件-两者的代码都添加在下面;

摘要如下:

var element = document.getElementById("firstInput");

document.addEventListener("keydown", function(event) {

  console.log('we got key:', event.key, '  keyCode:', event.keyCode, '  charCode:', event.charCode);

  /* enter is pressed */
  if (event.keyCode == 13) {
    console.log('enter pressed:', event);

    setTimeout(function() {
      /*  event.keyCode = 13;  event.target.value += 'b';  */

      theKey = 'Tab';
      var e = new window.KeyboardEvent('focus', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
      e = new window.KeyboardEvent('keydown', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
      e = new window.KeyboardEvent('beforeinput', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
      e = new window.KeyboardEvent('keypress', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
      e = new window.KeyboardEvent('input', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
      e = new window.KeyboardEvent('change', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
      e = new window.KeyboardEvent('keyup', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.activeElement.dispatchEvent(e);
    }, 4);

    setTimeout(function() {
      theKey = 'Tab';
      var e = new window.KeyboardEvent('focus', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
      e = new window.KeyboardEvent('keydown', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
      e = new window.KeyboardEvent('beforeinput', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
      e = new window.KeyboardEvent('keypress', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
      e = new window.KeyboardEvent('input', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
      e = new window.KeyboardEvent('change', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
      e = new window.KeyboardEvent('keyup', {
        bubbles: true,
        key: theKey,
        keyCode: 9,
        charCode: 0,
      });
      document.dispatchEvent(e);
    }, 100);



  } else if (event.keyCode != 0) {
    console.log('we got a non-enter press...: :', event.key, '  keyCode:', event.keyCode, '  charCode:', event.charCode);
  }

});
<h2>convert each enter to a tab in JavaScript... check console for output</h2>
<h3>we dispatchEvents on the activeElement... and the global element as well</h3>

<input type='text' id='firstInput' />
<input type='text' id='secondInput' />

<button type="button" onclick="document.getElementById('demo').innerHTML = Date()">
    Click me to display Date and Time.</button>
<p id="demo"></p>

答案 14 :(得分:3)

这是我设法找到的:

function createKeyboardEvent(name, key, altKey, ctrlKey, shiftKey, metaKey, bubbles) {
  var e = new Event(name)
  e.key = key
  e.keyCode = e.key.charCodeAt(0)
  e.which = e.keyCode
  e.altKey = altKey
  e.ctrlKey = ctrlKey
  e.shiftKey = shiftKey
  e.metaKey =  metaKey
  e.bubbles = bubbles
  return e
}

var name = 'keydown'
var key = 'a'

var event = createKeyboardEvent(name, key, false, false, false, false, true)

document.addEventListener(name, () => {})
document.dispatchEvent(event)

答案 15 :(得分:3)

单行香草Javascript网络检查员在复制+粘贴 中准备好控制台(这个家伙已经对大多数开发者有吸引力了,所以不要'试着美化他 - 他应该是单身的......划船的)

    var pressthiskey = "q"/* <--- :) !? q for example */;
    var e = new Event("keydown");
    e.key = pressthiskey;
    e.keyCode = e.key.charCodeAt(0);
    e.which = e.keyCode;
    e.altKey = false;
    e.ctrlKey = true;
    e.shiftKey = false;
    e.metaKey = false;
    e.bubbles = true;
    document.dispatchEvent(e);

答案 16 :(得分:3)

这是一个适用于Chrome和Chromium的解决方案(仅测试了这些平台)。似乎Chrome有一些错误或自己的处理密钥代码的方法,所以这个属性必须单独添加到KeyboardEvent。

function simulateKeydown (keycode,isCtrl,isAlt,isShift){
    var e = new KeyboardEvent( "keydown", { bubbles:true, cancelable:true, char:String.fromCharCode(keycode), key:String.fromCharCode(keycode), shiftKey:isShift, ctrlKey:isCtrl, altKey:isAlt } );
    Object.defineProperty(e, 'keyCode', {get : function() { return this.keyCodeVal; } });     
    e.keyCodeVal = keycode;
    document.dispatchEvent(e);
}

答案 17 :(得分:1)

截至2019年,此解决方案对我有效:

document.dispatchEvent(
  new KeyboardEvent("keydown", {
    keyCode: 69, // example values
    code: "KeyE" // put everything you need in this object
  })
);

我在浏览器游戏中使用了此功能,以支持带有模拟键盘的移动设备。

答案 18 :(得分:1)

这就是我在chrome中尝试使用js / typescript的方法。谢谢 this answer寻求灵感。

'pkcs1'
const x = document.querySelector('input');

    const keyboardEvent = new KeyboardEvent("keypress", { bubbles: true });
    Object.defineProperty(keyboardEvent, "charCode", {
      get() {
        return 13;
      },
    });
    x.dispatchEvent(keyboardEvent);

答案 19 :(得分:0)

我知道这个问题需要一种模拟按键的javascript方法。但是对于那些正在寻找jQuery的工作方式的人:

var e = jQuery.Event("keypress");
e.which = 13 //or e.keyCode = 13 that simulates an <ENTER>
$("#element_id").trigger(e); 

答案 20 :(得分:0)

带有TypeScript支持的本地JavaScript的解决方案:

键入keyCode或您正在使用的任何属性,并将其强制转换为KeyboardEventInit

示例

const event = new KeyboardEvent("keydown", {
          keyCode: 38,
        } as KeyboardEventInit);

答案 21 :(得分:0)

使之生效的关键部分是要意识到charCodekeyCodewhichall deprecated methods。因此,如果代码 processing 的按键事件使用这三个事件中的任何一个,那么它将收到虚假的答案(例如,默认值为0)。

只要您使用不推荐使用的方法(例如key)访问按键事件,就可以了。

为完成此操作,我添加了触发事件的基本Javascript代码:

const rightArrowKey = 39
const event = new KeyboardEvent('keydown',{'key':rightArrowKey})
document.dispatchEvent(event)

答案 22 :(得分:0)

一旦用户按下有问题的密钥,您就可以存储对该密钥的引用,并在任何其他HTML元素上使用它:

&#13;
&#13;
EnterKeyPressToEmulate<input class="lineEditInput" id="addr333_1" type="text" style="width:60%;right:0%;float:right" onkeydown="keyPressRecorder(event)"></input>
TypeHereToEmulateKeyPress<input class="lineEditInput" id="addr333_2" type="text" style="width:60%;right:0%;float:right" onkeydown="triggerKeyPressOnNextSiblingFromWithinKeyPress(event)">
Itappears Here Too<input class="lineEditInput" id="addr333_3" type="text" style="width:60%;right:0%;float:right;" onkeydown="keyPressHandler(event)">
<script>
var gZeroEvent;
function keyPressRecorder(e)
{
  gZeroEvent = e;
}
function triggerKeyPressOnNextSiblingFromWithinKeyPress(TTT)
{
  if(typeof(gZeroEvent) != 'undefined')  {
TTT.currentTarget.nextElementSibling.dispatchEvent(gZeroEvent);
keyPressHandler(TTT);
  }
}
function keyPressHandler(TTT)
{
  if(typeof(gZeroEvent) != 'undefined')  {
TTT.currentTarget.value+= gZeroEvent.key;
event.preventDefault();
event.stopPropagation();
  }
}
</script>
&#13;
&#13;
&#13;

如果你创建自己的事件,你可以设置keyCode,你可以从任何真正的键盘事件中复制现有的参数(忽略目标,因为它是dispatchEvent的工作)和:

ta = new KeyboardEvent('keypress',{ctrlKey:true,key:'Escape'})