Creating a packing list using Javascript, DOM, and the replaceChild() method



I am making a packing list for my assignment and we choose any place and any 3 items to bring. What is supposed to happen is the user presses the 1, 2, or 3 buttons and a prompt will appear telling the user what they want to swap the chosen item with. Then, once they hit OK, the new item will appear in the list. So, if they press 1 and type an item, the new item will be in the 1. The same should happen if the user wanted to swap the item in 2 or the item in 3. However, the problem I am having is that it does not show the new item. It allows me to press 1, 2, or 3 and then type what I want to swap whichever item with, but then adds to the list with a 4 appearing at the end of the list. To swap the items, the assignment says to use the replaceChild() method. Did I put in something wrong in the coding or forget something? Help is appreciated.

<!DOCTYPE html>

<html lang="en">
<head>
    <title>CIS 223 Chapter 10 Program</title>
    <meta charset="utf-8">
    <script>        
    var list;
        function createDOM()
        {
            list = document.getElementById("items");

            var newElement = document.createElement("LI");
            var nodeText = document.createTextNode("Sunscreen");
            newElement.appendChild(nodeText);
            list.appendChild(newElement);

            var newElement = document.createElement("LI");
            var nodeText = document.createTextNode("Water");
            newElement.appendChild(nodeText);
            list.appendChild(newElement);

            var newElement = document.createElement("LI");
            var nodeText = document.createTextNode("Swim suits");
            newElement.appendChild(nodeText);
            list.appendChild(newElement);       
        }

        //Swap items function.
        function registerKey(keyEvent)
        {
            var keyValue = keyEvent.key;        
            if (keyValue < "1" || keyValue > "3")
            {   
                alert("Only press 1, 2, or 3");
                return;
            }
        
            var userInput;
            var newInput;
            var newElement = document.createElement("LI");

            //Prompt user for new entry.
            userInput = prompt("Enter a new item for slot "+keyValue,"");
        

            //Check input for valid entry.
            if (userInput != null && userInput != "")
            {   
                //Write Your code to Pass string input to Text Node.
                //     .......
                newInput = document.createTextNode("");
                //Write Your code to Attach Text Node to Element.
                //     .......
                newElement.appendChild(newInput);
                list.appendChild(newElement);
                var whichNode = parseInt(keyValue);  // which item to be replaced
                //Write Your code to Replace existing node with new node.
                //     .......
                nodeText.replaceChild(newInput,nodeText.childnodes[LI]);
            }
        }
    </script>   
</head>

<body onload=createDOM() onkeypress=registerKey(event)>
    <div id="wrapper">

        <header>
            <h1>Summer Vacation</h1>
        </header>

        <main>
            <h2>We're going to Cancun, Mexico!</h2>
            <p>Let's pack a few <em>essentials</em> for the trip.</p>
            <ol id="items">

            </ol>
    
            <p>These provisions were carefully selected for this trip.<br><br>
            However, you can swap out any of the three items by pressing:<br>
            <strong>1</strong>, <strong>2</strong>, or <strong>3</strong> on your keyboard.</p>
            
        </main>
    </div>
</body>
</html>

Answer

As this is an assignment, I won’t give you the fixed code, but here are the main issue that need to be fixed:

  • You need to create the text node using the input that the user entered. Currently newInput = document.createTextNode(""); creates a text node with an empty string "". You need to pass your user’s input into this.

  • nodeText doesn’t exist inside of your registerKey function. The variable defined within a function body {} only exist within that function body (scope). So anywhere you’re trying to access nodeText inside of your registerKey function you’ll get an error – you can read more about scope here.

  • You don’t need to use list.appendChild(newElement);. This appends/adds your new item to your list at the end of the list. This isn’t the behavior you want. Instead, your script will add the item to your list using .replaceChild(). So you can remove this line.

  • nodeText.replaceChild(newInput,nodeText.childnodes[LI]); isn’t correct either. The idea of .replaceChild() is to pass in the new element you want to replace the old element with. The use case is as so:

    parentNode.replaceChild(newChild, oldChild);
    

    In your case the new element is newElement, which is the <li> element you’ve created containing the user’s input value, and not the text node newInput. Again, here nodeText doesn’t exist, so you need to use list instead of nodeText as that is the (parent) element that contains your list items/<li> elements as children.

  • nodeText.childnodes[LI] is also going to give you issues. As established above, nodeText needs to be list. Moreover, childnodes needs to be changed to childNodes. This will give you a NodeList of child items in your list, which is similar to an array. Recall that the item you need to pass as the second argument to replaceChild() needs to be the item you want to replace/remove from your list, so this item needs to be obtained from the node list using the whichNode number. You can take a look at NodeList.item() to help you achieve this. Note that you have created your HTML element with a space:

    <ol id="items">
    
    </ol>
    

    meaning that using .childNodes on your empty <ol> will give you an element at index 0 of the NodeList. I suggest you remove this blank space and use <ol id="items"></ol> instead:

var items = document.getElementById("items1");
console.log(items.childNodes); // empty NodeList

var items = document.getElementById("items2");
console.log(items.childNodes); // NodeList with 1 item (undesirable)
<ol id="items1"></ol>
<ol id="items2">

</ol>


Source: stackoverflow