115

Is there a way to replace the normal text within a table element that is placed within the body of the HTML?

Like replacing "hello" with "hi"?

Please only use JavaScript without jQuery.

Web_Designer
  • 72,308
  • 93
  • 206
  • 262
Wahtever
  • 3,597
  • 10
  • 44
  • 79
  • Can you please be more specific? What do you want to replace, where is it in the body, etc. – Zirak Apr 05 '11 at 21:15
  • the body has a div and within that a table, then i would like to replace some normal text not code like replacing ("hello") with ("hi") – Wahtever Apr 05 '11 at 21:22
  • 5
    most solutions below will destroy all events and the whole dom structure if word being replaced happened to be class name, tag name or anything in html – Muhammad Umer Oct 17 '15 at 04:28
  • It looks like both question and answers are wrong. It asks how to replace words and not chars. Such as replacement of this `hello, this is a text randomTexthello` should be `hi, this is a text randomTexthello`. However, all other answers here replacing the chars instead of words. – Orhun Alp Oral Sep 18 '19 at 23:33
  • 1
    I think [Sebastian Simon's answer](https://stackoverflow.com/a/41886794/3291390) is better than the answers here. – Stack Underflow May 12 '21 at 20:46

11 Answers11

172

To replace a string in your HTML with another use the replace method on innerHTML:

document.body.innerHTML = document.body.innerHTML.replace('hello', 'hi');

Note that this will replace the first instance of hello throughout the body, including any instances in your HTML code (e.g. class names etc..), so use with caution - for better results, try restricting the scope of your replacement by targeting your code using document.getElementById or similar.

To replace all instances of the target string, use a simple regular expression with the global flag:

document.body.innerHTML = document.body.innerHTML.replace(/hello/g, 'hi');
Dexter
  • 18,213
  • 4
  • 44
  • 54
  • 1
    didnt work for me here is what i used `` – Wahtever Apr 05 '11 at 21:39
  • It can be more complicated with extended characters - what encoding is your document in? Are you sure that the character is an ü, and not ü for example..? – Dexter Apr 05 '11 at 21:44
  • just to be sure i tried it with some text in a paragraph but it didnt work – Wahtever Apr 05 '11 at 21:47
  • 2
    you didn't copy my code accurately ;-) make sure you've got innerHTML on both sides of the statement, i.e: document.body.innerHTML = document.body.innerHTML.replace('ü', 'n'); – Dexter Apr 05 '11 at 21:49
  • no im sure i did (i tried it again) i just made a mistake when writing the comment, sorry. – Wahtever Apr 05 '11 at 21:52
  • thanks for help however i don't know what to say. it still doesn't work for me sorry. here http://jsfiddle.net/kqeSB/ – Wahtever Apr 05 '11 at 22:16
  • Your example is replacing the first instance of your target string, which in this case is (I think it's a bug in jsFiddle) in the title - see http://jsfiddle.net/kqeSB/2/. If you use a simple regular expression, you can replace all instances of the target through your text (see my update above) – Dexter Apr 05 '11 at 22:27
  • never mind got it working (the function was executing before the body and all the elements with in was loaded thus not changing the words so i just added the onload event to the body tag it self ` – Wahtever Apr 05 '11 at 23:02
  • 4
    FYI - Bug in the first comment is: set `window.onload = clear;` without the parentheses "()". When you write `clear()` then you actually execute the function, but you only want to assign the function to the onload-handler – Philipp May 20 '13 at 10:20
  • 1
    Note that using innerHTML is generally considered bad these days: http://www.slideshare.net/x00mario/the-innerhtml-apocalypse – kufudo Dec 14 '14 at 23:59
  • it also replace html tag string. did not work for me – Sumeet Vishwas Nov 10 '17 at 06:31
  • Hi I’m beginner at coding. I can do some good with AppleScript. But that’s all I know. Can you please give me some advices, what to begin with, my purpose is to use javascript to automate collecting databases, images, videos, filling web forms, upload, may be to work with excel. Applescript is ok with it but java is seem to be a whole new level and much more better. What should I start with in order to achieve my purposes. I know 0 about javascript and I dont even know how to make your script above work! Where do I suppose to paste it to? Thanks you very much! – Zui Zui Jun 16 '20 at 13:45
  • How can I replace globally using template variables (`{{}}`, a loop and an array: ` links={ gh: 'https://github.com/tik9', stack: 'https://stackoverflow.com/users/1705829/timo', } for (link in links) { document.body.innerHTML = document.body.innerHTML.replace('{{ '+link + ' }}', links[link]) }` – Timo Jul 14 '20 at 10:24
  • InnerHTML stops other click functionalities. Don't try this with your code. – Surya R Praveen Mar 08 '23 at 13:05
  • This solution was very buggy for me on chrome - it seemed to refresh all of the elements in the page and even reset selected form fields!? – TV-C-1-5 Jun 07 '23 at 18:34
28

I ended up with this function to safely replace text without side effects (so far):

function replaceInText(element, pattern, replacement) {
    for (let node of element.childNodes) {
        switch (node.nodeType) {
            case Node.ELEMENT_NODE:
                replaceInText(node, pattern, replacement);
                break;
            case Node.TEXT_NODE:
                node.textContent = node.textContent.replace(pattern, replacement);
                break;
            case Node.DOCUMENT_NODE:
                replaceInText(node, pattern, replacement);
        }
    }
}

It's for cases where the 16kB of findAndReplaceDOMText are a bit too heavy.

funky-future
  • 3,716
  • 1
  • 30
  • 43
  • very elegant, is it necessary to keep two cases separate? one for ELEMENT_NODE and the other for DOCUMENT_NODE. Also, there seem to have many other [nodetypes](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType), does that mean other types don't matter? – B.Mr.W. Jan 26 '22 at 05:59
  • 1
    @B.Mr.W. i don't remember why i made the cases so explicit. for the question, theses types are sufficient. mind, that some of the types are xml-specific. – funky-future Jan 27 '22 at 15:39
  • Nice! Does `node.textContent.replace()` do a simple or a regexp-based search, and (how) can it be used on patterns that span several lines? My goal is to remove 2 buttons from a form (phpbb forum reply editor). – RJVB Dec 08 '22 at 22:43
15

The function below works perfectly for me:

// Note this *is* JQuery, see below for JS solution instead
function replaceText(selector, text, newText, flags) {
  var matcher = new RegExp(text, flags);
  $(selector).each(function () {
    var $this = $(this);
    if (!$this.children().length)
       $this.text($this.text().replace(matcher, newText));
  });
}

Here's a usage example:

function replaceAllText() {
  replaceText('*', 'hello', 'hi', 'g');
}

$(document).ready(replaceAllText);
$('html').ajaxStop(replaceAllText);

You can also use do a direct replacement like so:

document.body.innerHTML = document.body.innerHTML.replace('hello', 'hi');

But be careful with it since it may affect the tags, css and scripts as well.

EDIT: As for a pure JavaScript solution use this method instead:

function replaceText(selector, text, newText, flags) {
  var matcher = new RegExp(text, flags);
  var elems = document.querySelectorAll(selector), i;

  for (i = 0; i < elems.length; i++)
    if (!elems[i].childNodes.length)
      elems[i].innerHTML = elems[i].innerHTML.replace(matcher, newText);
}
Riccardo
  • 1,104
  • 13
  • 22
Ziad
  • 1,036
  • 2
  • 21
  • 31
15

Sometimes changing document.body.innerHTML breaks some JS scripts on page. Here is version, that only changes content of text elements:

function replaceRecursively(element, from, to) {
    if (element.childNodes.length) {
        element.childNodes.forEach(child => replaceRecursively(child, from, to));
    } else {
        const cont = element.textContent;
        if (cont) element.textContent = cont.replace(from, to);
    }
};

replaceRecursively(document.body, new RegExp("hello", "g"), "hi");
arjunsiva
  • 315
  • 2
  • 13
Oleksandr Boiko
  • 182
  • 3
  • 9
11

I had the same problem. I wrote my own function using replace on innerHTML, but it would screw up anchor links and such.

To make it work correctly I used a library to get this done.

The library has an awesome API. After including the script I called it like this:

findAndReplaceDOMText(document.body, {
  find: 'texttofind',
  replace: 'texttoreplace'
  }
);
Community
  • 1
  • 1
David Silva Smith
  • 11,498
  • 11
  • 67
  • 91
  • 1
    This was the only solution that worked for my issue. I needed to use REGEX to find and replace phone numbers across an entire site and other answers here would break my DOM events. – EmilyH Jul 23 '20 at 20:47
8

I was trying to replace a really large string and for some reason regular expressions were throwing some errors/exceptions.

So I found this alternative to regular expressions which also runs pretty fast. At least it was fast enough for me:

var search = "search string";
var replacement = "replacement string";

document.body.innerHTML = document.body.innerHTML.split(search).join(replacement)

src: How to replace all occurrences of a string in JavaScript?

Community
  • 1
  • 1
Bartho Bernsmann
  • 2,393
  • 1
  • 25
  • 34
4

While using innerHTML.replace will work and is pretty fast, this will break the DOM state.

You can replicate this by setting "autofocus" on an input field and then changing innerHTML on body, it will loose focus.

A less destructive approach is:

// retrives all childNodes of body
var childNodes = document.body.childNodes;

// start replacing
replaceInNodes(childNodes, "search", "replace");

function replaceInNodes(nodes,search,replace) {
    // iterate through all nodes
    for (var i = 0; i < nodes.length; i++) { 
        var curNode = nodes[i];
        // if the node has attributes, let us look at those
        // i.e. we want to change "John" in the input placeholder to "Peter" - <input type="text" value="John">
        if (curNode.attributes !== undefined) {
            var curNodeAttributes = curNode.attributes;
            for (var ii = 0; ii < curNodeAttributes.length; ii++) {
                // replace attribute values
                curNodeAttributes[ii].nodeValue = curNodeAttributes[ii].nodeValue.replace(search, replace);
            }   
        }
        // It is a "TEXT_NODE"
        // i.E. <span>John</span>
        if (curNode.nodeType === Node.TEXT_NODE) {
            curNode.data = this.injectIntoString(curNode.data);
        }
        // It is a "ELEMENT_NODE", meaning we need to go deeper
        if (curNode.nodeType === Node.ELEMENT_NODE) {
            this.replaceInNodes(curNode.childNodes);
        }
    }
}

More info can be found here: https://zgheb.com/i?v=blog&pl=71#12.11.2020_-_Unobstrusively_replace_text_with_JavaScript

Note: I am the author of said link

nik7
  • 806
  • 3
  • 12
  • 20
ozzi-
  • 159
  • 2
  • 12
3

Use the default javascript string replace function

var curInnerHTML = document.body.innerHTML;
curInnerHTML = curInnerHTML.replace("hello", "hi");
document.body.innerHTML = curInnerHTML;
Mark Costello
  • 4,334
  • 4
  • 23
  • 26
  • The above can be written in a single line as `document.body.innerHTML = document.body.innerHTML.replace(/hello/g, "hi");` and will replace all instances of "hello" in a case sensitive manner. – lbragile Nov 20 '20 at 03:12
1

I am new to Javascript and just started learning these skills. Please check if the below method is useful to replace the text.

<script>

    var txt=document.getElementById("demo").innerHTML;
    var pos = txt.replace(/Hello/g, "hi")
    document.getElementById("demo").innerHTML = pos;

</script>
V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
Manish
  • 29
  • 1
1

Try to apply the above suggested solution on pretty big document, replacing pretty short strings which might be present in innerHTML or even innerText, and your html design becomes broken at best

Therefore I firstly pickup only text node elements via HTML DOM nodes, like this

function textNodesUnder(node){
  var all = [];
  for (node=node.firstChild;node;node=node.nextSibling){
    if (node.nodeType==3) all.push(node);
    else all = all.concat(textNodesUnder(node));
  }
  return all;
}

textNodes=textNodesUnder(document.body)
for (i in textNodes) { textNodes[i].nodeValue = textNodes[i].nodeValue.replace(/hello/g, 'hi');    

`and followingly I applied the replacement on all of them in cycle

FantomX1
  • 1,577
  • 2
  • 15
  • 23
1

Wanted to add an example to funky-future's answer as I kept getting this error:

Uncaught TypeError: element.childNodes is not iterable

use like this:

replaceInText(document.body,"search term","replacement");

it didn't work for me with jQuery selectors.

Y Stroli
  • 339
  • 3
  • 8
  • 1
    If you have a new question, please ask it by clicking the [Ask Question](https://stackoverflow.com/questions/ask) button. Include a link to this question if it helps provide context. - [From Review](/review/low-quality-posts/24894427) – SilverNak Dec 19 '19 at 07:53
  • 1
    This is not a new question, I was expanding on funky-future's answer by providing a example that works. had to post a new answer bc I lack rep to comment on his. – Y Stroli Dec 19 '19 at 12:29