Using childnodes to change text

Viewed 468

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>
2 Answers

Use the toUpperCase() function on the nodeValue

let node = document.getElementsByClassName("list")[0].parentNode;
let numChildNodes = node.childNodes.length;
for (var i = 0; i < numChildNodes; i++) {
    node.childNodes[i].nodeValue = node.childNodes[i].nodeValue.toUpperCase();
}

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
Related