Trevor Trevor - 2 months ago 9
Javascript Question

Manipulate text value of jQuery nodes

I selected all nodes on an HTML page like so:

var all = $('*');


I then traverse each node, checking to see if each has an associated text value:

var newDom = all.map((i, node) => {
if ($(node).text()) {
var temp = $(node).text() + 'a';
$(node).text(temp);
}
});


I ultimately want to view the manipulated DOM in the browser. Without the above manipulation,
all.html()
yields the exact webpage that was selected, as we would expect. Meanwhile,
newDom.html()
yields the following error:

Unhandled rejection Error: getaddrinfo ENOTFOUND on.ico on.ico:80
at errnoException (dns.js:28:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:79:26)


At first glance, why might this not be working as I have it above?

Answer

There is no selector for text nodes, however you can write a recursive function to get them all as an array based on a root node. Then you can loop over the array and do stuff to the text nodes, e.g.

/* Return all text nodes that are descendents of root as an array
** @param {DOMElement} root - node to start from, defaults to document.body
** @returns {Array} array of all text nodes that are descendents of root
*/
function getTextNodes(root) {
  var root = root || document.body;
  var textNodes = [];
  // Don't process text inside these nodes
  var elementsToIgnore = {'script':true};

  if (root && root.nodeType == 1) {
    Array.prototype.forEach.call(root.childNodes || [root], function(node) {

      if (node.nodeType == 1 && node.tagName && !(node.tagName.toLowerCase() in elementsToIgnore)) {
        textNodes = textNodes.concat(getTextNodes(node));

      } else if (node.nodeType == 3){
        textNodes.push(node);
      }
    });
  } else if (root.nodeType == 3) {
    textNodes.push(root);
  }
  return textNodes;
}
 <p>Here is some text</p>
 <ol>
   <li>List item 1
   <li>List item 2
     <ol>
       <li>List item 2.1
       <li>List item 2.3
     </ol>
   <li>List item 3
  </ol>
  <textarea>Gets text in here too</textarea>
  <br>

  <button onclick="getTextNodes().forEach(function(node){node.data = node.data.replace(/s/g,'$')})">Replace all 's' with $</button>