在 greasemonkey 脚本中显示元素后立即修改元素(而不是在页面完全加载后)?
Modify elements immediately after they are displayed (not after page completely loads) in greasemonkey script?
我有this script。应用于RottenTomatoes电影页面,修改3个元素
(工具提示中有 1 个可见文本和 2 个文本)。
目前,(由于 greasemonkey 的 @run-at document-end
)它仅在页面完全加载后 修改元素 。
此外,RottenTomates 页面有很多次延迟加载,最多 20 秒(!),
所以这是我脚本的额外延迟。
这会导致两件事:
- 延迟显示修改后的可见文本,
- 如果您在页面完全加载之前将鼠标悬停在任一工具提示中,那么在页面加载之后,它可能只包含初始文本而没有我添加的内容,或者只是我添加的内容。
要查看此内容,请安装 script and then visit this typical target page。
RottenTomatoes 页面通过 XHR 加载各种内容(正如我在 Firefox Netowork Monitor 中看到的那样),
但是 3 个元素(我想修改的)立即显示,而不是在页面完全加载时显示。
我曾尝试使用 MutationObserver
来观察屏幕上出现的特定文本值,但它似乎不起作用。它的结构是这样的:
var target = selector_for_element_containing_text ; // the selector is: document.querySelector('.audience-info > div:nth-child(1)');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
modifyElements();
});
});
var config = { attributes: true, childList: true, characterData: true, subtree: true };
observer.observe(target, config);
function modifyElements(){ // This is just the current code of my script
// modify element 1
// modify element 2
// modify element 3
}
如何在元素显示后立即修改?
通过将此代码添加到脚本元区块,在 document-start
制作脚本 运行:
..............
// @run-at document-start
..............
// ==/UserScript==
现在,当脚本 运行s 文档中没有任何内容时,我们会将观察者附加到文档根目录,并将扫描添加的节点以查找容器元素 .audience-info
:
var observer = new MutationObserver(function(mutations) {
for (var i=0; i<mutations.length; i++) {
var mutationAddedNodes = mutations[i].addedNodes;
for (var j=0; j<mutationAddedNodes.length; j++) {
var node = mutationAddedNodes[j];
if (node.classList && node.classList.contains("audience-info")) {
node.firstElementChild.innerHTML = node.firstElementChild.innerHTML
.replace(/[\d.]+/g, function(m) { return 2 * m });
// don't hog resources any more as we've just done what we wanted
observer.disconnect();
return;
}
}
}
});
observer.observe(document, {childList: true, subtree: true});
当观察者被调用时,工具提示已经存在于文档树中,因此您可以简单地将代码从 "load" 函数移至 return
之前的观察者中,而无需更改任何内容。
N.B。最好让观察者尽可能快,特别是使用普通的 for
循环而不是函数回调,因为调用它们会产生开销,这可能会在打开一个缓慢的 PC/device 时成为一个问题非常复杂的页面,会产生数千(很常见的情况)或数十万的突变(极其罕见但仍然存在!)。并在工作完成后断开连接。
P.S。使用 setMutationHandler 函数,观察者代码将是:
// @require https://greasyfork.org/scripts/12228/code/setMutationHandler.js
// ==/UserScript==
setMutationHandler(document, '.audience-info div:first-child', function(nodes) {
this.disconnect();
nodes.forEach(function(n) {
n.innerHTML = n.innerHTML.replace(/[\d.]+/g, function(m) { return 2*m });
});
});
我有this script。应用于RottenTomatoes电影页面,修改3个元素
(工具提示中有 1 个可见文本和 2 个文本)。
目前,(由于 greasemonkey 的 @run-at document-end
)它仅在页面完全加载后 修改元素 。
此外,RottenTomates 页面有很多次延迟加载,最多 20 秒(!),
所以这是我脚本的额外延迟。
这会导致两件事:
- 延迟显示修改后的可见文本,
- 如果您在页面完全加载之前将鼠标悬停在任一工具提示中,那么在页面加载之后,它可能只包含初始文本而没有我添加的内容,或者只是我添加的内容。
要查看此内容,请安装 script and then visit this typical target page。
RottenTomatoes 页面通过 XHR 加载各种内容(正如我在 Firefox Netowork Monitor 中看到的那样),
但是 3 个元素(我想修改的)立即显示,而不是在页面完全加载时显示。
我曾尝试使用 MutationObserver
来观察屏幕上出现的特定文本值,但它似乎不起作用。它的结构是这样的:
var target = selector_for_element_containing_text ; // the selector is: document.querySelector('.audience-info > div:nth-child(1)');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
modifyElements();
});
});
var config = { attributes: true, childList: true, characterData: true, subtree: true };
observer.observe(target, config);
function modifyElements(){ // This is just the current code of my script
// modify element 1
// modify element 2
// modify element 3
}
如何在元素显示后立即修改?
通过将此代码添加到脚本元区块,在
document-start
制作脚本 运行:.............. // @run-at document-start .............. // ==/UserScript==
现在,当脚本 运行s 文档中没有任何内容时,我们会将观察者附加到文档根目录,并将扫描添加的节点以查找容器元素
.audience-info
:var observer = new MutationObserver(function(mutations) { for (var i=0; i<mutations.length; i++) { var mutationAddedNodes = mutations[i].addedNodes; for (var j=0; j<mutationAddedNodes.length; j++) { var node = mutationAddedNodes[j]; if (node.classList && node.classList.contains("audience-info")) { node.firstElementChild.innerHTML = node.firstElementChild.innerHTML .replace(/[\d.]+/g, function(m) { return 2 * m }); // don't hog resources any more as we've just done what we wanted observer.disconnect(); return; } } } }); observer.observe(document, {childList: true, subtree: true});
当观察者被调用时,工具提示已经存在于文档树中,因此您可以简单地将代码从 "load" 函数移至
return
之前的观察者中,而无需更改任何内容。
N.B。最好让观察者尽可能快,特别是使用普通的 for
循环而不是函数回调,因为调用它们会产生开销,这可能会在打开一个缓慢的 PC/device 时成为一个问题非常复杂的页面,会产生数千(很常见的情况)或数十万的突变(极其罕见但仍然存在!)。并在工作完成后断开连接。
P.S。使用 setMutationHandler 函数,观察者代码将是:
// @require https://greasyfork.org/scripts/12228/code/setMutationHandler.js
// ==/UserScript==
setMutationHandler(document, '.audience-info div:first-child', function(nodes) {
this.disconnect();
nodes.forEach(function(n) {
n.innerHTML = n.innerHTML.replace(/[\d.]+/g, function(m) { return 2*m });
});
});