7

There is a page http://example.com/1.php that includes javascript file as usual:

<script type="text/javascript" src="/util.js?1354729400"></script>

This file contain function named exampleFunction which I need to use in my userscript. Also I have an user script:

// ==UserScript==
// @name          SomeName
// @namespace     http://example.com/userscripts
// @description   Greets the world
// @include       http://example.com/*
// ==/UserScript==
window.onload = function () {
        console.log(exampleFunction);
      alert("LOADED!");
}

which works perfectly in Firefox and returns an error in Chrome:

Uncaught ReferenceError: exampleFunction is not defined 

How do I make it work?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Alex
  • 634
  • 1
  • 8
  • 29

3 Answers3

9

The reason that exampleFunction was undefined is because Chrome userscripts operate in a sandbox ("isolated world"). Note that Greasemonkey scripts often operate in a sandbox too, but yours is currently running with an implicit @grant none.
If your script were to use a GM_ function, it would stop working in Firefox too.

To make this script work on both browsers (and a few others, as well), use Script Injection similar to this answer.

However, there is another hitch, since that script is using window.onload. Chrome userscripts, with the default execution start-mode, will often never see the onload event.

To get around that, add // @run-at document-end to the metadata block.

So the script becomes:

// ==UserScript==
// @name            SomeName
// @namespace       http://example.com/userscripts
// @description     Greets the world
// @include         http://example.com/*
// @run-at          document-end
// @grant           none
// ==/UserScript==

function GM_main () {
    window.onload = function () {
        console.log(exampleFunction);
        alert("LOADED!");
    }
}

addJS_Node (null, null, GM_main);

//-- This is a standard-ish utility function:
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • It's not always working... And I can't determine the reason of that – Alex Dec 07 '12 at 20:04
  • 1
    **How** is it "not working"? What are the symptoms ***exactly***? Use the script from the answer with no changes but the `@include` line. **What is the URL of the page** where the script appears not to work? Is that page taking a long time to *completely* load? `onload` will not fire until the last large image, etc., has finished downloading. – Brock Adams Dec 07 '12 at 23:51
  • Try it by yourself: remove "console.log(exampleFunction);" and leave "alert" from the script. Staying on this page, click on your profile link and refresh that page several times. How is it working for you? I don't get onload event in half of cases at all – Alex Dec 08 '12 at 11:37
  • @aljesco, I did that and it works every single page load or refresh, without fail. What version of Chrome are you using? What OS? What are your symptoms and error messages? Temporarily disable all other extensions and try again. – Brock Adams Dec 08 '12 at 15:03
3

If you want the equivalent to onLoad, which doesn't fire till all images on the page are loaded, you want to use // @run-at document-idle in your metadata block. The default, document-end, fires when the DOM is loaded, the equivalent of document.ready.

Noumenon
  • 5,099
  • 4
  • 53
  • 73
1

Have you tried calling examplefunction with brackets ? :) Like this:

console.log(exampleFunction());

If you try it in chrome console, you have to add brackets to call function.

rhorvath
  • 3,525
  • 2
  • 23
  • 30