1

tl;dr

Don't use exotic dynamic injection of external libraries in Userscript. @require them instead.


Original Question

I am trying to modify this page with the following script:

console.log("run");
!function(){var e=document.createElement("SCRIPT")
e.src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js",e.type="text/javascript",document.getElementsByTagName("head")[0].appendChild(e)
var t=function(e){window.jQuery?e(jQuery):window.setTimeout(function(){t(e)},100)}
t(function(e){e(".title").children().each(function(){this.href="/"+this.href.split("'")[1]})})}()

The script works fine from the console (try it), transforming window-open links to URL hrefs. However, the same script in Tampermonkey does not work (and the debug line shows in the console, indicating that the script is indeed running):

screenshot

These are the settings for the particular script:

screenshot

What am I doing wrong? How can I make the script work from Tampermonkey?


After checking syntax (see comments):

syntax


Changing some commas to semicolons --- this is a mess.

bad parser

Simon Kuang
  • 3,870
  • 4
  • 27
  • 53
  • Have you clicked the check for syntax errors buttons? It's directly to the left of "update url". – Vedaad Shakib May 29 '14 at 00:43
  • @Vedaad, yes, it does say syntax errors (see edit), but the code "works". It's legal JavaScript --- it works form the console. – Simon Kuang May 29 '14 at 00:46
  • Why not simply replace those commas with semi-colons? At least then you can rule that out as a cause – Phil May 29 '14 at 00:52
  • @Phil I tried, rechecking syntax every time. Apparently the syntax parser is buggy. Halfway through I just gave up. See edit. – Simon Kuang May 29 '14 at 00:58
  • @Phil Can you try the code yourself, at least in the console? – Simon Kuang May 29 '14 at 00:59
  • I'm not saying the code doesn't work (it does) but if Tapermonkey is flagging syntax errors, maybe it won't run the script completely / properly. How about you stop trying to minify your code and write it as syntactically verbose as possible? – Phil May 29 '14 at 01:03
  • @Phil Is there a hack that I can use to run it as if it were in the console? – Simon Kuang May 29 '14 at 01:07
  • I don't know, I don't write Tapermonkey scripts. Try this version ~ http://pastebin.com/aeUTLenT – Phil May 29 '14 at 01:15

1 Answers1

2

That script relies on a very short timer for jQuery to load. That is very bad form; it sets up a race condition which might be okay in one circumstance but fail in others.

It might (usually) work from the console because most of the code operates synchronously and it's all in the same scope.

But that code from a Tampermonkey script switches scopes and injects some but not all of the needed code.

Don't use jQuery from a userscript that way! Keep the script sandboxed and use @require for better performance.

In this case, your entire script would become:

// ==UserScript==
// @name     OpenHymnal fix
// @match    http://openhymnal.org/genindex.html
// @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

console.log ("run");

$(".title").children ().each (function () {
    this.href = "/" + this.href.split("'")[1]
} );
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • What's GM? Can you explain `@grant`? – Simon Kuang May 29 '14 at 01:18
  • Probably *Grease Monkey* – Phil May 29 '14 at 01:18
  • 1
    GM is Greasemonkey -- the Firefox add-on that Tampermonkey tries very hard to recreate. In this case `@grant` forces the sandbox back on and only allows the specified `GM_` function(s). The `@grant` minimizes conflicts in both GM and TM, and that script works the same in both. – Brock Adams May 29 '14 at 01:19