javascripthtmlnodeschild-nodes

Using childnodes to change text


I've been learning about javascript and childnodes. For an exercise, we have to switch the text of listitems to uppercase through the use of a parent node.

Right now, it seems to add the values in javascript to the list, instead of changing them. It only needs to change the original text value.

I think I'm pretty close but I get some odd results (this doesn't happen when I do it without childnodes). It's probably something minor, but I still appreciate anyone giving it a look!

javascript

addEventListener("load",init,false);

function init(){
    let span = document.getElementsByClassName("aantal");
    span[0].innerHTML = "3";

    let node = document.getElementsByClassName("list")[0].parentNode;
    node.firstChild.nodeValue = "ROOD";
    node.childNodes[1].nodeValue = "GROEN";
    node.childNodes[2].nodeValue = "BLAUW";

}

html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Slides Opdracht04</title>
    <link href="style/stijl.css" rel="stylesheet" />
    <script src="js/demo4.js"></script>
</head>
<body>
    <p>Kleuren</p>
    <ul>
        <li class="list">Rood</li>
        <li class="list">Groen</li>
        <li class="list">Blauw</li>
    </ul>
    <p>De lijst bevat <span class="aantal"></span> kleuren</p>
</body>
</html>

Solution

  • Let's examine those childNodes more closely.

    const childNodes = document.querySelector('#parent').childNodes
    
    console.log('Total', childNodes.length)
    console.log([...childNodes]
      .map(({ nodeType, textContent, nodeValue }) => ({ nodeType, textContent, nodeValue })))
    <ul id="parent">
        <li class="list">Rood</li>
        <li class="list">Groen</li>
        <li class="list">Blauw</li>
    </ul>

    As you can see from the output, #parent has 7 childNodes, not 3 as you might expect. Four are "nodeType: 3", which means they're text nodes. As you can see, they contain only whitespace. The remaining 3 are "nodeType: 1", which means they're HTML elements. These are the li children.

    When you set the nodeValues of nodes 0..2, you're actually setting them on the first 2 whitespace text nodes plus one of the lis. Setting the nodeValue of an HTML element is a no-op, so that one is ignored. Thus, you get:

    [0] WHITESPACE     => "ROOD"
    [1] <li>Rood</li>  => "GROEN" # no-op - nothing happens
    [2] WHITESPACE     => "BLAUW"
    # other elements at indexes > 2 - out of scope, nothing happens