【问题标题】:Modify elements immediately after they are displayed (not after page completely loads) in greasemonkey script?在greasemonkey脚本中显示后立即修改元素(而不是在页面完全加载后)?
【发布时间】:2016-09-05 20:40:34
【问题描述】:

我有this script。它适用于RottenTomatoes电影页面,并修改了3个元素
(工具提示内有 1 个可见文本和 2 个文本)。

目前,(由于greasemonkey 的@run-at document-end)它仅在页面完全加载后修改元素。

此外,RottenTomates 页面有很多次延迟加载,最多 20 秒(!),
所以这对我的脚本造成了额外的延迟。

这会导致两件事:

  • 显示修改后的可见文本的延迟,以及,
  • 如果您在页面完全加载之前将鼠标悬停在任一工具提示中,那么在加载之后,它可能只包含初始文本而没有我的添加,或者仅包含我的添加。

要查看此内容,请安装 script,然后访问 this typical target page。


RottenTomatoes 页面通过 XHR 加载各种内容(正如我在 Firefox Network 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 
}

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

【问题讨论】:

    标签: javascript html xmlhttprequest greasemonkey


    【解决方案1】:
    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 之前的观察者中,而无需更改任何内容。

    注意最好让观察者尽可能快,特别是通过使用普通的for-loops 而不是函数回调,因为调用它们的开销很大,当打开一个非常复杂的页面时,这可能会成为慢速 PC/设备上的问题产生数千个(相当常见的情况)或数十万个突变(极其罕见但仍然存在!)。工作完成后断开连接。

    附:使用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 });
        });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 2015-05-13
      • 2022-11-21
      相关资源
      最近更新 更多