how to run greasemonkey script before the page content is displayed?

25,165

Solution 1

EDIT: This post was created prior to the implementation of the @run-at key in Greasemonkey - as noted by Blaise, from Greasemonkey 0.9.8 you may now have the script executed as soon as the page begins to load.

@run-at document-start is described in the wiki as follows:

Start is new as of version 0.9.8. The script will run before any document begins loading, thus before any scripts run or images load.

Note that this means having the script run (potentially) prior to the creation of the DOM and may lead to some inconsistent/unusual behaviour. You will need (a little) more than just this one-line drop-in.

There are a few more details over at the Greasemonkey Wiki: http://wiki.greasespot.net/Metadata_Block#.40run-at

Side-note: The information I have to hand is specifically related to Greasemonkey in the browser. I am unsure whether @run-at document-start works well with the script compiler - I suggest living dangerously.. Test it and find out! ;]



It is not currently possible to run a user script before the page loads.

To stop the flicker using current versions of Greasemonkey, you could try adding a user-style to your Firefox profile (which is then undone using the script) as described at the Greasemonkey wiki but this would also require each of your users to do the same to benefit from this.

It is something that has been desired for a long time and looking through issue #1103 on Greasemonkey's Github site, a working prototype appears to have been made (but there is no timescale for this to be added to a release version afaik).

Solution 2

In addition to the previous answers I've found a solution that works flawlessly, just like previous versions of Firefox & GreaseMonkey. First off, run-at must be set to the earliest moment, so document-start:

// @run-at      document-start

Because the DOM is probably not loaded yet, wait for the document to get a readyState of interactive:

document.onreadystatechange = function () {
    if (document.readyState === "interactive") {
       // Do something
    }
}

While Greasemonkey implements more or less the same with document-end, I've noticed that the technique above works faster. Using this has resolved all issues I had in Firefox with flashing / jumping screens on pages when the DOM changes kicked in and directly loads the page as intended with the userscript.

Solution 3

Using the @run-at document-start as suggested in the answer by @kwah my script executed before the content I wanted to manipulate was in the document body. As a work-around I set up an interval running my script 5 times/second until document.readyState == "complete" (or until 20 seconds have passed).

This worked well for my case:

// ==UserScript==
// ...
// @run-at      document-start
// ==/UserScript==

var greasemonkeyInterval = setInterval(greasemonkey, 200);
var greasemonkeyStart = (new Date()).getTime();

function greasemonkey() {

    // ...

    // waiting for readyState (or timeout)
    if (
        (new Date()).getTime() - greasemonkeyStart > 20000
        || document.readyState == "complete"
    ) {
        clearInterval(greasemonkeyInterval);
    }

};

If you're more sure about that the content will be there at documentready I think something like this would be more preferable:

function greasemonkey() {

    if (
        document.readyState != "interactive"
        && document.readyState != "complete"
    ) {
        return;
    }

    // ...

    clearInterval(greasemonkeyInterval);

}
Share:
25,165

Related videos on Youtube

khr2003
Author by

khr2003

Updated on July 09, 2022

Comments

  • khr2003
    khr2003 almost 2 years

    I am writing a plug-in for Firefox and using greasemonkey script to do that (I compile the user script using this tool http://arantius.com/misc/greasemonkey/script-compiler).

    The issue is that the script is run after the page is fully loaded. Meaning the user would see the viewed page in its original form and then the script will apply the changes that I made. My question is there a way to run the user script before the contents of the page is displayed to the user, so the user would only the final version of the website?

    • Brock Adams
      Brock Adams over 13 years
      This is probably not possible with add-ons generated by that compiler -- which, like GM, run after the DOM is fully loaded and operate by JavaScript injection. You probably need to use more "Typical" add-on/extension techniques to filter the page as it is downloaded. That is, you need to write an extension, not port a GM script.
    • Neil
      Neil over 13 years
      Even if you write an extension, the browser will start displaying the page in its original form before it's fully loaded.
  • Blaise
    Blaise over 11 years
    That bug has been fixed and you can now run scripts before the page loads by adding this to the meta section: @run-at document-start
  • kwah
    kwah over 11 years
    Cheers Blaise - I have updated my answer to reflect the changes in Greasemonkey since first posting the answer. I am not sure how well @run-at document-start works with the script compiler as I have not been involved with Greasemonkey for quite a while now.