【问题标题】:How to access sidebar Bookmarks Panel page in SeaMonkey如何在 SeaMonkey 中访问侧边栏书签面板页面
【发布时间】:2015-03-28 05:54:29
【问题描述】:

我正在尝试将我的叠加层插件转换为无重启。
我无法访问 SeaMonkey 中的书签面板(在侧边栏上),以加载我的叠加 UI。
具体来说,我需要将我的叠加层加载到 bm-panel.xul,类似于以下内容: myListener.document.loadOverlay("chrome://myBookmarksPanelOverlay.xul");

为此,我需要 bm-panel.xul 的窗口,但我只有浏览器的主窗口。

SeaMonkey 与 Firefox 的结构不同,所以下面的例子
var sidebarPanels = window.document.getElementById('sidebar');
在文档中,不适用于 SeaMonkey。

我可以在 Dom Inspector 中看到 bm-panel.xul 窗口,但我无法使用 Javascript 访问它。

我只能访问侧边栏面板,但仅此而已:
var sidebarPanels = window.document.getElementById('sidebar-panels');

我如何访问书签面板页面本身?

【问题讨论】:

  • 一个重要的问题是您通常不应该在无需重启的扩展中使用document.loadOverlay()。相反,您应该动态添加和删除 DOM 的元素。请记住,在无需重启的附加组件中,您需要能够干净地删除您对 Firefox 所做的所有更改。如果您无法彻底删除它们,那么它不是无需重启的插件,无论您无需重启即可加载插件。
  • @Makyen,谢谢。你当然是对的,我会相应地改变它。但是,我仍然需要 bm-panel.xul 来添加元素(按钮)。所以问题仍然存在。
  • 如果有完整的代码(MCVE)可用,而不是仅仅为了测试这个问题的代码而推出我自己的 SeaMonkey 插件原型,这会容易得多。
  • 顺便说一句:感谢您将无效示例从 ID=sidebar-panels 中更改出来。错误地指出 ID 在 MDN 文档中是这样的,并暗示该声明在 SeaMonkey 中不起作用,但在 Firefox 中起作用,这是导致我不清楚您的问题的原因之一,因为它是相反是正确的(它应该在 SeaMonkey 中工作,但不能在 Firefox 中工作,并且不是 MDN 侧边栏文档的一部分(即,该 ID 未在股票 Firefox 中使用,但在 SeaMonkey 中)。

标签: javascript firefox-addon bookmarks seamonkey


【解决方案1】:

我不能 100% 确定您的问题是否真的仅限于查找 bookmarksPanel。因此,此答案包含有关访问 bookmarksPanel、查看 DOM、从覆盖或无重启扩展访问侧边栏以及获取 window 参考的一般信息。

访问bookmarksPanel

以下内容应该让您参考<page id="bookmarksPanel">

var sidebarDocument = document.getElementById("sidebar").contentDocument;
var bookmarksPanelElement = sidebarDocument.getElementById("bookmarksPanel")

请注意,您需要在sidebarDocument 中使用getElementById(),而不是不会搜索到侧边栏的主要window.document.getElementById()

查看 DOM

如果您在了解特定元素的 DOM 结构时遇到问题,我建议您安装 DOM Inspector (for SeaMonkey)(查看 DOM)和 Element Inspector(允许您转移- 右键单击​​一个元素并打开该元素上的 DOM 检查器)。

这是 DOM Inspector 在 Firefox 中查看书签侧边栏的示例:

从 Overlay 或 Restartless 扩展访问侧边栏

引用 MDN:“Sidebar: Accessing the sidebar from a browser.xul script”:

从 browser.xul 脚本访问侧边栏
侧边栏内容始终位于与主浏览器文档分开的文档中(侧边栏实际上是作为 XUL 浏览器元素实现的)。这意味着您无法从 browser.xul 覆盖层引用的脚本直接访问侧边栏内容。

要访问侧边栏的窗口或文档对象,您需要分别使用document.getElementById("sidebar")contentWindowcontentDocument 属性。例如,下面的代码调用了在侧边栏上下文中定义的函数:

var sidebarWindow = document.getElementById("sidebar").contentWindow;
// Verify that our sidebar is open at this moment:
if (sidebarWindow.location.href ==
      "chrome://yourextension/content/whatever.xul") {
  // call "yourNotificationFunction" in the sidebar's context:
  sidebarWindow.yourNotificationFunction(anyArguments);
}

根据您当前运行的代码的启动方式(例如 UI 按钮),您可能需要获取当前浏览器 window

大量复制another answer of mine,您可以通过以下方式获得:

获取对最新window的引用:

Firefox 附加组件通常在未定义全局 window 对象的范围内运行(是否已定义取决于当前运行的代码部分是如何输入的)。即使已定义,它通常也不会定义为您所期望的window(当前选项卡的window)。您可能需要为最近访问的窗口/选项卡获取对 window 对象的引用。

如果存在浏览器窗口(在某些情况下,您可能在不存在浏览器窗口的情况下运行,例如在启动时),您可以获得对最新浏览器 windowdocumentgBrowser 与:

if (window === null || typeof window !== "object") {
    //If you do not already have a window reference, you need to obtain one:
    //  Add/remove a "/" to comment/un-comment the code appropriate for your add-on type.
    /* Add-on SDK:
    var window = require('sdk/window/utils').getMostRecentBrowserWindow();
    //*/
    //* Overlay and bootstrap (from almost any context/scope):
    var window=Components.classes["@mozilla.org/appshell/window-mediator;1"]
                         .getService(Components.interfaces.nsIWindowMediator)
                         .getMostRecentWindow("navigator:browser");        
    //*/
}
if (typeof document === "undefined") {
    //If there is no document defined, get it
    var document = window.content.document;
}
if (typeof gBrowser === "undefined") {
    //If there is no gBrowser defined, get it
    var gBrowser = window.gBrowser;
}

如果您正在运行代码以响应事件(例如按钮command 事件),您可以通过以下方式获取当前window

var window = event.view

缺少可用的全局window 对象,或者它引用的内容与您的预期不同,这是许多人在编写 Firefox 插件时遇到的问题。

注意:如果您希望与multi-process Firefox(Electrolysis,或 e10s)原生兼容,那么获取对当前文档内容的访问权限会更加复杂。有一些 shims 可以让您的代码在多进程 Firefox 中继续工作一段时间,但它们可能/将会最终消失。

参考资料:

  1. nsIWindowMediator
  2. Working with windows in chrome code
  3. SDK:window/utils
  4. SDK:windows
  5. Multiprocess Firefox
  6. Working with multiprocess Firefox

其中大部分内容是从我之前的答案中复制而来的,包括this link

【讨论】:

  • 我试图在上面澄清我的要求。我特别需要 Seamonkey 的信息,这就是我使用 Seamonkey 术语的原因。通用案例和 Mozilla 文档是关于 Firefox 的。
【解决方案2】:

这可能不是唯一的方法或最好的方法,但这是我正在做的:

  1. 找到侧边栏元素(sidebar-panels)
  2. 在侧边栏 childNodes 中搜索属性为 src=chrome://communicator/content/bookmarks/bm-panel.xul 的元素

搜索子节点必须延迟到相关帧加载完毕,并且搜索本身是对所有元素的递归迭代。

以下是一个最小的剥离代码:

    var sidebarE =  domWindow.document.getElementById('sidebar-panels');
    setTimeout(function() {
        var sbPanelE = searchChildNodes(sidebarE);
    }, 350);

    function searchChildNodes (aElement) {
        var stackNew = [];
        var current;
        var i, lenArr;

        iterate(aElement); 
        function iterate(current) { 
            var childrenE = current.childNodes;
            for (var i = 0, lenArr = childrenE.length; i < lenArr; i++) {
                iterate(childrenE[i]);
                foundE = checkElement(childrenE[i]);
                if (e.nodeType == 1){ // Element node
                    if (e.getAttribute('src') == loc){
                        stackNew.push({ //pass args via object or array
                            element: childrenE[i],
                        });
                        return;
                    }
                }
            }
        }

        for (i=0;i<stackNew.length ;i++ ){
            var itm = stackNew[i].element;
            return itm;
        }
    } // searchChildNodes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2013-08-09
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多