我有this script。它适用于RottenTomatoes电影页面,并修改3个元素
(工具提示中有1个可见文本和2个文本)。
目前,(由于greasemonkey' @run-at document-end
)它仅在页面完全加载后才修改元素。
此外,RottenTomates页面有很多次延迟加载,最多20秒(!),
这样我的剧本就会延迟。
这会导致两件事:
要查看此内容,请安装script,然后访问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
}
如何在显示元素后立即对其进行修改?
答案 0 :(得分:2)
通过将此代码添加到脚本元区块来使脚本在document-start
运行:
..............
// @run-at document-start
..............
// ==/UserScript==
现在,当脚本运行时,文档中没有任何内容,因此我们将观察者附加到文档根目录,并将扫描添加的节点以查找容器元素.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});
当调用观察者时,文档树中已经存在工具提示,因此您只需将代码从“加载”函数移动到return
之前的观察者中,而无需更改任何内容。
N.B。最好尽可能快地使观察者,特别是通过使用普通的for
- 循环而不是函数回调,因为调用它们的开销,这可能会在打开一个非常复杂的PC /设备时成为一个问题产生数千个(非常常见的情况)或数十万个突变的页面(非常罕见但仍然!)。并在工作完成后断开连接。
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 });
});
});