2

I'm having a problem when using the @run-at document-start directive. I'm sure it comes down to inexperience, but for the life of me I can't figure this out.

Save for a few other directives this is the entire script.

// @require https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js  
// @run-at  document-start

And the error in FF

Error: document.documentElement is null  
Source File: file:///C:/Users/---/Test-1/jquery.js  
Line: 4899

I see and understand the problem, I'm just not sure what steps to take to allow me to run my script as close to document-start as possible, but still have @required scripts function properly.
A little nervous about my first post... go easy please :)

Firefox 12
Greasemonkey 0.9.20

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
MeltingPoint
  • 23
  • 1
  • 2

1 Answers1

1

Yes, this is a drawback of using // @run-at document-start. @required scripts that attempt to manipulate the DOM may throw errors. (But many @required libraries are fine, as they merely load tools that are activated by your code later).

You can work around this by using @resource, eval(), and by monitoring readyState. Like so:

// ==UserScript==
// @name        _Using DOM-manipulating libraries with run-at start
// @include     http://YOUR_SERVER/YOUR_PATH/*
// @run-at      document-start
// @resource    jQ_src https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js
// ==/UserScript==

var jQ_src  = GM_getResourceText ("jQ_src");

window.addEventListener ("readystatechange", FireWhenReady, true);

function FireWhenReady () {
    this.fired  = this.fired || false;

    if (    document.readyState != "uninitialized"
        &&  document.readyState != "loading"
        &&  ! this.fired
    ) {
        this.fired = true;
        eval (jQ_src);
        $(document).ready (DoStuff);
    }
}

function DoStuff () {
    //--- Where this next paragraph appears can give you an idea of the delays involved...
    $("body").append ('<p style="background:yellow;">Hello from quick-start jQuery!</p>');
}

Important! For libraries like jQuery, there is not much point in using @run-at document-start, because jQuery won't let you do anything until $(document).ready() anyway, and this is when Greasemonkey fires by default.

Loading jQuery early buys you nothing, because then you must explicitly use $(document).ready() (or one of the shortcut forms). You may have other reasons to use @run-at document-start, and then also want to use jQuery later, perhaps.

Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Thanks for the quick answer, that code will really help me out. Just to be clear, I wasn't making any calls to jQuery, literally just the lines in the OP caused the error. And you are correct about having reasons, cosmetic as they are, a screen wide banner that I just can't seem to hide without causing 'flickering' or in my case, a pretty jarring screen jump. Thanks again! – MeltingPoint May 17 '12 at 04:43
  • You're welcome. For getting rid of "screen wide banners", if [Adblock](https://addons.mozilla.org/en-US/firefox/addon/adblock-plus/) can't nuke it, chances are [Stylish](https://addons.mozilla.org/en-US/firefox/addon/stylish/) can. These both operate more efficiently than Greasemonkey for that kind of thing and will not cause flicker. Adblock will also free bandwidth and speedup the page (Ads aren't allowed to download). – Brock Adams May 17 '12 at 04:55