我想,您指的是 Gmail 上的大框,您在撰写电子邮件时输入消息正文。
» 如果是这样的话;
原因:
Gmail 上的编辑控件不是文本控件(输入或文本区域)。那是一个所见即所得的编辑器,通过设置(或 取决于浏览器支持)<iframe>
使其可编辑。document.designMode = "on"
document.body.contentEditable = true
所以,当点击时;document.activeElement
在这种情况下,您并不总是以查询的方式获得正确的元素。你得到包装(主)文档的body
, (甚至不是iframe
's body
)。
例如; 我相信,在你的这行代码;您将click
事件侦听器添加到主文档。但是您也应该将其添加到页面中的可编辑 iframe;因为页面和 iframe(s) 有不同的document
对象(并且 iframe 不会将自己设置为活动的)。所以,你会弄错document.activeElement
。
解决方法:
也将必要的事件侦听器添加到 iframe;因为您想收到有关它们的通知。
// Add mouseup event listener to the main document
document.addEventListener('mouseup', logActiveElement, false);
// Get all the iframes on the main document.
var iframeElems = document.getElementsByTagName('iframe');
// Add mouseup event listener to the document of the iframe elements
for (var i = 0; i < iframeElems.length; ++i) {
addIframeEvent(iframeElems[i], true, 'mouseup', logActiveElement);
}
以下是辅助函数:(
请注意我们如何将事件侦听器从主文档添加到 iframe(文档),以及我们如何检查 iframe 当前是否可编辑。)
// Adds the specified event listener to the iframe element.
function addIframeEvent(iframeElem, editableOnly, eventName, callback) {
// Get the document of the iframe element.
var iframeDocument = iframeElem.contentDocument ||
iframeElem.contentWindow.document;
// Watch for editableOnly argument.
if ( (editableOnly && isDocEditable(iframeDocument)) || !editableOnly) {
// Add the event listener to the document of the iframe element.
iframeDocument.addEventListener(eventName, callback, false);
}
}
// Checks whether the specified document is content-editable or in design mode.
function isDocEditable(doc) {
return ( ('contentEditable' in doc.body) && (doc.body.contentEditable === true) ) ||
('designMode' in doc) && (doc.designMode == "on") );
}
// Handler function
function logActiveElement() {
console.log("Active Element:", document.activeElement);
}
现在,事件处理程序将正确记录activeElement
到控制台。
并发症:
因此; 现有代码中的文本选择和检查等内容与常规编辑控件(输入、文本区域等)的工作方式不同。
例如; 您的getWordUnderCaret(editor)
函数获取insertionPoint
(目标)editor.
selectionStart
中不存在的方法。对于这种选择/检查;你应该在DOM Selections,DOM Ranges之间切换;而不是文本编辑控件中的文本选择和范围。document.body
iframe
注意:您使用的文本选择/范围 jQuery 库 ( Rangy ) 承诺在浏览器中处理这种可编辑的内容(iframe、div 等)。您是否为 iframe 尝试过(例如在 Gmail 上)?
更多的信息:
- 请参阅Mozilla 开发者网络上的activeElement 文档。此外,它表示:“不要将焦点与文档上的选择混淆。当没有选择时,它
activeElement
是页面的<body>
。”
更新:
检查 Gmail 上的文本控件;我也玩过你的示例代码;
- 添加
attachTo: ["existing", "top", "frame"]
到 PageMod 选项。
- 将 PageMod 选项中的值更改
contentScriptWhen
为'end'
(而不是
'ready'
);确保包括 DOM、CSS、JS 在内的所有内容都已加载。某些内容可能会在页面就绪/加载时通过 JS 进行更改,因此“结束”将在其之后执行。
- 也将选择器上下文应用于菜单项;为了确保该项目仅在选择器上下文中出现。
在 Gmail(搜索框、聊天框等)和其他网站上测试;这似乎工作。在addon builder 上
查看/测试工作示例。

