How to Search and Change Text with Javascript

Last updated 27 July 2016

Replacing text in javascript is easy, just use replace (i.e. 'wat'.replace('a', 'ha'); //=> 'what'). Sometimes, though, you want to do a search and replace on text in a whole html document that includes html tags and things that aren’t just text. I had to do that recently and found it wasn’t as obvious as I first thought.

Let’s say I wanted to replace all occurrences of hats with rats. Simple enough.

My first thought was to do something like this:

function hatsToRats() {
  var html = document.innerHTML;
  var newHtml = html.replace(/hats/, 'rats');
  document.innerHTML = newHtml;

This has a few problems. First, it changes all occurrences of hats to rats, even those inside html tag properties to <a href="">hats</a> becomes <a href="">rats</a>. Ideally, I would want <a href="">rats</a> so the link isn’t broken. The other problem is that if there were any javascript events bound to elements on the page, I’ve just replaced all the elements so those events will no longer be bound. I wanted this function to be independent of any other javascript so it shouldn’t know about what events it might need to rebind after running.

I wasn’t sure what to do so I did a little searching and came across Phrogz’s stackoverflow answer to a related question that explained document.createTreeWalker as a solution. This gives us access to each text node in the document like so:

function hatsToRats() {
  var html = document.querySelector('html');
  var walker = document.createTreeWalker(html, NodeFilter.SHOW_TEXT);
  var node;
  while (node = walker.nextNode()) {
    node.nodeValue = node.nodeValue.replace(/hats/, 'rats')

What this does is finds all text nodes inside the html tag on the document and replaces its value with the newly hats/rats-swapped text. This won’t affect binding on any element on the page (even if you crazily have an event bound to a text node) and leaves tag attributes (like the aforementioned href) alone.

Hopefully this article saves you some time if you ever need to do some html find and replacing!