在greasemonkey脚本中显示元素后立即修改元素(不是在页面完全加载后)?

时间:2015-09-05 12:10:38

标签: javascript html xmlhttprequest greasemonkey

我有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 
}

如何在显示元素后立即对其进行修改?

1 个答案:

答案 0 :(得分:2)

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

    ..............
    // @run-at        document-start
    ..............
    // ==/UserScript==
    
  2. 现在,当脚本运行时,文档中没有任何内容,因此我们将观察者附加到文档根目录,并将扫描添加的节点以查找容器元素.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之前的观察者中,而无需更改任何内容。

  3. 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 });
        });
    });