【问题标题】:document.activeElement not available on firefox addon's content script only for Gmaildocument.activeElement 在 Firefox 插件的内容脚本中不可用,仅适用于 Gmail
【发布时间】:2012-12-25 16:37:54
【问题描述】:

我正在使用 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();
    }
});

失败的原因是document.activeElement 指向document.bodygetWordUnderCaret 失败,因为它需要一个输入/文本区域控件。这在所有其他地方都很好。我不确定为什么它指向document.body,因为我可以看到焦点在输入控件上。在 Firebug 控制台中输入 document.activeElement 会给我正确的对象。

另外,我尝试自己跟踪活动元素,而不是使用document.activeElement。但我遇到了一些问题,比如在某个地方坚持这个。我不能使用window 来坚持这个,因为window 是一个代理。我尝试使用unsafeWindow,但无法正常工作。

我想知道为什么这在 Gmail 中会失败?任何解决此问题的帮助都会很棒!

我的代码可以在Github获得

编辑

看起来这是 addon-sdk 的问题。我创建了一个可用于重现问题的 Gist。可用here

【问题讨论】:

  • Gmail 是指撰写新邮件时的大框还是顶部的搜索框?
  • 聊天窗口中的搜索框和文本区域

标签: javascript firefox firefox-addon firefox-addon-sdk


【解决方案1】:

我猜,您指的是 Gmail 上的大框,您在撰写电子邮件时输入邮件正文。

» 如果是这样的话;

原因:

Gmail 上的编辑控件不是文本控件(输入或文本区域)。这是一个 WYSIWYG 编辑器,使用 <iframe> 实现,通过设置 document.designMode = "on"(或 document.body.contentEditable = true 取决于浏览器支持)。

所以,当点击时;在这种情况下,您并不总是通过查询 document.activeElement 的方式获得正确的元素。你会得到包装(主)文档的body,(甚至没有iframebody)。

例如;我相信,at this line 你的代码;您将click 事件侦听器添加到主文档。但是你也应该把它添加到页面中的editable iframes中;因为页面和 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) 函数通过editor.selectionStart 获取insertionPoint,这在document.body(目标iframe)中不存在。对于这种选择/检查;你应该在DOM SelectionsDOM Ranges之间切换;而不是 text edit controls 中的文本选择和范围。

注意:您使用的文本选择/范围 jQuery 库 (Rangy) 承诺在浏览器中处理此类可编辑内容(iframe、div 等)。您是否为 iframe 尝试过(例如在 Gmail 上)?

更多信息:

  • 请参阅 Mozilla 开发人员上的 activeElement documentation 网络。此外,它表示:“不要将焦点与 选择文件。没有选择时, activeElement 是页面的&lt;body&gt;。"

更新:

检查 Gmail 上的文本控件;我也玩过你的示例代码;

  • 在 PageMod 选项中添加了 attachTo: ["existing", "top", "frame"]
  • contentScriptWhen 的值更改为'end'(而不是 'ready') 在 PageMod 选项中;确保包括 DOM、CSS、JS 在内的所有内容都已加载。某些内容可能会在页面就绪/加载时通过 JS 进行更改,因此 'end' 将在其之后执行。
  • 也将选择器上下文应用于菜单项;为了 确保该项目仅在选择器上下文中出现。

在 Gmail(搜索框、聊天框等)和其他网站上进行了测试,并且;这似乎有效。
查看/测试工作的example here on addon builder

【讨论】:

  • 谢谢。但我的问题在于聊天窗口中的搜索框和文本区域。
  • 非常感谢您的详细回答。
【解决方案2】:

您是否尝试过使用最新的 git 版本的插件 sdk?那里的上下文菜单已经从头开始重写,我听说它修复了很多错误。

【讨论】:

    猜你喜欢
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多