Nav*_*K N 12 javascript firefox firefox-addon firefox-addon-sdk
我正在使用addon-sdk开发一个Firefox插件.此插件将菜单项添加到上下文菜单,用户可以右键单击任何编辑控件以激活此菜单项.一旦激活,它会在用户输入内容时显示一个带有建议的小弹出窗口.
除了Gmail之外,一切运作良好.
在Gmail中,以下代码失败.
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();
}
});
Run Code Online (Sandbox Code Playgroud)
失败的原因是document.activeElement指向document.body和getWordUnderCaret失败,因为它期望输入/ textarea控制.这适用于所有其他地方.我不确定它为什么指向,document.body因为我可以看到焦点在于输入控件.键入document.activeElementFirebug控制台给了我适当的对象.
或者,我试图自己跟踪活动元素而不是使用document.activeElement.但我遇到了一些问题,比如坚持这个问题.我不能用window它作为window代理来坚持这个.我尝试过,unsafeWindow但无法让它工作.
我想知道为什么这在Gmail中失败了?任何帮助解决这个问题都会很棒!
我的代码可以在Github上找到
编辑
看起来这是addon-sdk的一个问题.我创建了一个Gist,可以用来重现问题.它可以在这里找到
Onu*_*rım 12
我想,你指的是Gmail上的大框,你在撰写邮件时输入邮件正文.
»如果是这样的话;
Gmail上的编辑控件不是文本控件(输入或文本区域).这是一个WYSIWYG编辑器,可通过设置(或 取决于浏览器支持)<iframe>进行编辑.document.designMode = "on"document.body.contentEditable = true
所以,点击时; document.activeElement在这种情况下,您并不总是以查询的方式获得正确的元素.你得到的包装(主)文件的body,(甚至没有iframe的body).
例如; 我相信,在你的代码的这一行 ; 您将一个click事件侦听器添加到主文档.但您也应该将其添加到页面中的可编辑iframe中; 因为页面和iframe具有不同的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);
}
Run Code Online (Sandbox Code Playgroud)
以下是帮助函数:(
注意我们如何从主文档向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);
}
Run Code Online (Sandbox Code Playgroud)
现在,事件处理程序将正确的日志记录activeElement到控制台.
结果是; 现有代码中的文本选择和检查等功能与常规编辑控件(输入,文本区域等)的工作方式不同.
例如; 你的getWordUnderCaret(editor)功能得到insertionPoint由editor.selectionStart不中不存在document.body(的目标iframe).对于这种选择/检查; 你应该在DOM选择,DOM范围之间切换; 而不是文本编辑控件中的文本选择和范围.
注意:您使用的文本选择/范围jQuery库(Rangy)承诺在浏览器中处理这种可编辑的内容(iframe,div等).您是否尝试过iframe(例如在Gmail上)?
activeElement页面就是页面<body>."检查Gmail上的文本控件; 我也玩过你的示例代码;
attachTo: ["existing", "top", "frame"]到PageMod选项.contentScriptWhen为'end'(而不是
'ready')的值; 确保包括DOM,CSS,JS在内的所有内容都已加载.某些内容可能会在页面就绪/加载时通过JS进行更改,因此"结束"将在其后执行.在Gmail(搜索框,聊天框等)和其他网站上测试; 这似乎有效.
见/测试工作的例子在这里的附加建设者.

