How to Override a Global JS Function from a .js File Using Greasemonkey

4,212 views
Skip to first unread message

Shlomi Fish

unread,
Nov 5, 2007, 11:11:40 AM11/5/07
to greasemon...@googlegroups.com
Hi all!

I'm new to this list, and this is my first post.

I'm trying to fix the broken-in-Firefox JavaScript code of
http://www.yjobs.co.il/ , which uses outerHTML and other MSIE-specific
horrors. I'm trying to over-ride the function "SaveSelectBoxs()" that appears
in http://www.yjobs.co.il/in.js using Greasemonkey. This affects the upper
Find ("מצא") button.

Now, as I discovered if I put its new definition in the .user.js file, like
so:

{======================

function SaveSelectBoxs() {
var sSelects = "";
var nSelected = "";
.
.
.
}

======================}

(Occupying my entire script.)

The page still misbehaves. However, if I paste the new definition into the
Firebug script evaluation editor, and evaluate it, the find button starts
working.[1]

So what I figured out was that the in.js was evaluated *after* the .user.js
one, and so over-rided it. So I'm looking for a while to delay evaluating the
function to after all the JavaScript in the page completely loads and
compiles. Someone I talked with suggested I use a JS timeout, but that seems
like a kludge.

Any help would be appreciated. I couldn't find anything specifically about it
in the Greasemonkey book.

Regards,

Shlomi Fish

[1] - There are other errors that prevent the resultant page to be used
properly, but I figured out I can resolve them afterwards in a similar
manner.
---------------------------------------------------------------------
Shlomi Fish shl...@iglu.org.il
Homepage: http://www.shlomifish.org/

I'm not an actor - I just play one on T.V.

Anthony Lieuallen

unread,
Nov 5, 2007, 11:21:25 AM11/5/07
to greasemon...@googlegroups.com
On 11/5/2007 11:11 AM, Shlomi Fish wrote:
> Any help would be appreciated. I couldn't find anything specifically
> about it in the Greasemonkey book.

I don't know what you mean by "the" greasemonkey book, but you probably
mean Dive Into Greasemonkey, which was once /great/, but is now out of
date and largely wrong.

Read the wiki [1] and especially the article it links to [2] by the same
author as DiG and more up to date. That article answers the vast
majority of questions asked on this list.

(Hint: execution time is not your only/primary issue. Your primary
issue is that GM scripts execute in their own scope, separate from the
page.)

[1] http://wiki.greasespot.net/Main_Page
[2] http://www.oreillynet.com/lpt/a/6257

chaichana nilwatchararang

unread,
Nov 6, 2007, 12:26:15 PM11/6/07
to greasemonkey-users
hi ! this is my first post too :)
hope it'll help ...
greasemonkey run in a sandbox, not the same environment of the page...
It will disappeared after everything is executed and no reference left
to point to anything in gm script.
so,your cannot define a function in your script because your function
will gone after everything in your script has been executed.
you must go with addEventListener to create a reference to your
script ... so i can stay there in sandbox .
=========
for example::
var elem=document.getElementById('a3');
elem.addEventListener("click",SaveSelectBoxs2 , true);
then write your own version of SaveSelectBoxs ....
=========
or inject your own script in the original page
example::
var script = document.createElement("script");
script.setAttribute('type','text/javascript');
script.text="function SaveSelectBoxs(){alert('yo');}";
document.body.appendChild(script);
=========
hope it will help ... someone correct me if i'm wrong

Shlomi Fish

unread,
Nov 6, 2007, 2:29:14 PM11/6/07
to greasemon...@googlegroups.com, Anthony Lieuallen
Hi!

On Monday 05 November 2007, Anthony Lieuallen wrote:
> On 11/5/2007 11:11 AM, Shlomi Fish wrote:
> > Any help would be appreciated. I couldn't find anything specifically
> > about it in the Greasemonkey book.
>
> I don't know what you mean by "the" greasemonkey book, but you probably
> mean Dive Into Greasemonkey, which was once /great/, but is now out of
> date and largely wrong.

Yes, that's what I meant. I should note that it's still featured in
http://www.greasespot.net/ , and the Wiki was not featured in a place that I
noticed there. Perhaps these things ought to be fixed.

>
> Read the wiki [1] and especially the article it links to [2] by the same
> author as DiG and more up to date. That article answers the vast
> majority of questions asked on this list.
>

Thanks. I eventually found the solution to my problem here:

http://wiki.greasespot.net/Code_snippets#Embed_a_function_in_the_current_page

What I eventually did in my .user.js was:

<<<<<<<<<<<<<<<

function SaveSelectBoxs() {
// SNIPPED
}

function embedFunction(s) {
document.body.appendChild(document.createElement('script')).innerHTML=s.toString().replace(/([\s\S]*?return;)
{2}([\s\S]*)}/,'$2');
}

embedFunction(SaveSelectBoxs);

>>>>>>>>>>>>>>>

This made it work.

I'll fully read http://www.oreillynet.com/lpt/a/6257 later.

> (Hint: execution time is not your only/primary issue. Your primary
> issue is that GM scripts execute in their own scope, separate from the
> page.)
>

OK.

Regards,

Shlomi Fish

Shlomi Fish

unread,
Nov 6, 2007, 2:37:29 PM11/6/07
to greasemon...@googlegroups.com, chaichana nilwatchararang
Hi!

A note - please format your message more properly. Use linebreaks between
paragraphs, etc. And use proper capitalisation.

On Tuesday 06 November 2007, chaichana nilwatchararang wrote:
> hi ! this is my first post too :)
> hope it'll help ...

It is helpful and would have helped if I hadn't read Anthony Lieuallen's
message and managed accordingly.

> greasemonkey run in a sandbox, not the same environment of the page...
> It will disappeared after everything is executed and no reference left
> to point to anything in gm script.
> so,your cannot define a function in your script because your function
> will gone after everything in your script has been executed.
> you must go with addEventListener to create a reference to your
> script ... so i can stay there in sandbox .
> =========
> for example::
> var elem=document.getElementById('a3');
> elem.addEventListener("click",SaveSelectBoxs2 , true);
> then write your own version of SaveSelectBoxs ....

That's not good enough because the function is called from other functions.

> =========
> or inject your own script in the original page
> example::
> var script = document.createElement("script");
> script.setAttribute('type','text/javascript');
> script.text="function SaveSelectBoxs(){alert('yo');}";
> document.body.appendChild(script);

That's what I eventually did, but while using .toString() and the
embedFunction() function from the snippets on the site.

Regards,

Shlomi Fish

> =========
> hope it will help ... someone correct me if i'm wrong
>
>
>

esquifit

unread,
Nov 6, 2007, 6:00:07 PM11/6/07
to greasemon...@googlegroups.com
unsafeWindow.SaveSelectBoxs = function(){alert("Hello World!")};

http://wiki.greasespot.net/UnsafeWindow

En/na Shlomi Fish ha escrit:

Chaichana Nilwatchararang

unread,
Nov 7, 2007, 12:54:53 AM11/7/07
to Shlomi Fish, greasemon...@googlegroups.com
:$
Sorry for improper writing. Thanks for warning me about this.

paka

unread,
Dec 10, 2007, 2:09:43 PM12/10/07
to greasemonkey-users
There is a simpler way to do all this if you trust the site that you
are rewriting the script for. This method will create a persistent
function replacement by providing access to the original native script
(that is outside of the sandbox). This used to be the default in
Greasemonkey until it was seen that a hostile site could rewrite your
user scripts and compromise your computer. (This whole security issue
was highly overblown, IMO). The "unsafeWindow" variable is a reference
to the actual window with all of it's variables, functions, scripts,
etc. Use this to provide the same direct access to original scripts
and variables as in the old "unsafe" GM.

To replace a function completely, simply use this syntax:

unsafeWindow.originalFunction = function(p1, p2, p3...) {
... do your own thing with the parameters normally passed to the
originalFunction...
}

This creates a persistent altered function indistinguishable from the
original. Other scripts, both native and sandbox will recognize it for
the life of the window.

paka

unread,
Dec 10, 2007, 3:28:57 PM12/10/07
to greasemonkey-users
When using unsafeWindow to create persistent function replacements,
please note that any references to other objects within the altered
function, must be persistent also. Do not reference sandboxed (i.e.
temporary) variables within the altered function; any objects within
your function need also to be referenced as "unsafeWindow":

unsafeWindow.originalFunction = function(p1, p2, p3...) {
var oldTable =
unsafeWindow.document.getElementsByTagName("table")[0] //access
existing table
var newDiv = unsafeWindow.document.createElement("div"); //
create new var
}

you can also do this for shorthand at the beginning of your GM script:

var uw = unsafeWindow

Then you can reference any unsafeWindow object as: [uw.object]
anywhere in your GM script

Big Jim

unread,
Dec 11, 2007, 9:33:01 PM12/11/07
to greasemonkey-users
Just wanted to say thanks to those who helped in this thread.

So.. thanks. =)

paka

unread,
Dec 12, 2007, 7:54:55 PM12/12/07
to greasemonkey-users
> Thanks. I eventually found the solution to my problem here:
>
> http://wiki.greasespot.net/Code_snippets#Embed_a_function_in_the_curr...
>
> What I eventually did in my .user.js was:
>
> <<<<<<<<<<<<<<<
>
> function SaveSelectBoxs() {
> // SNIPPED
>
> }
>
> function embedFunction(s) {
> document.body.appendChild(document.createElement('script')).innerHTML=s.toString().replace(/([\s\S]*?return;)
> {2}([\s\S]*)}/,'$2');
>
> }
>
> embedFunction(SaveSelectBoxs);
>
>
>
> This made it work.
You may get limited functionality using the embedFunction solution.
However, certain references within the embedded functions will be
unavailable after the page is loaded. The embedFunction method does
not allow embedded functions access to:
a) variables created by other (original source) scripts on the
page
b) variables created by other user (GM) scripts on the page

In the case of (a) it is presumably because Firefox treats the global
variables created in other scripts as though they were created with a
local visibility. This may be because the newly embedded function,
being created on the fly, does not share the same codespace with the
native scripts. It can know about page elements only, but not cross-
scripted global variables.

In the case of (b), variables from other user scripts created in the
sandbox have dissapeared along with the sandbox, making all of those
"global" vars destroyed for subsequent events occurring on the page
(those triggered by user actions).

Since Greasemonkey effectively isolates ALL of the original native
scripts and variables by creating copies wrapped in individual
XPCNativeWrappers, the only absolute way to persistently alter those
scripts and variables (for access during user triggered events) is to
"unwrap" them using the "unsafeWindow" object reference.
Unfortunately, this means that when you redefine a native function
(such as alert()) or one which was previously defined in the original
source, each and every reference to a wrapped object or method WITHIN
that redefined function also needs to be unwrapped by using the
unsafeWindow.obj sytax. (I don't see any way around this, though in a
future version of GM, it would be great to have a NOWRAP option scoped
to the current GM function.)

This repetitive unwrapping can be daunting if the redefined functions
reference such objects or methods extensively. The good news is that
any UNaltered original source functions and vars which refer to or
call unsafeWindow referenced objects will treat your objects as
original source, unlike with the embedFunction method, which will fail
when referencing these objects.
>
> I'll fully readhttp://www.oreillynet.com/lpt/a/6257later.
>
> > (Hint: execution time is not your only/primary issue. Your primary
> > issue is that GM scripts execute in their own scope, separate from the
> > page.)
>
> OK.
>
> Regards,
>
> Shlomi Fish
>
> > [1]http://wiki.greasespot.net/Main_Page
> > [2]http://www.oreillynet.com/lpt/a/6257
>
> ---------------------------------------------------------------------
> Shlomi Fish shlo...@iglu.org.il
Reply all
Reply to author
Forward
0 new messages