.onload вызывается несколько раз из расширения Firefox - PullRequest
9 голосов
/ 12 августа 2010

Я занимаюсь разработкой расширения 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"

1 Ответ

7 голосов
/ 13 августа 2010

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

Текущие ночные сундуки Firefox запускают функцию onPageLoad не только для документов, но и xul:image s (значки в tabbrowser).Если вы хотите обрабатывать только документы, убедитесь, что aEvent.originalTarget.nodeName == "#document"

Если вы все еще видите, что запускаются посторонние события «загрузки», вы можете проверить цель события на рисуноквыясните, что загружается, и используйте подобную логику, чтобы избежать вызова логики вашего расширения в определенных конкретных случаях.

...