views:

70

answers:

1

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"
+1  A: 

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.

MatrixFrog
It fires a lot less, but still does multiple times on some pages. I'm guessing this is due to iframes firing an onload event?Just looking into how to tell apart an iframe load from the document's load and whether there's of capturing when the page and all of its iframes have loaded.
Ivan Kruchkoff