草庐IT

javascript - document.activeElement 在仅适用于 Gmail 的 firefox 插件的内容脚本中不可用

coder 2024-05-11 原文

我正在使用 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.body 并且 getWordUnderCaret 失败,因为它需要输入/文本区域控件.这在所有其他地方都很有效。我不确定为什么它指向 document.body 因为我可以看到焦点在输入控件上。在 Firebug 控制台中键入 document.activeElement 会给我正确的对象。

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

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

我的代码可在 Github 获得

编辑

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

最佳答案

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

» 如果是这样的话;

原因:

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

因此,当被点击时;您并不总是通过查询方式获得正确的元素 document.activeElement ,在这种情况下。您将获得包装(主)文档的 body , (甚至不包括 iframebody)。

例如;我相信,at this line你的代码;你加一个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. <强> selectionStartdocument.body 中不存在(目标 iframe )。对于这种选择/检查;你应该在 DOM Selections 之间切换, DOM Ranges ;而不是 text edit control 中的文本选择和范围

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

更多信息:

  • 参见 activeElement documentation 在 Mozilla 开发者上 网络。另外,它表示:“不要将焦点与 选择文档。当没有选择时, activeElement是页面的<body>

更新:

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

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

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

关于javascript - document.activeElement 在仅适用于 Gmail 的 firefox 插件的内容脚本中不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14272366/

有关javascript - document.activeElement 在仅适用于 Gmail 的 firefox 插件的内容脚本中不可用的更多相关文章

  1. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  2. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  3. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  4. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  5. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  6. ruby - Watir 更改 Mozilla Firefox 首选项 - 2

    我正在使用Watir运行一个Ruby脚本来为我自动化一些事情。我试图自动将一些文件保存到某个目录。因此,在我的Mozilla设置中,我将默认下载目录设置为桌面并选择自动保存文件。但是,当我开始运行我的脚本时,这些更改并没有反射(reflect)出来。似乎首选项恢复为默认值。我已经包括以下内容require"rubygems"#Optional.require"watir-webdriver"#Forwebautomation.require"win32ole"#Forfilesavedialog.并打开一个新的firefox实例:browser=Watir::Browser.new(:

  7. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  8. ruby - 如何在ruby中提取方括号内的内容 - 2

    我正在尝试提取方括号内的内容。到目前为止,我一直在使用它,它有效,但我想知道我是否可以直接在正则表达式中使用某些东西,而不是使用这个删除功能。a="Thisissuchagreatday[coolawesome]"a[/\[.*?\]/].delete('[]')#=>"coolawesome" 最佳答案 差不多。a="Thisissuchagreatday[coolawesome]"a[/\[(.*?)\]/,1]#=>"coolawesome"a[/(?"coolawesome"第一个依赖于提取组而不是完全匹配;第二个利用前瞻和

  9. ruby-on-rails - 如何找出拦截 'method_missing' 的内容 - 2

    使用Ruby1.8.6/Rails2.3.2我注意到在我的任何ActiveRecord模型类上调用的任何方法都返回nil而不是NoMethodError。除了烦人之外,这还破坏了动态查找器(find_by_name、find_by_id等),因为即使存在记录,它们也总是返回nil。不从ActiveRecord::Base派生的标准类不受影响。有没有办法追踪在ActiveRecord::Base之前拦截method_missing的是什么?更新:切换到1.8.7后,我发现(感谢@MichaelKohl)will_paginate插件首先处理method_missing。但是will_pa

  10. ruby - 使用 ruby​​ 从文本中删除 url - 2

    给定一个文本,我想删除url部分并保留其他文本。例子:'blablabla...blablabla...http://bit.ly/someuriblablabla...'成为'blablabla...blablabla...blablabla...'是否有任何ruby​​内置方法可以有效地执行此操作? 最佳答案 尝试使用正则表达式:(?:f|ht)tps?:\/[^\s]+ 关于ruby-使用ruby​​从文本中删除url,我们在StackOverflow上找到一个类似的问题:

随机推荐