最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - .onload called multiple times from Firefox extension - Stack Overflow

programmeradmin8浏览0评论

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"

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"
Share Improve this question edited Jul 14, 2019 at 9:59 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Aug 12, 2010 at 18:51 IvanIvan 1,56116 silver badges22 bronze badges 1
  • 1 The proposed solution cannot handle when pages load at different firefox tabs beacause only for one tab (the focused tab) the condition aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec will be evaluated as true – John d. Commented Oct 1, 2011 at 16:28
Add a ment  | 

1 Answer 1

Reset to default 7

From https://developer.mozilla/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.

发布评论

评论列表(0)

  1. 暂无评论