在 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 
}

如何在元素显示后立即修改?

  1. 通过将此代码添加到脚本元区块,在 document-start 制作脚本 运行:

    ..............
    // @run-at        document-start
    ..............
    // ==/UserScript==
    
  2. 现在,当脚本 运行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 });
    });
});