I use Tampermonkey 4.8.41 stable/4.9.6004 beta in Chrome 77 (win 10).
I have this userscript (written with a great help from Stack Overflow) for the site metal-archives.com.
In its simplest form it's as follows:
// ==UserScript==
// @name Metal Archives discography pages - Test
// @include /^https?:\/\/www\.metal-archives\.com/bands?/.*$/
// @grant none
// @require https://greasyfork.org/scripts/12036-mutation-summary/code/Mutation%20Summary.js
// @require https://greasyfork.org/scripts/5844-tablesorter/code/TableSorter.js
// ==/UserScript==
function handleDiscographyChanges (muteSummaries) {
var mSummary = muteSummaries[0];
if (mSummary.added.length) {
var tbl = $(mSummary.added[0])[0];
$(tbl).tablesorter ( {} );
}
}
new MutationSummary ( {
callback: handleDiscographyChanges,
rootNode: $('#band_disco')[0],
queries: [ {element: '.discog'} ]
} );
The issue that I'm having is that, when running it in
e.g. https://www.metal-archives.com/bands/Kamelot/166 (DISCOGRAPHY > MAIN tab),
then not the page's jQuery nor the tablesorter @require seem to work for the script anymore.
(The userscript until recently would make use of the page's jQuery 1.11.1 (because of the script's '@grant none' imperative), located inside the combined jQuery libraries file:
http://www.metal-archives.com/min/index.php?g=js )
I'm initially getting in Chrome console:
> ERROR: Execution of script 'Metal Archives discography pages - Test' failed! jQuery is not defined
and if I add the following inside the script's header:
// @require https://code.jquery.com/jquery-1.11.1.min.js
then I'm getting:
Uncaught TypeError: $(...).tablesorter is not a function
even though in the script's 'Externals' tab, Tablesorter.js exists ok.
If it helps, I've also tried the script in latest Tampermonkey versions (stable/beta) in Firefox 69,
and I'm getting the exact same issues, but, there's a difference:
if at Firefox launched, the focused tab is a metal-archives.com restored tab (e.g.) ,
then usually the script initially works ok, until I reload the page (i.e. then I'm getting the issue described above)
Kindly cc'ing @BrockA (he is the one that helped me the most with this script - thank you! ),
in case he'd like to help me confirm whether it's a Tampermonkey issue or something that could be fixed in the script.
This is not a Tampermonkey issue. That page changed the way it loads jQuery, so it won't be present when your script fires (but about half a second later).
So you must @require jQuery and you must do it before TableSorter.js.
Then you must change the @grant to prevent destructive conflicts.
Like so:
// ==UserScript==
// @name Metal Archives discography pages - Test
// @include /^https?:\/\/www\.metal-archives\.com/bands?/.*$/
// @grant GM_addStyle
// @require https://code.jquery.com/jquery-1.11.1.min.js
// @require https://greasyfork.org/scripts/12036-mutation-summary/code/Mutation%20Summary.js
// @require https://greasyfork.org/scripts/5844-tablesorter/code/TableSorter.js
// ==/UserScript==
Thank you so much!! Now it works again!
Just one clarification please, if it's not too much to ask:
could you please explain how did you manage to find that "_the page's jQuery won't be present when your script fires, but about half a second later_", i.e. the point when the page's jQuery becomes available, in relation with the time of the script's @require files injection?
I'm asking because I tried checking Chrome 78's devtool 'Network', as well as Tampermonkey's 'background.html' page, and in none of them are the @require files of the script listed.
It would be great for me to learn how, as future reference for my other scripts.
Hi, sorry for the late reply, but I've been traveling the last few days.
@BrockA Thanks for helping out.
I'm asking because I tried checking Chrome 78's devtool 'Network', as well as Tampermonkey's 'background.html' page, and in none of them are the @require files of the script listed.
@require files are cached by Tampermonkey. They appear at the 'background.html' page only when they're updated.

It would be great for me to learn how, as future reference for my other scripts.
A great starting point always is to add a debugger; statement in order to check the environment i.e. at script start.
@derjanb Thanks for the reply.
So, I added a debugger; right after the script's metadata block, kept the Chrome devtools open, refreshed a metal-archives page, and so the execution stopped at the start of the script.
I checked the devtools 'Sources' tab,
and noticed in the path of metal-archives.com > min the index.php?g=js file was not yet listed at that time, i.e. the page's jQuery was not yet loaded. After multiple pressing of F10 (step over next function call) the index.php?g=js file became listed, but, unfortunately, there was no execution duration info in the 'Sources' devtool at that time.
Also, as I mentioned above, the @require files of the script are not listed in Chrome 78's 'Network' devtool, nor in Tampermonkey's 'background.html' page > 'Network' tab.
And as you said:
They appear at the 'background.html' page only when they're updated.
so, summarizing, it seems to me there's no way to display in the same timeline both the page's jQuery and the script's @require files.
So, dear @BrockA, how did you manage to find that the page's jQuery was loaded about half a second later after the script fires? i.e. how did you find the specific duration?
Could you please educate me upon this? I've searched StackOverflow and couldn't find any relevant question.
When you see that a page is using things like rocket-loader, it usually means that the page's JS will load after your script fires.
You can measure the actual delay with code like:
console.time ("jQ loaded");
var J = 0;
console.log (J, "jQuery type: ", typeof jQuery);
var jqLoadedTmr = setInterval ( function() {
J++;
console.log (J, "jQuery type: ", typeof jQuery);
if (typeof jQuery === "function") {
clearInterval (jqLoadedTmr);
console.timeEnd ("jQ loaded");
}
}
, 100
);
Thanks a lot once more, @BrockA ! I'm grateful!
Most helpful comment
This is not a Tampermonkey issue. That page changed the way it loads jQuery, so it won't be present when your script fires (but about half a second later).
So you must
@requirejQuery and you must do it before TableSorter.js.Then you must change the
@grantto prevent destructive conflicts.Like so: