Take the 2-minute tour ×

I'm using an HTML page out of my control. It defines a Javascript function in an inline <script> tag and calls it in <body onload="..."> :

<body onload="init()">
    function init() {

How can I change that function before it's called? I've tried to use Greasemonkey to modify the script or to insert another script just after it to override the function, but it doesn't seem to have any effect.

share|improve this question

migrated from superuser.com May 6 '12 at 17:20


how much is this HTML page out of your control if you can still modify the JavaScript on it? –  Hawken May 6 '12 at 3:28
@Hawken: Greasemonkey is a browser add-on for rewriting incoming HTML just before it's rendered –  palm3D May 7 '12 at 15:35

2 Answers 2

Greasemonkey can now usually do this kind of thing by leveraging the beforescriptexecute event and @run-at document-start. Note that only Firefox seems to support that event and so this will not work on Chrome. See here and here for more tedious approaches.

To change that init() function before it is called, leverage the checkForBadJavascripts() function that is defined below.

You would call it like this:

//--- New "init" function to replace the bad one.
function init () {
    //... Do what you want here...

checkForBadJavascripts ( [
    [false, /function\s+init(/, function () {addJS_Node (init);} ]
] );

Where function\s+init( must be unique to the <script> tag you are targeting. (Note that addJS_Node() is defined below, too.)

For example, visit this page at jsBin. You will see 3 lines of text, two of them added by JS.

Now, install the following script and revisit the page. You will see that the GM-script deleted one bad <script> tag and replaced another with our "good" JS.

// ==UserScript==
// @name        _Replace evil Javascript
// @include     http://jsbin.com/ogudon*
// @run-at      document-start
// ==/UserScript==

/****** New "init" function that we will use
    instead of the old, bad "init" function.
function init () {
    var newParagraph            = document.createElement ('p');
    newParagraph.textContent    = "I was added by the new, good init() function!";
    document.body.appendChild (newParagraph);

/*--- Check for bad scripts to intercept and specify any actions to take.
checkForBadJavascripts ( [
    [false, /old, evil init()/, function () {addJS_Node (init);} ],
    [true,  /evilExternalJS/i,  null ]
] );

function checkForBadJavascripts (controlArray) {
    /*--- Note that this is a self-initializing function.  The controlArray
        parameter is only active for the FIRST call.  After that, it is an
        event listener.

        The control array row is  defines like so:
        [bSearchSrcAttr, identifyingRegex, callbackFunction]
            bSearchSrcAttr      True to search the SRC attribute of a script tag
                                false to search the TEXT content of a script tag.
            identifyingRegex    A valid regular expression that should be unique
                                to that particular script tag.
            callbackFunction    An optional function to execute when the script is
                                found.  Use null if not needed.
    if ( ! controlArray.length) return null;

    checkForBadJavascripts      = function (zEvent) {

        for (var J = controlArray.length - 1;  J >= 0;  --J) {
            var bSearchSrcAttr      = controlArray[J][0];
            var identifyingRegex    = controlArray[J][1];

            if (bSearchSrcAttr) {
                if (identifyingRegex.test (zEvent.target.src) ) {
                    stopBadJavascript (J);
                    return false;
            else {
                if (identifyingRegex.test (zEvent.target.textContent) ) {
                    stopBadJavascript (J);
                    return false;

        function stopBadJavascript (controlIndex) {
            zEvent.stopPropagation ();
            zEvent.preventDefault ();

            var callbackFunction    = controlArray[J][2];
            if (typeof callbackFunction == "function")
                callbackFunction ();

            //--- Remove the node just to clear clutter from Firebug inspection.
            zEvent.target.parentNode.removeChild (zEvent.target);

            //--- Script is intercepted, remove it from the list.
            controlArray.splice (J, 1);
            if ( ! controlArray.length) {
                //--- All done, remove the listener.
                window.removeEventListener (
                    'beforescriptexecute', checkForBadJavascripts, true

    /*--- Use the "beforescriptexecute" event to monitor scipts as they are loaded.
        See https://developer.mozilla.org/en/DOM/element.onbeforescriptexecute
        Note that it does not work on acripts that are dynamically created.
    window.addEventListener ('beforescriptexecute', checkForBadJavascripts, true);

    return checkForBadJavascripts;

function addJS_Node (text, s_URL, funcToRun) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    //--- Don't error check here. if DOM not available, should throw error.
    targ.appendChild (scriptNode);
share|improve this answer

The following Greasemonkey userscript (based on this source) finally worked for me. It overrides the existing function by defining another one with the same name in a new script tag just after the existing script tag. No @run-at or beforescriptexecute was required.

var firstScript = document.body.getElementsByTagName('script')[0];
var newScript = document.createElement('script');
var scriptArray = new Array();
scriptArray.push('function init() {');
scriptArray.push('    ...');
newScript.innerHTML = scriptArray.join('\n');
scriptArray.length = 0; // free this memory
firstScript.parentNode.insertBefore(newScript, firstScript.nextSibling);

I didn't have much previous experience with Greasemonkey or even Javascript, so I found the Firefox Web Developer tools indispensable, specifically:

  • the Error Console to catch the many small errors that you're bound to make. and
  • the Inspect tool to see the resulting HTML (because the regular View Source doesn't show that!).
share|improve this answer
If this works, I believe it's pure luck. It sets up a "race condition" which means that though it might work on some pages, some of the time, it shouldn't work on other pages, depending upon their composition. –  Brock Adams May 7 '12 at 22:51

Your Answer


