Lex27
Lex27

Reputation: 115

Find text (child text nodes) and wrap it in a paragraph

I need a function that finds text (child text nodes) inside some (for this example the div) elements and wraps the text in a paragraph.

Text1
<div>
  <div>
    Text2
    <div>Text3</div>
  </div>
  <div>Text4</div>
  <p>Text5</p>
</div>
<div>Text6</div>
<div>
  Text7
  <p>Text8</p>
  Text9
</div>

tried did it like this:

const fn = (doc) => {
  const coll = [...doc.childNodes];
  coll.forEach(el => {
    if (el.tagName === 'DIV' && el.childElementCount === 0) {
      el.innerHTML = `<p>${el.innerHTML}</p>`;
    }
    if (el.childElementCount > 0) {
      el.childNodes.forEach(item => {
          if (item.nodeType === 3 && item.textContent.trim()) {
            const content = item.textContent.trim();
            item.innerHTML = `<p>${content}</p>`;
            console.log('2: ', item.innerHTML);
          }
        });
      fn(el);
    }
  });
}

but it works wrong - in if condition (el.childElementCount > 0) in console log, I got all needed nodes in p tags. but not in result. item.innerHTML = `<p>${content}</p>`; not apply it to document :(. Can anyone help to fix it?

result i need:

Text1
<div>
  <div>
    <p>Text2</p>
    <div><p>Text3</p></div>
  </div>
  <div><p>Text4</p></div>
  <p>Text5</p>
</div>
<div><p>Text6</p></div>
<div>
  <p>Text7</p>
  <p>Text8</p>
  <p>Text9</p>
</div>

Upvotes: 2

Views: 1094

Answers (3)

User863
User863

Reputation: 20039

You can use replaceWith() to replace the text node with the paragraph element

function filterTextNode(node) {
  var textNodes = [];
  for (node = node.firstChild; node; node = node.nextSibling) {
    if (node.nodeType == 3 && node.textContent.trim()) textNodes.push(node);
    else textNodes = textNodes.concat(filterTextNode(node));
  }
  return textNodes;
}

function wrapTextNode(text) {
  var p = document.createElement('p');
  p.innerHTML = text.textContent;
  text.replaceWith(p);
}

const fn = (doc) => {
  var textNodes = filterTextNode(doc);
  textNodes.forEach(text => {
    if (text.parentNode.tagName != 'P') {
      wrapTextNode(text);
    }
  });
}

fn(document.body)
p {
  color: red;
}
Text1
<div>
  <div>
    Text2
    <div>Text3</div>
  </div>
  <div>Text4</div>
  <p>Text5</p>
</div>
<div>Text6</div>
<div>
  Text7
  <p>Text8</p>
  Text9
</div>

References

Upvotes: 5

Mo Salah
Mo Salah

Reputation: 11

var elements = document.getElementsByTagName('div');
  for(var i=0;i<elements.length;i++){
    if(elements[i]===0){
      console.log(elements[i].textContent);
     
                       }
  else{
    var y=elements[i].innerHTML
console.log(y)
      }
  }
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>testing result</title>
</head>
<body>
  
<div>Text1</div>
<div>
<div>Text2</div>
<p>Text3</p>
</div>
<div>Text4</div>
</body>


</body>
</html>

i tryed this but i cant get last two div(4 and 2) like this output in the console <div>text4</div> and <div>text2</div> i hope this my help and i dont know how to print last two div innerHTML

Upvotes: 1

Aravindan Venkatesan
Aravindan Venkatesan

Reputation: 628

By considering the childElementCount of the div we can get your desired result. Rewrite your function like below.

const fn = (document) => {
    let elements = document.getElementsByTagName('div');
    elements = Array.prototype.slice.call(elements);
    elements.forEach(el => {
      if (el.innerHTML && el.childElementCount === 0) {
        el.innerHTML = `<p>${el.innerHTML}</p>`;
        }
    });
  }

Upvotes: 2

Related Questions