是否有可能以编程方式模拟按键事件?
是否有可能在JavaScript中以编程方式模拟按键事件?
在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);
如果你可以使用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"); });
你可以做的是通过触发keyevents以编程方式触发keyevent监听 器 。 从沙盒安全angular度来看,这是有道理的。 使用这个能力,你可以应用一个典型的观察者模式 。 你可以把这个方法称为“模拟”。
下面是一个如何在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]方式来实际触发keyevents离开浏览器 – 沙箱。 所有主stream浏览器厂商都将坚持这一安全理念。
对于基于NPAPI的Adobe Flash等插件,以及绕过沙盒的许可证,这些插件正在逐步淘汰 ; Firefox 。
详细说明:
你不能,也不能出于安全原因(如Pekka已经指出的)。 您将始终需要用户之间的交互。 另外想象一下浏览器厂商被用户起诉的可能性,因为各种程序化的键盘事件都会导致欺骗攻击。
看到这个职位的替代品和更多的细节。 总是有基于闪存的复制和粘贴。 这是一个很好的例子 。 同时,这也certificate了为什么networking正在从插件供应商那里转移。
在selectjoinCORS策略的情况下,采用类似的安全思想来以编程方式访问远程内容。
答案是:
在正常情况下,无法在沙盒浏览器环境中以编程方式触发input密钥 。
底线:我并不是说在未来的特定浏览器模式和/或特权下,游戏的最终目标或类似的用户体验是不可能的。 然而,在进入这种模式之前,用户将被要求权限和风险,类似于Fullscreen API模型 。
有用的:在KeyCodes的情况下, 这个工具和键码映射将派上用场。
披露:答案是基于这里的答案。
你可以使用dispatchEvent()
:
function simulateKeyPress() { var evt = document.createEvent("KeyboardEvent"); evt.initKeyEvent("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"); } }
我没有testing这个,但它是从dispatchEvent()的文档中的代码改编的 。 您可能需要阅读该文档,以及createEvent()和initKeyEvent()的文档。
您可以创build和分派键盘事件,并且它们将触发适当的注册事件处理程序,但是,例如,如果分派给input元素,它们将不会生成任何文本 。
要完全模拟文本input,您需要生成一系列键盘事件,并明确设置input元素的文本。 事件的顺序取决于你想如何彻底模拟文本input。
最简单的forms是:
$('input').val('123'); $('input').change();
基于alex2k8的答案,这里是一个修改后的版本,适用于jQuery支持的所有浏览器(问题出在jQuery.event.trigger的缺失参数上,使用内部函数时很容易被忽略)。
// 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'); });
你甚至可以进一步推动它,让它不仅模拟事件,而且实际插入字符(如果它是一个input元素),但是当试图这样做时,有很多跨浏览器的问题。 更好地使用像SendKeys这样更复杂的插件。
您可以像这样在元素上分派键盘事件
element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));
这种方法支持跨浏览器更改关键代码的价值。 资源
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);
对于那些有兴趣的人来说,事实上可以可靠地重新创build键盘input事件。 为了改变input区域中的文本(移动光标,或通过input字符的页面),您必须严格遵循DOM事件模型: http : //www.w3.org/TR/DOM-Level-3-Events/ #h4_events-inputevents
模型应该这样做:
- 焦点(与目标集合一起发送到DOM上)
然后对于每个人物:
- keydown(发送到DOM)
- 在input之前(如果其为textarea或input,则在目标上发送)
- 按键(在DOM上发送)
- input(如果有textarea或input,则发送到目标)
- 改变(如果它的select是在目标上发送的)
- keyup(在DOM上发送)
然后,可选地对于大多数:
- 模糊(与目标集合在DOM上分派)
这实际上通过JavaScript更改页面中的文本(不修改值语句),并适当地设置任何JavaScript的监听器/处理程序。 如果你搞乱了顺序,javascript将不会以适当的顺序触发,input框中的文本将不会改变,select不会改变,或者光标不会移动到文本区域中的下一个空格。
不幸的是,这些代码是为NDA编写的,所以我不能共享它,但这肯定是可能的,但是您必须按照正确的顺序为每个元素重新创build整个键盘input“堆栈”。
只是使用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前想要模拟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})
这里有一个真正有帮助的图书馆: https : //cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js
我不知道它是从哪里来的,但它是有帮助的。 它将一个.simulate()
方法添加到window.KeyEvent
,所以您只需使用KeyEvent.simulate(0, 13)
window.KeyEvent
KeyEvent.simulate(0, 13)
来模拟一个'Q'
的enter
或KeyEvent.simulate(81, 81)
window.KeyEvent
KeyEvent.simulate(81, 81)
。
我在https://github.com/ccampbell/mousetrap/tree/master/tests 。
这工作对我来说,它确实模拟了我textaera的关键。 如果你想为整个页面只是把KeySimulation()
放在<body>
像这样<body onmousemove="KeySimulation()">
或者如果不是onmousemover
那么onmouseover
或onload
也可以。
<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>
你应该使用一些JS库支持包装DOM事件模型。 在那里,你可以开火和testing你的处理程序。