0

I want to add html elements to the body of my page as an unordered list. I have used DocumentFragment method to create a fragment of the reply button and comment span. Now I need to add a textbox and a add reply to that ul whenever a user clicks on the reply button and add all the replies as a list next to respective comment. Here is what I've tried:

function comment() {
  var my_comment = document.getElementById('comments');
  my_comment.innerHTML = "<textarea id='user_comment'> </textarea> <button onclick='addNewItem()'>Post Comment</button>";
}
function addNewItem() {
  var thediv = document.getElementById("comments_and_replies");
  var listItem = document.createElement("ul");
  var replyBox = document.createElement("textbox");
  var commentSpan = document.createElement("span");
  var user_comment = document.getElementById('user_comment');
  var replyButton = document.createElement("button");

  listItem.className = "comments-list";
  replyButton.innerText = "Reply";
  replyButton.className = "reply";
  replyButton.addEventListener("click", function() {
    var g = document.getElementById('comments_and_replies');
    for (var i = 0, len = g.children.length; i < len; i++) {

      (function(index) {
        g.children[i].onclick = function() {
          listItem.insertBefore(replyBox, listItem.children[index]);
        }
      })(i);

    }
  })

  commentSpan.textContent = user_comment.value;

  var documentFragment = document.createDocumentFragment();
  documentFragment.appendChild(listItem);
  listItem.appendChild(commentSpan);
  listItem.appendChild(replyButton);
  thediv.appendChild(documentFragment);
}
<section><button onclick="comment()">Leave a comment</button></section>
<div id="comments"></div>
<div id="comments_and_replies"></div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • What is expected functionality? What is not working?? – mplungjan Nov 22 '21 at 13:41
  • It is expected to add a textbox in the ul when the reply button is clicked. when the user enters the reply and clicks on the button again, the reply is added next to the comment in the same ul – Mayank Sharma Nov 22 '21 at 14:15
  • also, the user can add as many replies as they want to the particular comment, so the reply button does not need to be taken out of the ul – Mayank Sharma Nov 22 '21 at 14:16

1 Answers1

0

Event delegation on a single <form> can accommodate an unlimited amount of <button>s even if they are added after the page has loaded.

The example below uses the following:

Note: Unless you are submitting data to a server, add type="button" to each <button>

Details are commented in code below

// Refernce <form>
const form = document.forms.commentsReplies;
// Any click on <form> invokes post()
form.onclick = post;

// Pass the event
function post(event) {
  /* Reference all <fieldset>
  (also <button>, <textarea>, etc) */
  const field = event.currentTarget.elements;
  // Reference the actual element clicked
  const clicked = event.target;
  // if element clicked has class postCom
  if (clicked.matches('.postCom')) {
    /* find <fieldset name="post"> and
    insert HTML into it */
    field.post.insertAdjacentHTML('beforeEnd', `<fieldset name='commentPost'><textarea></textarea><button class='comTxt' type='button'>Done</button></fieldset>`);
    // Otherwise if clicked element has class comTxt
  } else if (clicked.matches('.comTxt')) {
    /* find the clicked element's element
    that is right before it and get it's text */
    const text = clicked.previousElementSibling.value;
    /* find <fieldset name='comments'> and insert HTML */
    field.comments.insertAdjacentHTML('afterBegin', `<fieldset>${text}<button class='postRep' type='button'>Reply</button><ul></ul></fieldset>`);
    // Remove <fieldset name='commentPost'>
    field.commentPost.remove();
  } else if (clicked.matches('.postRep')) {
    clicked.insertAdjacentHTML('afterEnd', `<ul><textarea></textarea><button class='repTxt' type='button'>Done</button></ul>`);
  } else if (clicked.matches('.repTxt')) {
    const text = clicked.previousElementSibling.value;
    const list = clicked.parentElement;
    list.insertAdjacentHTML('afterBegin', `<li>${text}<button class='postRep' type='button'>Reply</button></li>`);
    clicked.previousElementSibling.remove();
    clicked.remove();
  } else {
    return false;
  }
}
button {
  display: block;
  margin-left: 25%;
}
<form id='commentsReplies'>
  <fieldset name='post'><button class='postCom' type='button'>Leave a comment</button>
  </fieldset>
  <fieldset name="comments">
    <legend>Comments</legend>
  </fieldset>
</form>
zer00ne
  • 41,936
  • 6
  • 41
  • 68