JS replace only text without html tags and codes

2019-08-22 01:17发布

问题:

I want to replace some words of the document without changing any html tags or js codes.

Basically what I do is;

document.body.innerHTML = document.body.innerHTML.replace('lorem','new lorem');

But this code will replace any 'lorem'. I want to avoid tags like; <script... var lorem = 123; <div class="lorem", <a id="lorem" etc.

How can I do this in JS?

回答1:

Walk the DOM, and .replace() the values of text nodes.

function walk(el, fn) {
    for (var i = 0, len = el.childNodes.length; i < len; i++) {
        var node = el.childNodes[i];
        if (node.nodeType === 3)
            fn(node);
        else if (node.nodeType === 1 && node.nodeName !== "SCRIPT")
            walk(node, fn);
    }
}

walk(document.body, function(node) {
    var text = node.data.split("foo"),
        parent = node.parentNode,
        i = 1,
        newNode;

    parent.insertBefore(textNode(text[0]), node);

    for (; i < text.length; i += 2) {
        (newNode = document.createElement("b"))
                           .appendChild(textNode("bar"));
        parent.insertBefore(newNode, node);
        parent.insertBefore(textNode(text[i]), node);
    }
    parent.removeChild(node);
});

function textNode(txt) {
    return document.createTextNode(txt);
}


回答2:

Another way of doing this is using regular expressions, science you can't insert HTML tags to a text node.

First I am using a regular expressions to catch parts of the body.innerHTML property that are outside of the HTML tags.

But, the string contains also another data, and if I will directly replace it with thge new data some text will be lost.

Insted, I get each match as an argument for a function, and inside this function I use another regular expression.

Notice that you have to replace "foo" twice.

The code:

document.body.innerHTML=document.body.innerHTML.replace(/<[^(script)][^>]*>[^<]*(foo)[^<]*</g,function(match){ return match.replace(/foo/,"newWord"); });