Bertoncelj1
Bertoncelj1

Reputation: 436

How to iterate all the children including those without tags in an DOM element with JavaScript

I am trying to parse a ruby tag like this:

<div id="foo">
  <ruby>
      <rb>気</rb>
      <rp>(</rp>
      <rt>き</rt>
      <rp>)</rp>
  </ruby>
  が
  <ruby>
      <rb>狂</rb>
      <rp>(</rp>
      <rt>くる</rt>
      <rp>)</rp>
  </ruby>
  ってしまう。
</div>

The problem is, that I am unable to iterate all the child elements including those without tags. All the functions like: document.getElementById("foo").children and $("#foo").children() return only the two ruby tags without the text in between.

I am trying to get a list like:

Is there a way I can get a list of all the tags and text?

Upvotes: 0

Views: 106

Answers (1)

Errorname
Errorname

Reputation: 2459

You can use Node.childNodes (See documentation)

document.getElementById("foo").childNodes

But here is where it can get tricky:

In your HTML, between the <div> tag and the <ruby> tag, there is whitespaces and a newline. This will be parsed as a TextNode here. So .childNodes will return 5 nodes:

  1. A TextNode for what is between <div> and the first <ruby> (including a newline and whitespaces).
  2. The first <ruby> element.
  3. A TextNode containing the text between the two <ruby> elements (including two newlines and whitespaces)
  4. The second <ruby> element.
  5. A TextNode containing the text between the second </ ruby> and </ div>. (including a newline and whitespaces)

So, if you only need non-empty TextNode, when there is actually some text:

const nodes = [...document.getElementById('foo').childNodes].filter(node => !node.nodeValue || node.nodeValue.trim())

Upvotes: 1

Related Questions