[英]How can I detect keyboard events in Gmail
我正在編寫一個瀏覽器擴展,需要將處理程序附加到所有頁面上的keyup和keydown事件。 我可以使用以下內容腳本代碼很好地工作。
document.addEventListener("keydown",keyDown, true);
document.addEventListener("keyup", keyUp, true);
我不能讓這個在Gmail中運行。 具體來說,在編寫新電子郵件的正文時,我無法使其工作。 它將適用於我測試過的其他任何地方。 我認為問題是因為Gmail在所有鍵盤事件上調用stopPropagation
但很難調試其最小化代碼。 我認為將第3個參數設置為true
會導致在CAPTURE_PHASE
期間捕獲事件,但這不起作用。
如何在使用Google Chrome內容腳本在Gmail中編寫新主體時捕獲keyup
和keydown
事件?
編輯:
通過在我的清單中添加"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的問題。
您的代碼不起作用,因為event.srcElement
引用<iframe>
元素,而不是其內容。 要訪問其內容文檔,您必須等待加載幀( onload
或polling),然后使用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突變事件,因為后者嚴重降低了性能 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.