简体   繁体   中英

Wrap a tag around multiple instances of a string using Javascript

I'm trying to wrap multiple instances of a string found in html around a tag (span or abbr) using pure JS. I have found a way to do it by using the code:

function wrapString() {
    document.body.innerHTML = document.body.innerHTML.replace(/string/g, ‘<tag>string</tag>');
};

but using this code messes with a link's href or an input's value so I want to exclude certain tags (A, INPUT, TEXTAREA etc.).

I have tried this:

function wrapString() {
    var allElements = document.getElementsByTagName('*');
    for (var i=0;i<allElements.length;i++){
        if (allElements[i].tagName != "SCRIPT" && allElements[i].tagName != "A" && allElements[i].tagName != "INPUT" && allElements[i].tagName != "TEXTAREA") {
            allElements[i].innerHTML = allElements[i].innerHTML.replace(/string/g, ‘<span>string</span>');
        }
    }
}

but it didn't work as it gets ALL the elements containing my string (HTML, BODY, parent DIV etc.), plus it kept crushing my browser. I even tried with JQuery's ":containing" Selector but I face the same problem as I do not know what the string's container is beforehand to add it to the selector.

I want to use pure JavaScript to do that as I was planning on using it as a bookmark for quick access to any site but I welcome all answers regarding JQuery and other frameworks as well.

PS If something like that has already been answered I couldn't find it...

This is a quite complicated problem actually (you can read this detailed blog post about it).
You need to:

  1. recurse on the dom tree
  2. find all text nodes
  3. do your replace on its data
  4. make the modified data into dom nodes
  5. insert the dom nodes to the tree, before the original text node
  6. remove the original text node

Here is a demo fiddle .
And if you still need tagName based exclusions, look at this fiddle

The code:

function wrapInElement(element, replaceFrom, replaceTo) {
    var index, textData, wrapData, tempDiv;
    // recursion for the child nodes
    if (element.childNodes.length > 0) {            
        for (index = 0; index < element.childNodes.length; index++) {
            wrapInElement(element.childNodes[index], replaceFrom, replaceTo);
        }
    }
    // non empty text node?
    if (element.nodeType == Node.TEXT_NODE && /\S/.test(element.data)) {
        // replace
        textData = element.data;
        wrapData = textData.replace(replaceFrom, replaceTo);
        if (wrapData !== textData) {
            // create a div            
            tempDiv = document.createElement('div'); 
            tempDiv.innerHTML = wrapData;
            // insert
            while (tempDiv.firstChild) {
                element.parentNode.insertBefore(tempDiv.firstChild, element);
            }
            // remove text node
            element.parentNode.removeChild(element);
        }
    }
}

function wrapthis() {
    var body = document.getElementsByTagName('body')[0];
    wrapInElement(body, "this", "<span class='wrap'>this</span>");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM