Hướng dẫn javascript dom replace text

I'm trying to replace all text in between tags and I want to know the fastest way of doing so.

An example would be trying to replace all text with the arbitrary string helloWorld, so that this:

<div> <div> RandomText1 <div> RandomText2 </div> </div> </div>

Becomes this:

<div> <div> helloWorld <div> helloWorld </div> </div> </div>

My current approach would be :

  • Do Depth-first search (DFS) on DOM
  • For each element parse and determine which part is text and which part is an element.
  • For the part that is text replace it.

This to me would be really slow, especially trying to do this for a large document and having to repeat the process many times. Is there a faster way?

mplungjan

160k27 gold badges168 silver badges226 bronze badges

asked Feb 4, 2017 at 13:06

4

You don't need to parse each element to find text nodes, you can just recursively traverse childNodes property of an element

var newText = 'hello world'; function replaceTextNodes(node) { node.childNodes.forEach(function(el) { if (el.nodeType === 3) { // If this is a text node, replace the text if (el.nodeValue.trim() !== "") { // Ignore this node it it an empty text node el.nodeValue = newText; } } else { // Else recurse on this node replaceTextNodes(el); } }); } var onClick = replaceTextNodes.bind(null, document.querySelector('#container')); document.querySelector('#replace').addEventListener('click', onClick);<div id='container'> <div> RandomText1 <div> RandomText2 <ul> <li>RandomText3</li> </ul> </div> </div> </div> <button id="replace">Replace</button>

answered Feb 4, 2017 at 13:49

jetpackponyjetpackpony

1,2521 gold badge11 silver badges22 bronze badges

0

The nodeIterator is pretty fast. It has no problems with nested nodes no matter how deeply they're buried. Note: added red text that's 6 levels down. Details commented in Snippet.

SNIPPET

/* Create a custom filter which will... ||...the 3rd parameter of createNodeIterator method... */ function textFilter(node) { // if .nodeType is 3 (3 is text, 1 is element) if (node.nodeType === 3) { // Set .nodeValue to 'hellowWorld' node.nodeValue = 'helloWorld'; // Return NodeFilter object to accept node return NodeFilter.FILTER_ACCEPT; } // Otherwise ignore node return NodeFilter.FILTER_SKIP; } function findText() { // Reference the rootNode var content = document.querySelector('body'); /* Create nodeIterator passing || content or rootNode || NodeFilter object or WhatToShow property || Custom filter function */ var iterator = document.createNodeIterator(content, NodeFilter.SHOW_TEXT, textFilter); // Advance to the next sibling or descend to node's children nodes var node = iterator.nextNode(); // While there is a node... while (node) { // ...Go on to it...rinse, lather, and repeat node = iterator.nextNode(); } } findText();.mark { color: red; }<div> <div> RandomText1 <div> RandomText2 </div> </div> </div> <div> <div> <div> <div> <div> <div class='mark'> 6 Deep! </div> </div> </div> </div> </div> <div> RandomText1 <div> RandomText2 </div> </div> </div> <div> <div> RandomText1 <div> RandomText2 </div> </div> </div> <div> <div> RandomText1 <div> RandomText2 </div> </div> </div> <div> <div> RandomText1 <div> RandomText2 </div> </div> </div>

answered Feb 4, 2017 at 13:42

zer00nezer00ne

39.1k6 gold badges40 silver badges62 bronze badges

0

DOM searching done by the browser is very fast, and it optimized also. So, I would suggest to add some common class on the DOM elements which need to be changed and then manipulate them using that class identifier.

Also,

FYI, document.getElementById() works on DFS and is pretty efficient.

answered Feb 4, 2017 at 13:21

VishalVishal

5373 silver badges13 bronze badges

3

Loop over your HTML than find nodeValue like this:

document.querySelectorAll('div').forEach(function(o,i){ console.log(o.firstChild && o.firstChild.nodeValue); })

//jsfiddle.net/q7ewbswx/

answered Feb 4, 2017 at 13:45

romulealdromuleald

1,34815 silver badges29 bronze badges

Chủ đề