Search code examples
javascriptreplacewindow

Is there an equivalent for string.find() in window objects?


So I know window.find(), an unstandard js object that finds a string on the page, it returns true if found and false if not. Now is there somthing similar to string.replace(), but is a window object (ex : window.replace()) that would replace all concurrent elements to soemthing else (eg replace all of the "Hi" to "Hello")?


Solution

  • I don't think there is, but it's easier to write than you might suspect. You just walk the DOM looking for Text nodes and use replace on their nodeValue:

    function replaceAll(element, regex, replacement) {
        for (var child = element.firstChild;
             child;
             child = child.nextSibling) {
            if (child.nodeType === 3) { // Text
                child.nodeValue = child.nodeValue.replace(regex, replacement);
            } else if (child.nodeType === 1) { // Element
                replaceAll(child, regex, replacement);
            }
        }
    }
    

    There I used a regular expression (which needs to have the g flag) to get the "global" behavior when doing the replace, and for flexibility.

    Live Example:

    function replaceAll(element, regex, replacement) {
        for (var child = element.firstChild;
             child;
             child = child.nextSibling) {
            if (child.nodeType === 3) { // Text
                child.nodeValue = child.nodeValue.replace(regex, replacement);
            } else if (child.nodeType === 1) { // Element
                replaceAll(child, regex, replacement);
            }
        }
    }
    
    setTimeout(function() {
        replaceAll(document.body, /one/g, "two");
    }, 800);
    <div>
      Here's one.
      <p>And here's one.</p>
      <p>And here's <strong>one</strong>
    </div>

    If you want to use a simple string instead of a regular expression, just use a regular expression escape function (such as the ones in the answers to this question and build your regex like this:

    var regex = new RegExp(yourEscapeFunction(simpleString), "g");
    

    The case this doesn't handle is where the target string crosses text nodes, like this:

    <span>ex<span>ample</span></span>

    Using the function above looking for "example", you wouldn't find it. I leave it as an exercise for the reader to handle that case if desired... :-)