Javascript document.activeElement在firefox插件上不可用';s仅适用于Gmail的内容脚本
我正在使用插件sdk开发Firefox插件。此插件将菜单项添加到上下文菜单中,用户可以右键单击任何编辑控件来激活此菜单项。一旦激活,当用户键入内容时,它会显示一个带有建议的小弹出窗口 除了在Gmail上,一切都很好 在Gmail中,以下代码失败Javascript document.activeElement在firefox插件上不可用';s仅适用于Gmail的内容脚本,javascript,firefox,firefox-addon,firefox-addon-sdk,Javascript,Firefox,Firefox Addon,Firefox Addon Sdk,我正在使用插件sdk开发Firefox插件。此插件将菜单项添加到上下文菜单中,用户可以右键单击任何编辑控件来激活此菜单项。一旦激活,当用户键入内容时,它会显示一个带有建议的小弹出窗口 除了在Gmail上,一切都很好 在Gmail中,以下代码失败 self.port.on('showPopup', function(data) { var active = document.activeElement; console.log(active.type); if (activ
self.port.on('showPopup', function(data) {
var active = document.activeElement;
console.log(active.type);
if (active && getWordUnderCaret(active).word == data.input) {
populateSuggestions(data);
positionPopup(active);
stylePopup();
}
});
失败的原因是document.activeElement
指向document.body
,而getWordUnderCaret
由于需要输入/文本区域控件而失败。这在所有其他地方都很有效。我不知道为什么它指向document.body
,因为我可以看到焦点在输入控件上。在Firebug控制台中键入document.activeElement
可以为我提供正确的对象
或者,我尝试自己跟踪活动元素,而不是使用document.activeElement
。但我在某个地方遇到了类似坚持这样的问题。我无法使用window
来持久化此操作,因为window
是一个代理。我尝试使用unsafeWindow
,但无法使其工作
我想知道为什么这在Gmail中失败了?如果能帮上忙,那就太好了
我的代码可在
编辑
看起来这是插件sdk的问题。我创造了一个要点,可以用来重现这个问题。它是可用的您是否尝试过使用最新git版本的插件sdk?那里的上下文菜单已经从头重写,我听说它修复了不少bug。我想,你指的是Gmail上的大框,在那里你在撰写电子邮件时输入邮件正文 »如果是这样的话 原因是: Gmail上的编辑控件不是文本控件(输入或文本区域)。这是一个编辑器,通过设置
document.designMode=“on”
(或document.body.contentEditable=true
,根据浏览器的支持,可编辑
所以,当点击时;在这种情况下,查询document.activeElement的方式并不总是能得到正确的元素。您将获得包装(主)文档的正文
,(甚至不是iframe
的正文
)
比如,;我相信,你的代码;将单击事件侦听器添加到主文档中。但您也应该将其添加到页面中的可编辑iFrame;因为页面和iframe具有不同的文档
对象(并且iframe不会将自身设置为活动)。因此,您将得到错误的文档.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);
}
现在,事件处理程序将把正确的activeElement
记录到控制台
难题:
因此,;现有代码中的文本选择和检查等操作与常规编辑控件(输入、文本区域等)的工作方式不同
比如,;您的getWordUnderCaret(编辑器)
函数通过编辑器获取插入点。
,它不存在于document.body
(目标iframe
)中。对于此类选择/检查;你应该在;而不是s中的文本选择和范围
注意:您使用的文本选择/范围jQuery库()承诺在浏览器中处理此类可编辑内容(iFrame、div等)。你在iframes上试过吗(比如在Gmail上)
进一步资料:
- 请参见Mozilla Developer上的
网络。另一方面,它表示:“不要将焦点与焦点混淆
在文档上进行选择。如果没有选择,则
activeElement
是页面的
“
更新:
检查Gmail上的文本控件;我还使用了您的示例代码
- 添加了
附件:[“现有”、“顶部”、“框架”]
到PageMod选项
- 将
contentScriptWhen
的值更改为'end'
(而不是
PageMod选项中的'ready'
);确保所有内容,包括DOM、CSS、JS都已加载。一些内容可能会在页面就绪/加载时通过JS进行更改,因此“结束”将在页面就绪/加载后执行
- 将选择器上下文也应用于菜单项;为了
确保该项仅在选择器上下文中显示
在Gmail(搜索框、聊天框等)和其他网站上测试;这似乎起作用了。
请参阅/测试工作负载
Gmail是指撰写新邮件时的大邮箱还是顶部的搜索框?聊天窗口中的搜索框和文本区谢谢。但我的问题是在聊天窗口的搜索框和文本区域。非常感谢您提供的详细答案。
// 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);
}