5

With the update to Firefox 57 and Greasemonkey 4 a number of my userscripts broke. In some scripts I used:

document.addEventListener('DOMContentLoaded', doStuff, false);

This no longer works in Greasemonkey. What is the proper way to add an DOMContentLoaded event now?

P.S. I checked that at the time of registering the event, DOM is still not ready.

Brock Adams
  • 82,642
  • 19
  • 207
  • 268
jahu
  • 4,899
  • 2
  • 35
  • 55

2 Answers2

3

I still don't know what is the recommended way of running code on DOM ready in Greasemonkey 4, but after changing:

document.addEventListener('DOMContentLoaded', doStuff, false);

to:

window.addEventListener('load', doStuff, false);

my script works again. I just started testing other methods based on this answer, since I noticed that my jQuery based user scripts are still working (at least the DOM ready part does).

This answer is kind of obvious, but at the time of writing the question, I wasn't sure if I was keeping up with the changes in Greasemonkey (reading about all the async stuff) and I expected DOMContentLoaded to just work.

jahu
  • 4,899
  • 2
  • 35
  • 55
3

I ran into a similar problem after GreaseMonkey upgraded to version 4, but I used

addEventListener("DOMContentLoaded", function(){
  // …
});

instead.

When trying to fix my user-scripts, I initially commented out that wrapper and put a

// @run-at document-end

in the metadata block. This way, I ensured that the DOM was ready and the code that was originally inside the DOMContentLoaded wrapper executed correctly.

This worked, however, for two of my user-scripts I actually needed to run JavaScript, before any page script had run and execute other code when the DOM was ready. It turns out, that now you need to put

// @run-at document-start

in the metadata block in order for the DOMContentLoaded wrapper to work on your window (or document).

In previous versions of GreaseMonkey I could just omit this and it would run fine.

However, according to the GreaseSpot Wiki, document-start is not guaranteed to work in GreaseMonkey 4.0, perhaps due to asynchrounous execution or missing features in the WebExtensions rewrite of the add-on.

Also, document.readyState will be "loading" with document-start, but "interactive" with document-end or no // @run-at at all.

Sebastian Simon
  • 14,320
  • 6
  • 42
  • 61
  • Interesting! For me, the trick was to just remove the addEventListener function althogether. I copy-pasted what was inside the anonymous function, outside. I also have no @run-at set. I had to use the addEventListener function on previous versions of Greasemonkey, but now it works with everything omitted. – Yani2000 Jan 29 '18 at 20:56
  • @Yani2000 That worked for me as well, but only for some scripts, where I didn’t need to distinguish between running code before the DOM has loaded and after. – Sebastian Simon Jan 29 '18 at 21:00
  • Someone just upvoted this answer. Is it still up to date? I probably need to test this again. – Sebastian Simon Nov 18 '19 at 23:45