nyhunter77
nyhunter77

Reputation: 674

Adding node before sibling in Javascript

so I'm learning about manipulating Dom elements and adding nodes.

I use this js code:

var parent = document.getElementById('div2');
var newNode = document.createElement('p');
var text = document.createTextNode('Text Node!');
newNode.appendChild(text);
parent.insertBefore(newNode, parent.childNodes[4]);

This is my html within the usual vanilla setup:

<div id="div2">    
    <p> abc </p>
    <p> cde </p>
    <p> efg </p>
    <p> ghi </p>    
</div>

The output is this:

abc
cde
Text Node!
efg
ghi

Isn't this the wrong spot? Isn't this insertBefore childNode[2] before it's inserted? For some reason, when I change the number after childNode, the text is not showing up where I expect it to be? Why is that? Aren't the nodes still starting at 0 ... like arrays? Another example, using childNode[6] places it after efg. I thought that should have been insertBefore childNode[3].

I know the question's probably basic but I can't figure out why. thanks!

Upvotes: 0

Views: 465

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075895

childNodes includes Text nodes (and comment nodes and such, but you don't have any of those). In your HTML, the whitespace between the elements are Text nodes, so div2 has:

  • Index 0: A Text node with a newline and some spaces or tabs
  • Index 1: An Element node for the first paragraph (which contains a Text node with " abc ")
  • Index 2: A Text node with a newline and some spaces or tabs
  • Index 3: An Element node for the second paragraph (which contains a Text node with " cde ")
  • Index 4: A Text node with a newline and some spaces or tabs
  • Index 5: An Element node for the third paragraph (which contains a Text node with " efg ")
  • Index 6: A Text node with a newline and some spaces or tabs
  • Index 7: An Element node for the fourth paragraph (which contains a Text node with " ghi ")
  • Index 8: A Text node with a newline and some spaces or tabs

Live Example:

var div2 = document.getElementById("div2");
var index, child;
snippet.log("div2's child node types:");
for (index = 0; index < div2.childNodes.length; ++index) {
  child = div2.childNodes[index];
  snippet.log(index + ": " + nodeTypeName(child.nodeType));
}

// Type values from http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-111237558
function nodeTypeName(type) {
  switch (type) {
    case 1:  return "ELEMENT_NODE";
    case 2:  return "ATTRIBUTE_NODE";
    case 3:  return "TEXT_NODE";
    case 4:  return "CDATA_SECTION_NODE";
    case 5:  return "ENTITY_REFERENCE_NODE";
    case 6:  return "ENTITY_NODE";
    case 7:  return "PROCESSING_INSTRUCTION_NODE";
    case 8:  return "COMMENT_NODE";
    case 9:  return "DOCUMENT_NODE";
    case 10: return "DOCUMENT_TYPE_NODE";
    case 11: return "DOCUMENT_FRAGMENT_NODE";
    case 12: return "NOTATION_NODE";
    default:
      return "Unknown node type";
  }
}
<div id="div2">    
    <p> abc </p>
    <p> cde </p>
    <p> efg </p>
    <p> ghi </p>    
</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

On modern browsers, you can use children instead, which only includes elements, not other kinds of nodes.

Upvotes: 1

Related Questions