如何等待页面在运行脚本之前完成加载所有内容或如何最好地检测主要DOM更改 [英] How to wait for page to finish loading all content before running script or how to best detect major DOM changes

查看:118
本文介绍了如何等待页面在运行脚本之前完成加载所有内容或如何最好地检测主要DOM更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 here 作为取代文本的基础。



以下是一段重要的代码

  var elements = document.getElementsByTagName('*'); 

for(var i = 0; i< elements.length; i ++){
var element = elements [i]; (var j = 0; j var node = element.childNodes [j];

;

if(node.nodeType === 3){
var text = node.nodeValue;
var replacedText = text.replace(/ [在这里替换的词或短语] / gi,'[new word or phrase]');

if(replacedText!== text){
element.replaceChild(document.createTextNode(replacedText),node);






$ b现在这在99%的情况下工作正常,但在某些计算机上(我假设根据计算机的速度以及它缓存的内容),此代码在某些网站上无效,最重要的是在谷歌搜索上。脚本肯定会运行,但是它找不到任何要替换的内容。我最好的猜测是,它在加载并运行脚本,然后将所有数据从谷歌添加到DOM中。



我有两个问题



1)有没有什么方法可以检测到google在运行脚本之前完成了需要做的事情?或者这是固有的不可能的,因为(我认为)有一些异步的事情发生。 2)如果我无法检测到它已完全加载完成,那么检测文本或图像元素是否已添加到DOM中的最佳方法是(或编辑在DOM上),以便我可以重新运行替换文本的函数?



感谢您的帮助。

REPLACE 函数......











$ b

 函数REPLACE(text){
console.log(text);
//在这里更改文本
返回文本;首先,你应该使用
$ / code>

/developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalkerrel =nofollow> TreeWalker 来遍历DOM更多

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ .NodeFilter.SHOW_TEXT,null,false);

var node; ((node = walker.nextNode())){
node.textContent = REPLACE(node.textContent);
while


对于动态DOM,最好的办法是使用< a href =https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver =nofollow> MutationObserver API。

 函数initMO(root){
var MO = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MO(function(mutations){
observer.disconnect();
mutations.forEach(function(mutation){
var node = mutation.target;
if(node.nodeType === document.ELEMENT_NODE)
walk(node);
else
node.textContent = REPLACE(node.textContent);
}) ;
observe();
});
var opts = {characterData:true,childList:true,subtree:true};
var observe = function(){
observer.takeRecords();
observer.observe(root,opts);
};
observe();
}

请记住,在调用观察者之前可能会收集多个突变记录,一些更改可能不再在活动DOM上了。这是因为MutationObserver应该(浏览器在某些角落案例中是错误的 )只有在当前堆栈/任务的所有代码完成后才会触发为微任务。



在进行可能触发更多记录的更改之前,请小心断开观察者,否则将挂起浏览器/系统。



完成解决方案:

  document.addEventListener('DOMContentLoaded',function ){
//假设您的代码在DOMContentLoaded
之前运行//可能需要检查document.readyState
//或者使用jQuery的ready()代替
walk(document.documentElement );
initMO(document.documentElement);
});

打开小提琴看到它在行动。



注意: Firefox中存在不一致的情况,其中childList更改仅针对textContent-only更改触发,因此请记住。



您可以方便地找到 MutationSummary 库。查看宣传视频


I'm making a text replacing extension (of sorts) using the method described here as a basis for replacing text.

Here is the important piece of code

var elements = document.getElementsByTagName('*');

for (var i = 0; i < elements.length; i++) {
    var element = elements[i];

    for (var j = 0; j < element.childNodes.length; j++) {
        var node = element.childNodes[j];

        if (node.nodeType === 3) {
            var text = node.nodeValue;
            var replacedText = text.replace(/[word or phrase to replace here]/gi, '[new word or phrase]');

            if (replacedText !== text) {
                element.replaceChild(document.createTextNode(replacedText), node);
            }
        }
    }
}

Now this works fine in 99% of cases, but on some computers (I'm assuming based on the speed of the computer and what it has cached) this code will not work on certain websites, most importantly on google searches. The script definitely runs, but it doesn't find anything to replace. My best guess is that it is loading and running the script before it finishes loading and adding all the data from google onto the DOM.

I have two questions

1) Is there any way to detect that google has finished doing what it needs to do before running the script? Or is this inherently impossible because (I assume) there is some asynchronous stuff happening.

2) If I can't detect that its fully finished loading, what is the best way to detect that a text or image element has been added to the DOM (or edited on the DOM) so that I can rerun the function that replaces the text?

Thanks in advance for the help.

解决方案

Suppose you have a REPLACE function defined...

function REPLACE(text) {
    console.log(text);
    // change text here
    return text;
}

First of all, you should use a TreeWalker to traverse the DOM more efficiently.

function walk(root) {
    var walker = document.createTreeWalker(root, 
        window.NodeFilter.SHOW_TEXT, null, false);

    var node;
    while ((node = walker.nextNode())) {
        node.textContent = REPLACE(node.textContent);
    }
}

For dynamic DOM your best bet is to use the MutationObserver API.

function initMO(root) {
    var MO = window.MutationObserver || window.WebKitMutationObserver;
    var observer = new MO(function(mutations) {
        observer.disconnect();
        mutations.forEach(function(mutation){
            var node = mutation.target;
            if (node.nodeType === document.ELEMENT_NODE)
                walk(node);
            else
                node.textContent = REPLACE(node.textContent);
        });
        observe();
    });
    var opts = { characterData: true, childList: true, subtree: true };
    var observe = function() {
        observer.takeRecords();
        observer.observe(root, opts);
    };
    observe();
}

Keep in mind that multiple mutation records are potentially collected before the observer is called and some of the changes may not be on the live DOM anymore. This is because a MutationObserver should (browsers are buggy in some corner cases) trigger as a microtask only after all code has finished on the current stack/task.

Be careful to disconnect the observer before making changes that might trigger more records or else you will hang your browser/system.

To complete the solution:

document.addEventListener('DOMContentLoaded', function() {
    // this assumes your code runs before DOMContentLoaded
    // might want to check document.readyState
    // or use jQuery's ready() instead
    walk(document.documentElement);
    initMO(document.documentElement);
});

Open this fiddle to see it in action.

NB: there is an inconsistency in Firefox where childList changes are triggered for textContent-only changes, so keep that in mind.

You might find the MutationSummary library handy. See the promotional video

这篇关于如何等待页面在运行脚本之前完成加载所有内容或如何最好地检测主要DOM更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆