2

Following that discussion, I'd like to understand how to use TreeWalker to change text on textNodes filtered by class names.

I'd like to replace all numbers with "x" on <p class="french"> only.

There's a piece of solution here, but the final jQuery is not practical for me. I'd like to understand why my following solution doesn't work.

myfilter = function(node){
  if (node.className=="french")
  return NodeFilter.FILTER_ACCEPT
  else
  return NodeFilter.FILTER_SKIP;
}

var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, myfilter, false);

 while (walker.nextNode()) {
    walker.currentNode.nodeValue.replace(/(\d)/gu, 'x');   
 }
<body>
<p>890008900089000</p>
<p class="french">890008900089000</p>
</body>
Community
  • 1
  • 1
DimNC
  • 130
  • 10
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace – Robert Mar 26 '17 at 01:10
  • Thanks @Robert, but that solution seems to keep the original string unchanged. And I don't know how to apply this to a certain class. – DimNC Mar 26 '17 at 01:34
  • Use assignment operator on `nodeValue` because strings are immutable. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Assignment – Robert Mar 26 '17 at 02:05
  • Also use `node.parentNode.className` instead of `node.className` because `node` is the actual text node, not the paragraph. – Robert Mar 26 '17 at 02:15

1 Answers1

3

Your code

  • walks over all text nodes (NodeFilter.SHOW_TEXT)
  • where className=="french" and
  • replaces each digit in their value with "x"

There are several problems.

  1. Text nodes have no class. You have to test their parent nodes class.
  2. Strings are immutable and you don't use the result of the replacement.
  3. You actually want to replace all numbers with "x", not all digits. (?)

So change node.className to node.parentNode.className, \d to \d+, and assign the result of String#replace back to walker.currentNode.nodeValue:

myfilter = function(node){
  if (node.parentNode.className=="french")
  return NodeFilter.FILTER_ACCEPT
  else
  return NodeFilter.FILTER_SKIP;
}

var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, myfilter, false);

 while (walker.nextNode()) {
    walker.currentNode.nodeValue = walker.currentNode.nodeValue.replace(/\d+/g, 'x');   
 }
Robert
  • 2,603
  • 26
  • 25
  • 1. That's the problem, I get it. So the text is considered as child of the html tag it's inside. 2. Ok! 3. Actually, I want to replace the space after the numbers by non-breaking spaces, for page layout purposes. But I wrote "x" to simplify my question. I have another regex to replace spaces before punctuation too. Your solution works perfectly. Thanks a lot @Robert ! – DimNC Mar 26 '17 at 02:44
  • Yes, DOM elements like a paragraph can contain a mix of texts, elements, etc. `NodeFilter.SHOW_TEXT` only returns the actual text nodes. – Robert Mar 26 '17 at 02:59