我正在使用我无法控制的HTML页面。它在内联<script>
代码中定义了一个Javascript函数,并在<body onload="...">
中调用它:
<html>
...
<body onload="init()">
<script type="text/javascript" language="javascript">
function init() {
...
}
</script>
...
如何在调用之前更改该功能?我曾尝试使用Greasemonkey修改脚本或在其后插入另一个脚本来覆盖该函数,但它似乎没有任何效果。
答案 0 :(得分:10)
Greasemonkey现在可以通常通过利用the beforescriptexecute
event和@run-at document-start
来做这件事。请注意,只有Firefox似乎支持该事件,因此这不适用于Chrome。有关更繁琐的方法,请参阅here和here。
要在调用init()
函数之前更改它,请使用下面定义的checkForBadJavascripts()
函数。
你会这样称呼:
//--- New "init" function to replace the bad one.
function init () {
//... Do what you want here...
}
checkForBadJavascripts ( [
[false, /function\s+init(/, function () {addJS_Node (init);} ]
] );
function\s+init(
对于您定位的<script>
标记必须是唯一的。 (请注意,addJS_Node()
也定义如下。)
例如,访问this page at jsBin。您将看到3行文本,其中两行由JS添加。
现在,安装以下脚本并重新访问该页面。您将看到GM脚本删除了一个错误的<script>
标记,并用我们的“好”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);
}
答案 1 :(得分:-1)
以下Greasemonkey用户(基于this source)终于为我工作了。它通过在现有script
标记之后的新script
标记中定义另一个具有相同名称的函数来覆盖现有函数。无需@run-at
或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);
我之前没有使用Greasemonkey甚至是Javascript的经验,所以我发现Firefox Web Developer工具不可或缺,具体来说: