Simon Kuang
Simon Kuang

Reputation: 3940

Code from bookmarklet works in console but not in my Tampermonkey script?

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

Upvotes: 1

Views: 1490

Answers (1)

Brock Adams
Brock Adams

Reputation: 93493

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]
} );

Upvotes: 2

Related Questions