Squak Mountain Consulting, Inc. squakmt logo

Replacing Javascript using Greasemonkey greasemonkey icon

Please visit these links to our sponsor: Amazon.com

Search Now:
Amazon Logo


Replacing Javascript using Greasemonkey greasemonkey icon

This information is provided for educational purposes only.
You take all the responsibility for your use of this information.
There is no warranty, no support, no assurances.
There are errors in this information.
If you hurt yourself and/or others, it's your fault.
If you destroy your equipment or invalidate the warranties, it's your fault.

This disclaimer brought to you by one of the best justice systems on Earth.
This web page copyright © 2009-2012 Squak Mountain Consulting, Inc.

I knew it could be done, I just didn't know how: how to replace the code of a javascript function in a webpage.

I *could* do something fancy (and difficult) by hooking into the IP stack and changing the web page as it flys by. That is sort of a heavyweight solution for this problem, to say the least. Or, I could use an add-on tool for firefox, but which one?

I looked at a lot of tools, and found 2 that do the job. One is a debugger. I set a breakpoint on the javascript to force the return value of the javascript function. This is crude, difficult, labor-intensive, but at least it worked. I forgot the name of the debugger, unfortunately.

The other is greasemonkey. At first, this looked to be very difficult. But, like a lot of things, once you know how, it's easy. It turned out to take quite a number of hours to find a technique that would work. I started out by trying to modify 1 character of the script in the DOM. But, I couldn't get the script text to change when I did that. I started digging, and it seems to have to do with security and the context that Greasemonkey is executing in. I'll figure this out eventually. But, for now, I have to get this thing working!

Could I override the entire Javascript function with one of my own? It turned out I could. The official Greasemonkey documentation didn't mention anything like this. I was confused; isn't this a basic thing someone would want to do with a tool like greasemonkey?

I did a lot of searching on the web for "greasemonkey replace javascript" and similar phrases. I had to dig through a lot of false positive hits until I found a useful answer. A very nice person in Barcelona had run into a similar problem, and had written some documentation on it! That documentation can be found here: http://luckyshot.es/blog/greasemonkey-user-scripts-quick-guide at "Inserting Script and CSS Style tags"

It was even written in English, woo hoo! Now, I wasn't sure if this would work, since what is does is add a new Javascript function at the end of all the other scripts. I would then have two scripts with the same name. Wouldn't the two scripts conflict somehow, or at least be rejected by the browser?

A little experimentation showed that this technique has the effect of replacing the original script. The later script overrides the earlier script. Is this by design in Firefox, or did i find a bug? I don't know yet and, for the moment (Firefox 3.0.5), it works.

It turns out it is a feature. JavaScript in non-strict mode will use the last function definition it finds. According to Mozilla a feature called Strict Mode may reject duplicate function definitions as a syntax error. But, the JavaScript specification does not state that clearly.

For non-strict mode, here's how it goes:
First of all, I'm using a function I put on this page for this example, and I put it right near the start of my page, where it's easy for you to find. Here's the function

    <script>
      function getcurrenttime(){
          now=new Date;
          var currenttime = now.getTime();
        }
    </script>
We are going to replace it with
    <script>
      function getcurrenttime(){
          now=new Date;
          var currenttime = now.getTime();
          alert("The time is now: " + now );
        }
    </script>
OK, now let's have you run this example on your browser. You can later take the example and use it as the start of your greasemonkey script. Just install greasemonkey, browse to the page you're reading right now, right-click on the monkey head icon greasemonkey icon , choose "new user script", fill in a name for your script, and paste this code right in there. By default, the script operates on the page you currently have open, so it is good that you are reading this while creating the script!
// ==UserScript==
// @name        get current time alert
// @include     http*
// @grant       none
// ==/UserScript==
    var scriptCode = new Array();   // this is where we are going to build our new script
    
    // here's the build of the new script, one line at a time
    scriptCode.push('function getcurrenttime(){'        );
    scriptCode.push('  now=new Date;'                   );
    scriptCode.push('  var currenttime = now.getTime();');
    scriptCode.push('  alert("The time is: " + now );'  );
    scriptCode.push('}'                                 );
    
    // now, we put the script in a new script element in the DOM
    var script = document.createElement('script');    // create the script element
    script.innerHTML = scriptCode.join('\n');         // add the script code to it
    scriptCode.length = 0;                            // recover the memory we used to build the script
    
    // this is sort of hard to read, because it's doing 2 things:
    // 1. finds the first <head> tag on the page
    // 2. adds the new script just before the </head> tag
    document.getElementsByTagName('head')[0].appendChild(script); 


Now, click this button and you should get the alert:

alert box: The time is now

If you install firebug and look at the html of this page, you'll see that it now has 2 functions with the same name:

firebug display of the 2 functions

The function we just added is the one that got executed. That's all for now!

Troubleshooting:

It didn't work 1:

There are a lot of options in both browsers and Greasemonkey that can affect this. Most of them are security-related options.

It didn't work 2:

This technique usually works if you are running this page from its original location: http://squakmt.com/replacing_javascript/index.htm .
If you are looking at a copy of this page on another blog somewhere, it might not work.

It didn't work 3:

This technique usually works if you are running this page from a web server using the HTTP protocol, like this: http://squakmt.com/replacing_javascript/index.htm .
If you are running this from a non-webserver location, like "file:///...", it doesn't always work.


References:

  1. The code I started out with was at: http://luckyshot.es/blog/greasemonkey-user-scripts-quick-guide at "Inserting Script and CSS Style tags". But, that web site seems to no longer exist. :-(
  2. Firefox
  3. Greasemonkey


Search Now:
Amazon Logo
Advertisements - Please visit my sponsors and help support development!

Valid HTML 4.01