用JavaScript模拟在鼠标单击时按下多个键的方法是什么?

4
我正在开发一个Chrome扩展,以便使Netflix视频播放器打开隐藏的更改画质面板。
Netflix会根据您的互联网速度自动更改视频质量。
但是有一种已知的方法可以打开隐藏的面板并手动更改质量。
这是在HTML5播放器中打开隐藏面板的方法:只需按下CTRL + SHIFT + ALT + S即可。
当用户单击标题时,是否有一种方式可以模拟键盘键CTRL + SHIFT + ALT + S
$('body').on('click', 'div.player-status .player-status-main-title', function () {
    alert('Clicked!');
    //Simulate?
});

如果它是一个HTML5的函数,那就意味着它是在JavaScript中运行的。为什么不完全跳过按键步骤,直接识别并触发打开面板的函数呢? - DiMono
@DiMono 我尝试过,但我不太擅长 JavaScript,我无法识别该函数。如果你需要 Netflix 帐户自己尝试,我可以提供帐户。 - Jim
2个回答

11

尝试这个(无法测试,因为我无法访问Netflix 已测试,截至11.11.14确认可用)。

function simulateCtrlShiftAltS() {
  // Prepare function for injection into page
  function injected() {
    // Adjust as needed; some events are only processed at certain elements
    var element = document.body;

    function keyEvent(el, ev) {
      var eventObj = document.createEvent("Events");
      eventObj.initEvent(ev, true, true);

      // Edit this to fit
      eventObj.keyCode = 83;
      eventObj.which = 83;
      eventObj.ctrlKey = true;
      eventObj.shiftKey = true;
      eventObj.altKey = true;

      el.dispatchEvent(eventObj);
    }

    // Trigger all 3 just in case
    keyEvent(element, "keydown");
    keyEvent(element, "keypress");
    keyEvent(element, "keyup");
  }

  // Inject the script
  var script = document.createElement('script');
  script.textContent = "(" + injected.toString() + ")();";
  (document.head||document.documentElement).appendChild(script);
  script.parentNode.removeChild(script);
}

这段代码是从你链接的答案的评论中修改而来:https://dev59.com/8Gkv5IYBdhLWcg3wpCTJ#10520017

更精确地说,是根据这个示例:http://jsbin.com/awenaq/4

关于“根据需要进行调整”:

有些页面在元素上处理事件,有些则等待事件冒泡到类似于bodydocument的东西。您可以通过进入Dev工具、源并启用Event Listener Breakpoints > Keyboard来进行监视。从那里,您将能够看到哪个事件触发所需的更改,以及哪个元素捕获它 - 当断点触发时,它将在this中。

此外,请注意,如果播放器实际上是插件,则所有这些内容可能都无法正常工作。我在YouTube HTML5播放器上测试了这一点:对于除全屏以外的所有内容都起作用(我认为这是一种安全限制?),而且被处理的元素是#movie_player


谢谢,看起来你的代码触发了按键(我检查了控制台,确定它正在工作),但 Netflix 没有像我自己按键那样响应!......如果你需要 Netflix 账户来尝试一下,我可以提供给你账户,只需要私人方式发送我的账户给你。 - Jim
我已经尝试了,这是我的结果:http://jsfiddle.net/Jim_Toth/yn9804q5/。请查看第18531行,我试图触发函数本身,但是我在控制台中得到了错误Uncaught ReferenceError: m未定义。 - Jim
你不应该尝试触发函数;你只需要知道哪个元素捕获了事件。在断点被触发的那一刻,这将是作用域变量中的 this - Xan
这个:body#page-WiPlayer.ua-chrome.ua-chrome-38.le-blink.os-win.os-win-81.ua-not-ie.sc-wn.sc-strm.struts.global-header - Jim
这是用于手动触发事件并实际显示界面的吗? - Xan
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/64715/discussion-between-xan-and-jim。 - Xan

1
由于不确定 Netflix 播放器代码是否使用 jQuery 设置事件监听器,我建议使用本机 js 事件的解决方案。Netflix 可能需要更自然的事件时间,而不是在 1ms 内触发四个按键事件(请参阅此 SO-问题)。
下面的函数创建了四个本机的 keydown-KeyboardEvents,按照您给定的顺序具有正确的属性。它们之间以 50ms 的延迟触发,以模拟更自然的行为。我添加了一个紧随其后的 keypress-事件与 'S',因为某些设备会触发该事件。
在超时中,使用 IIFE(立即调用的函数表达式)将事件作为参数传递到超时回调中。
function simulateCtrlShiftAltS() {
    var keys = [
            {view: document.defaultView, bubbles: true, location: 1, keyLocation: 1, keyIdentifier: 'U+0017', key: 'Control', keyCode: 17, which: 17, altKey: false, ctrlKey: true, shiftKey: false},
            {view: document.defaultView, bubbles: true, location: 1, keyLocation: 1, keyIdentifier: 'U+0016', key: 'Shift', keyCode: 16, which: 16, altKey: false, ctrlKey: true, shiftKey: true},
            {view: document.defaultView, bubbles: true, location: 1, keyLocation: 1, keyIdentifier: 'U+0018', key: 'Alt', keyCode: 18, which: 18, altKey: true, ctrlKey: true, shiftKey: true},
            {view: document.defaultView, bubbles: true, location: 0, keyLocation: 0, keyIdentifier: 'U+0053', key: 'S', keyCode: 83, which: 83, altKey: true, ctrlKey: true, shiftKey: true}
        ], body = document.body;
    for (var i = 0; i < 5; i++) {
        var events = [new KeyboardEvent(i == 4 ? 'keyup' : 'keydown', keys[i] || keys[3])];
        if (i == 3) events.push(new KeyboardEvent('keypress', keys[i]));
        if (events[0].keyCode == 0) events.forEach(function(ev) {
            ['keyCode', 'which'].forEach(function(p) {
                delete ev[p]; Object.defineProperty(ev, p, {value: (keys[i] || keys[3])[p], enumerable: true});
            });
        });
        window.setTimeout(function(evts) {
            return function() {evts.forEach(function(ev) {body.dispatchEvent(ev);});};
        }(events), i * 50);
    }
}

你可以将函数直接传递给点击处理程序:
$('body').on('click', 'div.player-status .player-status-main-title', simulateCtrlShiftAltS);
编辑:发现Webkit浏览器没有正确设置keyCodewhich属性。我不建议使用.initKeyboardEvent(),因为它已经过时,并且浏览器处理方式非常不同。因此,我添加了一种方法来重新定义事件对象中的这些属性。它的灵感来自于这个SO问题上termi的回答。我还从T切换到了S

现在这个FIDDLE适用于FF、Chrome和Opera,但不适用于IE和Safari(没有实现KeyboardEvent API)。我将尝试找到并实现一个简单的解决方案。

编辑2:由于仍然无法正常工作,我们在'S'上添加了一个keyup事件。请参见更改后的代码。如果这还不够,我们将逐步释放ALT、SHIFT和CTRL,然后放弃。


1
有时候可能需要将这段代码注入到页面内容中 - Xan
我在 Netflix 上进行了测试,但它无法正常工作... 我认为传递 T 存在问题。请参见 http://jsfiddle.net/Jim_Toth/0wuj6s2j/1/,当我删除 T 键检查器时,它可以正常工作,请参见此处:http://jsfiddle.net/Jim_Toth/0wuj6s2j/。 - Jim
@Jim T-keyCode 是 84 而不是 16(你的警告框)。在 FF 中它可以工作。但是 Webkit 在初始化 KeyboardEvent 时总是将 keyCode 设置为 0。不知道为什么,我会寻找解决方案。 - Martin Ernst
顺便说一下,键不是(T),而是(S),对此很抱歉...还请从$('body').on('click', 'div.player-status .player-status-main-title'中删除额外的}。 - Jim
@MartinErnst 我测试了新的编辑,但不幸的是我遇到了与Xan的代码相同的问题,Netflix没有响应触发器,就像当我按键盘上的键时一样 :( - Jim
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接