javascripthtmlcssappendchildcreateelement

How to append something to a created element?


So I am working on a program that allows you to add books to a list and then write reviews for them. The reviews are supposed to be appended just underneath the list item that it belongs to, but I'm not sure how to do it. All I know is that I've been using appendChild(). I've tried searching online as well, but I wasn't really able to find a good answer. The main issue I'm having trouble with is that the list items are created elements that I didn't make specific identifiers for. So I'm not sure how to get around that.

In the code, I've tried using document.body.appendChild(comment) and document.h3.appendChild(comment). I've also attempted using function parameters, but I'm not very experienced in that field, so I didn't get any results with that either. Essentially, I'm just not sure what syntax to use here.

Here is my full code:

// listens for a click on the "add new" button
document.getElementById("new").addEventListener("click", newBook);
let newdiv = document.getElementById("newdiv");

// takes information about a new list item
function newBook() {
  // reveals the input boxes needed
  newdiv.style.display = "inline-block";
}

// listens for a click on the "add" button
document.getElementById("enternew").addEventListener("click", addItem);

// creates a new list item and adds it to the body of the webpage
function addItem() {
  // defines the new element as an h2 element
  let item = document.createElement("h2");
  item.setAttribute("class", "listItem");

  // gets the variable values from the user's input
  let bookname = document.getElementById("book").value;
  let authorname = document.getElementById("author").value;
  let seriesname = document.getElementById("series").value;

  // converts the user's input into text nodes
  let b = document.createTextNode('"' + bookname + '"');
  let a = document.createTextNode(", by " + authorname);
  let s = document.createTextNode(" (" + seriesname + ")");

  // creates buttons to initiate the review process and remove the list item
  let review = document.createElement("button");
  let remove = document.createElement("button");

  // creates a text node for the review button and appends it to the button element
  let rv = document.createTextNode("REVIEW");
  review.appendChild(rv);

  // creates a text node for the remove button and appends it to the button element
  let rm = document.createTextNode("✖");
  remove.appendChild(rm);
  
  // appends the text nodes to the h2 element
  item.appendChild(b);
  item.appendChild(a);
  item.appendChild(s);

  // appends the buttons to the h2 element
  item.appendChild(review);
  item.appendChild(remove);
  
  // adds the h2 element, including all the text nodes, to the body of the webpage
  document.body.appendChild(item);

  document.getElementById("book").value = "";
  document.getElementById("author").value = "";
  document.getElementById("series").value = "No series";

  // removes the list item when the "x" button is clicked
  remove.onclick = function() {
    document.body.removeChild(item);
  }

  // asks the user for review input and appends it to the list item
  review.onclick = function() {
    // gets input from the user for a star rating and their written review of the book
    let stars = prompt("Rate this book out from 1 to 5 (insert numerical values only):");
    let reviewText = prompt("Write a short review for this book:");

    // creates an h3 element to contain the review
    let comment = document.createElement("h3");

    // creates a text node to include in the h3
    let commentText = document.createTextNode("Stars: " + stars + "  " + reviewText);

    // appends the text node to the h3
    comment.appendChild(commentText);

    // appends the h3 to the list item
    //document.h3.appendChild(comment);
  }
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Reading List</title>
  <link href="style.css" rel="stylesheet" type="text/css" />
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Cutive Mono">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=EB Garamond">
</head>

<body>
  <center>
    <!-- page header -->
    <h1 class = "header">~ YOUR READING LIST ~</h1>
    <br/> <br/>
    <!-- add new section for new book entry -->
    <button class = "df" id = "new">ADD NEW +</button>
    <br/>

    <!-- hidden division that contains input fields to add a new entry -->
    <div id = "newdiv">
      <p>Book name:</p>
      <input id = "book"/>
      <br/>
      <p>Author name:</p>
      <input id = "author"/>
      <br/> 
      <p>Series name (optional):</p>
      <input id = "series" value = "No series"/>
      <br/> <br/>
      <button class = "df" id = "enternew">ADD</button>
    </div>
  </center>
  
  <script src="script.js"></script>
  <!-- <script src="https://replit.com/public/js/replit-badge-v2.js" theme="teal" position="bottom-right"></script> -->
</body>

</html>

The section of issue is the review.onclick = function() { section.

I really appreciate any help that I get on this. Thank you and have a great day!


Solution

  • You need insertBefore at the end of review like:

    // listens for a click on the "add new" button
    document.getElementById("new").addEventListener("click", newBook);
    let newdiv = document.getElementById("newdiv");
    
    // takes information about a new list item
    function newBook() {
      // reveals the input boxes needed
      newdiv.style.display = "inline-block";
    }
    
    // listens for a click on the "add" button
    document.getElementById("enternew").addEventListener("click", addItem);
    
    // creates a new list item and adds it to the body of the webpage
    function addItem() {
      // defines the new element as an h2 element
      let item = document.createElement("h2");
      item.setAttribute("class", "listItem");
    
      // gets the variable values from the user's input
      let bookname = document.getElementById("book").value;
      let authorname = document.getElementById("author").value;
      let seriesname = document.getElementById("series").value;
    
      // converts the user's input into text nodes
      let b = document.createTextNode('"' + bookname + '"');
      let a = document.createTextNode(", by " + authorname);
      let s = document.createTextNode(" (" + seriesname + ")");
    
      // creates buttons to initiate the review process and remove the list item
      let review = document.createElement("button");
      let remove = document.createElement("button");
    
      // creates a text node for the review button and appends it to the button element
      let rv = document.createTextNode("REVIEW");
      review.appendChild(rv);
    
      // creates a text node for the remove button and appends it to the button element
      let rm = document.createTextNode("✖");
      remove.appendChild(rm);
    
      // appends the text nodes to the h2 element
      item.appendChild(b);
      item.appendChild(a);
      item.appendChild(s);
    
      // appends the buttons to the h2 element
      item.appendChild(review);
      item.appendChild(remove);
    
      // adds the h2 element, including all the text nodes, to the body of the webpage
      document.body.appendChild(item);
    
      document.getElementById("book").value = "";
      document.getElementById("author").value = "";
      document.getElementById("series").value = "No series";
    
      // removes the list item when the "x" button is clicked
      remove.onclick = function() {
        document.body.removeChild(item);
      }
    
      // asks the user for review input and appends it to the list item
      review.onclick = function() {
        // gets input from the user for a star rating and their written review of the book
        let stars = prompt("Rate this book out from 1 to 5 (insert numerical values only):");
        let reviewText = prompt("Write a short review for this book:");
    
        // creates an h3 element to contain the review
        let comment = document.createElement("h3");
    
        // creates a text node to include in the h3
        let commentText = document.createTextNode("Stars: " + stars + "  " + reviewText);
    
        // appends the text node to the h3
        comment.appendChild(commentText);
        item.parentNode.insertBefore(comment, item.nextSibling);
    
        // appends the h3 to the list item
        //document.h3.appendChild(comment);
      }
    }
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Cutive Mono">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=EB Garamond">
    <center>
      <!-- page header -->
      <h1 class="header">~ YOUR READING LIST ~</h1>
      <br/> <br/>
      <!-- add new section for new book entry -->
      <button class="df" id="new">ADD NEW +</button>
      <br/>
    
      <!-- hidden division that contains input fields to add a new entry -->
      <div id="newdiv">
        <p>Book name:</p>
        <input id="book" />
        <br/>
        <p>Author name:</p>
        <input id="author" />
        <br/>
        <p>Series name (optional):</p>
        <input id="series" value="No series" />
        <br/> <br/>
        <button class="df" id="enternew">ADD</button>
      </div>
    </center>

    Instead of prompt i suggest you to use dialog, with dialog you can create a input type "number" with "min/max" like you need.