1

ページが読み込まれるたびにJavaScriptを読み込むFirefoxアドオンを構築しています。このページで見つけたプログレスリスナー関数を使用しています: https ://developer.mozilla.org/en/Code_snippets/Progress_Listeners

私の問題は、ページが完全に読み込まれる前にコードが実行されるように見えるため、スクリプトが実行されないことです。これが私のコードです。

var PageLoad = {
    browser: null,
    domain:  null,
    oldURL:  null,

    init: function() {
            gBrowser.addProgressListener(urlBarListener,Components.interfaces.nsIWebProgress.NOTIFY_LOCATION);
    },

    uninit: function() {
            gBrowser.removeProgressListener(urlBarListener);
    },

    processNewURL: function(aURI) {
            //if (aURI.spec == this.oldURL)
            //return;

        MyObject.function();

            this.oldURL = aURI.spec;
    }
};

var urlBarListener = {
    locChange: false,

    QueryInterface: function(aIID) {
            if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
               aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
               aIID.equals(Components.interfaces.nsISupports))
            return this;
            throw Components.results.NS_NOINTERFACE;
    },

    onLocationChange: function(aProgress, aRequest, aURI) {
            PageLoad.processNewURL(aURI);
    },

    onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) {},
    onProgressChange: function(a, b, c, d, e, f) {},
    onStatusChange: function(a, b, c, d) {},
    onSecurityChange: function(a, b, c) {}
};

window.addEventListener("load",
    function() {
            PageLoad.init()
    }, false);

var MyObject = {
    function : function() {
            var script = PageLoad.browser.createElement('script');
            script.src = 'url_to_script.js';
            PageLoad.browser.getElementsByTagName('head')[0].appendChild(script);
    }
};

このコードを使用すると、コンソールに次のエラーメッセージが表示されます。

PageLoad.browser.getElementByTagName( "head")[0]は未定義です

タイムアウトを追加すると、スクリプトは断続的に機能しますが、ページの読み込みが遅い場合は同じエラーが発生します。これが時々機能するものですsetTimeout(MyObject.function, 1000);

ページがロードされた後にスクリプトが実行されていることを確認するためのより信頼性の高い方法が必要です。

無関係で、問題は発生していないようですが、次のエラーメッセージも表示されます。

gBrowser.addProgressListenerは、サポートされていない2番目の引数で呼び出されました。バグ608628を参照してください。

4

4 に答える 4

2

If you want to load javascript at every page load - the best way is subscribing to DOMContentLoaded event:

var MyObject  = {
    processDOMContentLoaded: function(doc) {
        var script = doc.createElement('script');
        script.src = 'url_to_script.js';
        script.type = 'text/javascript';
        doc.getElementsByTagName('head')[0].appendChild(script);
    }
};

window.addEventListener('load', function() {
    var appcontent = document.getElementById('appcontent');
    if(appcontent != null) {
        appcontent.addEventListener('DOMContentLoaded', function(event) {
            var doc = event.originalTarget;
            if(doc instanceof HTMLDocument) {
                MyObject.processDOMContentLoaded(doc);
            }
        }, true);
    }
}, false);

Have not tested, but should work.

于 2012-05-22T19:07:22.100 に答える
1

実際、それは素晴らしい質問です。イベント リスナーは慎重に使用する必要があります。ページが読み込まれるたびにトリガーすると、複数回 (最悪の場合は数十回) トリガーされる可能性があるためです。では、どうすればそれを行うことができますか?

window.addEventListener("load", function load(event){
    window.removeEventListener("load", load, false); //remove listener, no longer needed
    myExtension.init(); 
},false);

var myExtension = {
    init: function() {
    var appcontent = document.getElementById("appcontent");   // browser
    if(appcontent){
      appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
    }

  },

  onPageLoad: function(aEvent) {
    var doc = aEvent.originalTarget; // doc is document that triggered the event
    var win = doc.defaultView; // win is the window for the doc

    if (doc.nodeName != "#document") return;
    if (win != win.top) return;
    if (win.frameElement) return;

      alert("the main page has been loaded");

  },
};

マルチロードを防ぐために、ページロードがトリガーされるたびにトリガーのタイプをチェックしていることに注意してください。

于 2013-04-08T06:30:48.483 に答える
1

You are using onLocationChange method - but if you look at how the browser behaves, the location in the address bar changes as soon as a connection with the server is established. You should look at state changes instead:

onStateChange: function(aWebProgress, aRequest, aFlag, aStatus)
{
  if ((aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
      (aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW))
  {
    // A window finished loading
    PageLoad.windowLoaded(aWebProgress.DOMWindow);
  }
},

Note that the window that finished loading is explicitly passed to PageLoad.windowLoaded() - you will be receiving notifications from different tabs and you cannot assume that the notification comes from the foreground tab.

As to the warning you are getting, just leave out the second parameter in the call to gBrowser.addProgressListener():

gBrowser.addProgressListener(urlBarListener);

tabbrowser.addProgressListener() only accepts one parameter, unlike nsIWebProgress.addProgressListener() which has a second parameter.

于 2012-05-22T18:55:09.553 に答える
-1

提供された回答は受け入れられましたが、完全に機能するさらに別の解決策を見つけました。

var PageLoad = {
init: function() {
    if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
  },
  onPageLoad: function(aEvent) {
    var doc = aEvent.originalTarget; // doc is document that triggered the event
    var win = doc.defaultView; // win is the window for the doc

    if (doc.nodeName != "#document") return;
    if (win != win.top) return;
    if (win.frameElement) return;

    MyAddon.function();
  }
}

window.addEventListener("load", function load(event){
  window.removeEventListener("load", load, false); //remove listener, no longer needed
  PageLoad.init();  
},false);
于 2012-05-23T17:45:49.203 に答える