我正在构建一个firefox插件,可以在每个页面加载时加载javascript。我正在使用我在此页面上找到的进度监听器功能: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,但不支持该参数。见错误608628。
答案 0 :(得分:2)
如果您想在每次加载页面时加载javascript - 最好的方法是订阅DOMContentLoaded
事件:
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);
尚未测试,但应该有效。
答案 1 :(得分:1)
您正在使用onLocationChange
方法 - 但是如果您查看浏览器的行为方式,则只要与服务器建立连接,地址栏中的位置就会发生变化。您应该查看状态更改:
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);
}
},
请注意,已完成加载的窗口会显式传递给PageLoad.windowLoaded()
- 您将收到来自不同标签的通知,并且您不能认为该通知来自前台标签。
至于您收到的警告,请在调用gBrowser.addProgressListener()
时忽略第二个参数:
gBrowser.addProgressListener(urlBarListener);
tabbrowser.addProgressListener()
只接受一个参数,与nsIWebProgress.addProgressListener()
不同,后者有第二个参数。
答案 2 :(得分: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");
},
};
注意我们检查每个页面加载触发的触发器类型,以防止多次加载。
答案 3 :(得分:-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);