.onload 从 Firefox 扩展调用多次

发布于 2024-09-13 18:28:45 字数 2321 浏览 0 评论 0原文

我正在开发一个 Firefox 扩展程序,并具有以下代码:

function initialize() { 
    // For accessing browser window from sidebar code.
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIWebNavigation)
               .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
               .rootTreeItem
               .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIDOMWindow);
    var gBrowser = mainWindow.gBrowser;
    gBrowser.onload = function() {
        alert('loaded');
    };
}
  1. 当我打开扩展程序(侧边栏)并继续在 Firefox 窗口中打开新选项卡时,会出现三个警告框。
  2. 当我刷新页面时,有两个警告框。
  3. 当页面加载完成时,只有一个警告框。
  4. 当我更改选项卡时,会触发警报。

我使用 .onload 而不是 DOMContentLoaded 或 Readystatechange,因为我需要等到所有其他 javascript 完成在页面上的加载后才能运行我的。

关于为什么触发多个事件(以及不应该触发事件的事情)有什么想法吗?

解决方案

根据 MatrixFrog 的建议,这是我得出的解决方案:

function initialize() { 
    // For accessing browser window from sidebar code.
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIWebNavigation)
               .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
               .rootTreeItem
               .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIDOMWindow);
    var gBrowser = mainWindow.gBrowser;
    if (gBrowser.addEventListener) {
        gBrowser.addEventListener("load",pageLoaded,true);
    }    
}

function pageLoaded(aEvent) {
    if ((aEvent.originalTarget.nodeName == '#document') && 
       (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) 
    {
        alert('loaded');
    }
}
  1. aEvent.originalTarget.nodeName == '#document' 检查页面是否已加载,而不是图标。
  2. (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) 检查触发事件的元素是否为选项卡中的页面,并且其 IFRAME 之一
  3. gBrowser.onload 不会仅针对 xul-image 触发不适用于#document,因此它被替换为 gBrowser.addEventListener("load",pageLoaded,true);
  4. 如果您想避免触发新空白选项卡的事件,请确保 gBrowser.currentURI.spec != "about:blank"

I'm developing a Firefox extension and have the following code:

function initialize() { 
    // For accessing browser window from sidebar code.
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIWebNavigation)
               .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
               .rootTreeItem
               .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIDOMWindow);
    var gBrowser = mainWindow.gBrowser;
    gBrowser.onload = function() {
        alert('loaded');
    };
}
  1. When I open the extension (a sidebar) and proceed to open a new tab within the Firefox window, there are three alert boxes.
  2. When I refresh a page, there are two alert boxes.
  3. When a page finishes loading, there is only one alert box.
  4. When I change tabs, an alert is fired.

I use .onload rather than DOMContentLoaded or readystatechange as I need to wait until all other javascript has finished loading on a page before I run mine.

Any ideas as to why multiple events are being triggered (and for things that the event shouldn't be triggered for)?

SOLUTION

Following from MatrixFrog's suggestion, here is the solution I came to:

function initialize() { 
    // For accessing browser window from sidebar code.
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIWebNavigation)
               .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
               .rootTreeItem
               .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIDOMWindow);
    var gBrowser = mainWindow.gBrowser;
    if (gBrowser.addEventListener) {
        gBrowser.addEventListener("load",pageLoaded,true);
    }    
}

function pageLoaded(aEvent) {
    if ((aEvent.originalTarget.nodeName == '#document') && 
       (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) 
    {
        alert('loaded');
    }
}
  1. aEvent.originalTarget.nodeName == '#document' checks that the page is loaded and not favicons.
  2. (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) checks that the element that fired the event is the page in the tab, and not one of its IFRAMEs
  3. gBrowser.onload would only fire for xul-image and not for #document so it was replaced with gBrowser.addEventListener("load",pageLoaded,true);
  4. If you want to avoid firing the event for new blank tabs, make sure gBrowser.currentURI.spec != "about:blank"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫性小仙女 2024-09-20 18:28:45

来自 https://developer.mozilla.org/en/Code_snippets/On_page_load

<块引用>
<块引用>

当前的 Firefox trunk nightly 不仅会为文档触发 onPageLoad 函数,还会为 xul:image(选项卡浏览器中的图标)触发 onPageLoad 函数。如果您只想处理文档,请确保 aEvent.originalTarget.nodeName == "#document"


如果您仍然看到无关的“load”事件触发,您可能需要检查事件目标来确定找出正在加载的内容,并使用类似的逻辑来避免在某些特定情况下调用扩展的逻辑。

From https://developer.mozilla.org/en/Code_snippets/On_page_load

Current Firefox trunk nightlies will fire the onPageLoad function for not only documents, but xul:images (favicons in tabbrowser). If you only want to handle documents, ensure aEvent.originalTarget.nodeName == "#document"

If you're still seeing extraneous 'load' events firing, you may want to inspect the event target to figure out what's being loaded, and use similar logic to avoid calling your extension's logic in certain specific cases.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文