如何检测Gmail中的键盘事件? [英] How can I detect keyboard events in Gmail

查看:103
本文介绍了如何检测Gmail中的键盘事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

虽然我无法在Gmail中使用此功能。具体来说,我无法在编写新电子邮件正文时使其起作用。它会在我测试过的其他地方工作。我认为这个问题是因为Gmail在所有键盘事件上调用了 stopPropagation ,但很难调试它们的最小化代码。我认为将第三个参数设置为 true 会导致事件在 CAPTURE_PHASE 中被捕获,但这不是加工。



如何捕获 keyup keydown 事件使用Google Chrome内容脚本在Gmail中撰写新内容?



编辑:



我的内容脚本通过向我的清单中添加all_frames:true,被注入到DOM的所有iframe中。我甚至尝试使用下面的代码:
$ b $ pre $ document $ add $ 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);

$ b}
},真正);

这仍然不能解决Gmail的问题。 < 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);}; //测试
函数keyUp(e){console.log(e.keyCode);}; //测试
(函数checkForNewIframe(doc){
if(!doc)return; //文档不存在Cya

//注意:使用true,将事件绑定到捕获
//阶段,如果省略或设置为false,则事件侦听器将绑定
//到冒泡阶段,其中事件不再可见当
// Gmail调用event.stopPropagation()。
//使用相同的参数调用addEventListener多次绑定
//只监听一次,所以我们不必设置
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; //同源策略违规?
}
if(contentDocument&a mp;&!contentDocument.hasSeenDocument){
//将轮询器添加到新的iframe
checkForNewIframe(iframes [i] .contentDocument);


setTimeout(checkForNewIframe,250,doc; //< - 延迟1/4秒
})(document); //启动文档的递归功能。

请注意,我使用轮询而不是DOM突变事件,因为后者 严重降低了性能 。 p>

I am writing a browser extension that needs to attach handlers to the keyup and keydown events on all pages. I can get it working pretty well with the following content script code.

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

I can't get this to work in Gmail though. Specifically I can't get it to work when composing the body of an new email. It will work everywhere else I have tested. I think the problem is because Gmail is calling stopPropagation on all keyboard events but it is difficult to debug their minimized code. I thought that setting the 3rd parameter to true would cause the event to be captured during the CAPTURE_PHASE but this isn't working.

How can I capture keyup and keydown events while composing a new body in Gmail with a Google Chrome content script?

Edit:

I've ensured that my content scripts are being injected into all iframes of the DOM by adding "all_frames": true, to my manifest. I have even tried using the following code:

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);

This still doesn't fix the issue with Gmail.

解决方案

Your code doesn't work because event.srcElement refers to the <iframe> element, not its content. To access its content document, you have to wait for the frame to be loaded (onload or polling), then use frame.contentDocument to access the frame.

Starting from Chrome 37.0.1995.0, you can also use the match_about_blank (with all_frames) to insert a content script in the about:blank frame that captures the event and sends it to the parent content script.

Here is an example of an implementation for the original idea (using polling):

The relevant parts of 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.

Note that I used polling instead of DOM mutation events, because the latter heavily reduces performance.

这篇关于如何检测Gmail中的键盘事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆