如何检测 Gmail 中的键盘事件 [英] How can I detect keyboard events in Gmail
问题描述
我正在编写一个浏览器扩展,需要将处理程序附加到所有页面上的 keyup
和 keydown
事件.我可以使用以下内容脚本代码使其正常工作.
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);
但我无法在 Gmail 中使用它.具体来说,在撰写新电子邮件的正文时,我无法使其正常工作.它适用于我测试过的其他任何地方.我认为问题是因为 Gmail 在所有键盘事件上调用 stopPropagation
但很难调试它们的最小化代码.我认为将第三个参数设置为 true
会导致在 CAPTURE_PHASE
期间捕获事件,但这不起作用.
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.
如何在使用 Google Chrome 内容脚本在 Gmail 中编写新正文时捕获 keyup
和 keydown
事件?
How can I capture keyup
and keydown
events while composing a new body in Gmail with a Google Chrome content script?
通过将 "all_frames": true,
添加到我的清单,我已经确保我的内容脚本被注入到 DOM 的所有 iframe 中.我什至尝试使用以下代码:
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);
这仍然不能解决 Gmail 的问题.
This still doesn't fix the issue with Gmail.
推荐答案
您的代码不起作用,因为 event.srcElement
引用了 元素,不是它的内容.要访问其内容文档,您必须等待框架加载(
onload
或轮询),然后使用 frame.contentDocument
访问框架.
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.
从 Chrome 37.0.1995.0 开始,您还可以使用 match_about_blank
(使用 all_frames)在 about:blank
捕获事件并将其发送到父内容脚本的框架.
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):
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 突变事件,因为后者 严重降低性能.
Note that I used polling instead of DOM mutation events, because the latter heavily reduces performance.
这篇关于如何检测 Gmail 中的键盘事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!