The following injection works perfectly in Chrome, however in the latest Firefox (version 21), the documents stays "Connecting..." forever and not even its elements like <img>
loads. (But if you click reload on them they show up fine...)
Screenshot:
Script:
// ==UserScript==
// @name Test
// @namespace Test
// @author Owyn
// @match http://*
// ==/UserScript==
function inject(func) {
var source = func.toString();
var script = document.createElement('script');
script.innerHTML = "("+ source +")()";
document.body.appendChild(script);
}
function myf() {
document.write('<html>TEST</html>');
}
inject(myf);
Any fixes, any workarounds? Should I contact Mozilla about a bug?
P.S. - I use document.write to remove all event listeners (unknown to me) and found no alternative to it yet.
The smartest/best(est) thing to do is to avoid document.write()
. Use DOM techniques. Here's a complete script:
// ==UserScript==
// @name _Replace a target page using DOM techniques
// @include http://YOUR_SERVER.COM/YOUR_PATH/*
// @grant GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
var D = document;
var newDoc = D.implementation.createHTMLDocument ("");
D.replaceChild (
D.importNode (newDoc.documentElement, true),
D.documentElement
);
D.body.innerHTML = '<h1>TEST</h1>'
Greasemonkey normally fires on DOMContentLoaded
, not when the page has fully completed loading. Chrome fires later than that, by default.
Anyway, at DOMContentLoaded
, in Firefox; something is getting orphaned when you trash the current document. Hence the "throbber" is never stopped and some other cleanup is probably missed.
This is probably a bug, but you shouldn't use document.write()
anyway. Also, per the DOC, you should call document.close()
A dirty workaround is to wait until the page has loaded before firing. So, instead of calling inject(myf);
directly, call it like this:
function myf () {
document.write ('<html>TEST</html>');
document.close ();
}
window.addEventListener ("load", function () { inject(myf); }, false);
but use DOM methods instead! They'll be faster, and won't trip edge-case bugs and security violations.