5

I'm @require-ing jQuery for my Greasemonkey script with this line in my script file:

// @require https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js

and it works quite well; I can use $('#id') to access the DOM.

However, the $ variable of the 'real' page is modified (where $ is jQuery 1.2.xx): I get an error that $.include is not defined.

I thought the sandbox model of Greasemonkey would prevent that the variables of the target-page are overwritten?

How can I ensure that the inclusion of javascript libraries does not affect the 'real' website, but only my Greasemonkey script?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
manuels
  • 1,511
  • 3
  • 14
  • 26

2 Answers2

10

Greasemonkey 1.0, radically changed the way the sandbox works, busting thousands of scripts. See also, jQuery in Greasemonkey 1.0 conflicts with websites using jQuery.

This is a huge problem, and I hope you will join me in voicing your opinion/experiences on the principle bug report for this issue.

Meanwhile, restore the sandbox to your script, and resolve the $ conflict, by editing your Metadata Block to end with the following lines:

// @grant       GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a major design change introduced in GM 1.0,
    It restores the sandbox.
*/


Specifying a @grant value (other than none) reactivates the sandbox.


You might also consider switching to Scriptish, which has offered superior features and performance in the past, and does not suffer from this new sandbox behavior.

Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
3

See jQuery.noConflict();; it explains a lot.

EDIT:
Found "Greasemonkey 1.0 + jQuery: Broken, with Workaround" on searching.

Possible solution:

 this.$ = this.jQuery = jQuery.noConflict(true);

Doing that, probably will implicitly specify that $, jQuery will be available in your script's namespace.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Prasanth
  • 5,230
  • 2
  • 29
  • 61
  • calling `unsafeWindow.$.noConflict()` does not bring back the 'old' jQuery version but after this call `$` is `undefined`. Why is is replaced in the first place? – manuels Sep 03 '12 at 16:23
  • because, through `unsafeWindow`, you are accessing the page's js. I think you want to do `$.noConflict();` on the userscript. – Prasanth Sep 03 '12 at 16:34
  • not really: the `$.include` not defined error is raised by the page's js. – manuels Sep 03 '12 at 22:18
  • I don't believe the `noConflict()` hack works in all cases (but I'm not going to work up a test case right now). It's the wrong approach, the most robust solution is to restore the sandbox. – Brock Adams Sep 04 '12 at 00:18