Changing Javascript on an HTML page out of my control

I am using an HTML page out of my control. It defines the Javascript function in the built-in <script> and calls it in <body onload="..."> :

 <html> ... <body onload="init()"> <script type="text/javascript" language="javascript"> function init() { ... } </script> ... 

How can I change this function before calling it? I tried using Greasemonkey to modify the script, or to insert another script immediately after it, to override the function, but it seems to have no effect.

+4
source share
2 answers

Now, Greasemonkey can usually do such things using the beforescriptexecute event and @run-at document-start . Please note: only Firefox seems to support this event, and therefore this will not work in Chrome. See here and here for more tedious approaches.

To change this init() function before calling it, use the checkForBadJavascripts() function, which 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() also defined below.)


For example, visit this page in jsBin . You will see 3 lines of text, two of which are added by JS.

Now install the following script and go to the page. You will see that the GM script removed one bad <script> and replaced the other with our "good" JS.

 // ==UserScript== // @name _Replace evil Javascript // @include http://output.jsbin.com/tezoni* // @run-at document-start // @grant none // ==/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] Where: 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() + ')()'; var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement; //--- Don't error check here. if DOM not available, should throw error. targ.appendChild (scriptNode); } 
+10
source

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

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

I did not have much previous experience with Greasemonkey or even Javascript, so I found Firefox Web Developer tools indispensable, in particular:

  • Error Console to catch many small errors that you have to make. and
  • The Inspect tool to see the resulting HTML (because the normal view source does not show this!).
-1
source

Source: https://habr.com/ru/post/1315755/


All Articles