是否可以在JavaScript中以编程方式模拟按键事件?
一个非jquery版本,适用于webkit和gecko:
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, // view: should be window false, // ctrlKey false, // altKey false, // shiftKey false, // metaKey 40, // keyCode: unsigned long - the virtual key code, else 0 0 // charCode: 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监听器.从沙盒安全角度来看,允许这样做是有意义的.使用此功能,您可以应用典型的观察者模式.您可以将此方法称为"模拟".
下面是如何在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等插件,允许绕过沙箱:这些都是逐步淘汰的 ; 火狐.
详细说明:
你不能也不能出于安全原因(正如Pekka已经指出的那样).您将始终需要用户之间的互动.此外,想象一下浏览器供应商被用户起诉的可能性,因为各种程序化键盘事件将导致欺骗攻击.
有关替代品和更多详细信息,请参阅此帖 总有基于闪存的复制粘贴.这是一个优雅的 例子.与此同时,它证明了为什么网络正在远离插件供应商.
如果选择加入CORS策略以编程方式访问远程内容,则应用类似的安全思维模式.
答案是:
在正常情况下,无法以编程方式触发沙盒浏览器环境中的输入键.
底线:我并不是说将来,在特殊的浏览器模式和/或特权用于游戏的最终目标或类似的用户体验下,它是不可能的.但是,在进入此类模式之前,将要求用户提供权限和风险,类似于Fullscreen API模型.
有用:在KeyCodes的上下文中,此工具和键码映射将派上用场.
披露:答案是基于这里的答案.
您可以在像这样的元素上调度键盘事件
element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));
你可以使用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()文档中的代码改编的.您可能想要阅读它,以及createEvent()和initKeyEvent()的文档.
您可以创建和分派键盘事件,它们将触发相应的已注册事件处理程序,但是如果调度到输入元素,它们将不会生成任何文本.
要完全模拟文本输入,您需要生成一系列键盘事件,并显式设置input元素的文本.事件序列取决于您想要模拟文本输入的彻底程度.
最简单的形式是:
$('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');
});
你甚至可以进一步推动它,让它不仅模拟事件,而且实际插入角色(如果它是一个输入元素),但是在尝试这样做时有许多跨浏览器的问题.更好地使用像SendKeys这样更精细的插件.
在某些情况下,keypress
事件无法提供所需的功能,通常情况下,事件是由两个因此触发的事件组合而来的keypress
,并且后面的事件是keydown
相同的键.所以只需逐个生成事件:
element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'})); element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));
对于那些感兴趣的人,您可以实际上可靠地重新创建键盘输入事件.为了更改输入区域中的文本(移动游标,或通过输入字符移动页面),您必须密切关注DOM事件模型:http://www.w3.org/TR/DOM-Level-3-Events/ #h4_events-inputevents
该模型应该:
focus(在具有目标集的DOM上调度)
然后为每个角色:
keydown(在DOM上发送)
beforeinput(如果是textarea或输入,则在目标处调度)
keypress(在DOM上发送)
输入(如果是textarea或输入,则在目标处调度)
更改(如果选择,则在目标处调度)
keyup(在DOM上调度)
然后,可选择大多数:
模糊(使用目标集在DOM上调度)
这实际上通过javascript更改页面中的文本(不修改值语句)并适当地设置任何javascript侦听器/处理程序.如果你弄乱了序列javascript将不会以适当的顺序触发,输入框中的文本将不会改变,选择不会改变或光标不会移动到文本区域中的下一个空格.
不幸的是,代码是根据NDA为雇主编写的,因此我无法共享它,但它绝对可以,但您必须以正确的顺序为每个元素重新创建整个键输入"堆栈".
这种方法支持跨浏览器更改密钥代码的值. 资源
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);
只需使用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})