javascript 如何在Gmail中检测键盘事件

f45qwnt8  于 2023-05-12  发布在  Java
关注(0)|答案(2)|浏览(170)

我正在编写一个浏览器扩展,需要将处理程序附加到所有页面上的keyupkeydown事件。我可以用下面的内容脚本代码让它工作得很好。

document.addEventListener("keydown",keyDown, true);      
document.addEventListener("keyup", keyUp, true);

我不能让它在Gmail中工作。特别是我不能得到它的工作时,撰写一封新的电子邮件的主体。它会在我测试过的任何地方工作。我认为问题是因为Gmail在所有键盘事件上都调用stopPropagation,但很难调试它们的最小化代码。我以为将第三个参数设置为true会导致在CAPTURE_PHASE期间捕获事件,但这不起作用。
如何在Gmail中使用Google Chrome内容脚本编写新正文时捕获keyupkeydown事件?
编辑:
我已经通过将"all_frames": true,添加到我的清单中来确保我的内容脚本被注入到DOM的所有iframe中。我甚至尝试使用以下代码:

document.addEventListener("DOMNodeInserted", function (event) {
     if(event.type === "DOMNodeInserted") {
        if(event.srcElement.nodeName === "IFRAME") {
        console.log(event.srcElement.nodeName + " iframe detected");
        event.srcElement.addEventListener("keydown", function(kevent) {
            document.dispatchEvent(kevent);
            }, true);
        event.srcElement.addEventListener("keyup", function(kevent) {
            document.dispatchEvent(kevent);
            }, true);
        
    }
}
},true);

这仍然不能解决Gmail的问题。

x759pob2

x759pob21#

您的代码无法工作,因为event.srcElement引用的是<iframe>元素,而不是其内容。要访问其内容文档,必须等待加载框架(onload或轮询),然后使用frame.contentDocument访问框架。
从Chrome 37.0.1995.0开始,您还可以使用match_about_blank(带有all_frames)在about:blank帧中插入内容脚本,该脚本捕获事件并将其发送给父内容脚本。
下面是原始想法的实现示例(使用轮询):
manifest.json相关部分:

"content_scripts": [{
      "matches": ["*://mail.google.com/*"],
      "js": ["contentscript.js"],
      "run_at": "document_end"
  }],

contentscript.js

function keyDown(e) {console.log(e.which);}; // Test
function keyUp(e) {console.log(e.keyCode);}; // Test
(function checkForNewIframe(doc) {
    if (!doc) return; // document does not exist. Cya

    // Note: It is important to use "true", to bind events to the capturing
    // phase. If omitted or set to false, the event listener will be bound
    // to the bubbling phase, where the event is not visible any more when
    // Gmail calls event.stopPropagation().
    // Calling addEventListener with the same arguments multiple times bind
    // the listener only once, so we don't have to set a guard for that.
    doc.addEventListener('keydown', keyDown, true);
    doc.addEventListener('keyup', keyUp, true);
    doc.hasSeenDocument = true;
    for (var i = 0, contentDocument; i<frames.length; i++) {
        try {
            contentDocument = iframes[i].document;
        } catch (e) {
            continue; // Same-origin policy violation?
        }
        if (contentDocument && !contentDocument.hasSeenDocument) {
            // Add poller to the new iframe
            checkForNewIframe(iframes[i].contentDocument);
        }
    }
    setTimeout(checkForNewIframe, 250, doc; // <-- delay of 1/4 second
})(document); // Initiate recursive function for the document.

请注意,我使用轮询而不是DOM突变事件,因为后者**heavily reduces performance**。

8zzbczxx

8zzbczxx2#

这个可能会有帮助
how can I listen for keyboard events in gmail
DOM冒泡在窗口上启动,因此需要在那里附加侦听器,并指定第三个参数true来指示捕获阶段,这实际上是第一个事件阶段。- wOxxOm
根据你的代码,它可能是这样的:

window.addEventListener("keydown",keyDown, true);      
window.addEventListener("keyup", keyUp, true);

相关问题