Создание раздела комментариев

Рейтинг: 0Ответов: 1Опубликовано: 03.02.2023

К элементу (комментарий), который создается из данных, введенных в input, добавляется счетчик рейтинга в формате кнопка "минус" - счетчик - кнопка "плюс", на которые можно нажать только один раз либо кнопка минус либо кнопка плюс - с шагом 1.

Как сделать эти кнопки и счетчик рейтинга уникальными для каждого комментария?

Ответы

▲ 0

Вот вам каркас

Это ещё совсем малая часть того, что стоит написать для нормалных комментариев, но как бы… все начинается с основ.

class CommentData {
  /**
   * @param {String} text 
   * @param {String} user 
   */
  constructor(text, user) {
    this.text = text;
    this.user = user;
  }
  /** @type {String} */
  text;
  /** @type {String} */
  user;
  /** @type {Map<String, (`up` | `down`)>} */
  votes = new Map();
  /** @readonly */
  get up() {
    return Array.from(this.votes).filter(([user, type]) => type == `up`).map(([user]) => user);
  }
  /** @readonly */
  get down() {
    return Array.from(this.votes).filter(([user, type]) => type == `down`).map(([user]) => user);
  }
}

/** @type {Array<CommentData>} */
const comments = [];
const userIdentifier = `--user identifier--`;

const templateCommentContainer = ( /** @type {HTMLTemplateElement} */ (document.querySelector(`template#comment-container`)));
const container = templateCommentContainer.parentElement;
if (!container) {
  throw new ReferenceError(`Element 'container' isn't defined.`);
}

const formCommentForm = ( /** @type {HTMLFormElement} */ (document.querySelector(`form#comment-form`)));
const inputComment = ( /** @type {HTMLInputElement} */ (document.querySelector(`input#comment`)));
formCommentForm.addEventListener(`submit`, (event) => {
  if (formCommentForm.checkValidity()) {
    const comment = new CommentData(inputComment.value, userIdentifier);
    comments.push(comment);
    const sectionCommentContainer = ( /** @type {HTMLElement} */ (container.appendChild(templateCommentContainer.content.querySelector(`section.comment-container`).cloneNode(true)))); {
      const spanVotes = ( /** @type {HTMLSpanElement} */ (sectionCommentContainer.querySelector(`span.votes`)));
      const buttonUpVote = ( /** @type {HTMLButtonElement} */ (sectionCommentContainer.querySelector(`button.up-vote`)));
      buttonUpVote.addEventListener(`click`, (event) => {
        if (comment.votes.has(userIdentifier)) {
          comment.votes.delete(userIdentifier);
        } else {
          comment.votes.set(userIdentifier, `up`);
        }
        spanVotes.innerText = `${comment.up.length - comment.down.length}`;
      });
      const buttonDownVote = ( /** @type {HTMLButtonElement} */ (sectionCommentContainer.querySelector(`button.down-vote`)));
      4;
      buttonDownVote.addEventListener(`click`, (event) => {
        if (comment.votes.has(userIdentifier)) {
          comment.votes.delete(userIdentifier);
        } else {
          comment.votes.set(userIdentifier, `down`);
        }
        spanVotes.innerText = `${comment.up.length - comment.down.length}`;
      });
      const spanComment = ( /** @type {HTMLSpanElement} */ (sectionCommentContainer.querySelector(`span.comment`)));
      spanComment.innerText = comment.text;
    }
  }
});
section.comment-container {
  display: grid;
  grid: 'up-vote comment' max-content 'votes comment' max-content 'down-vote comment' max-content '- comment' 1fr / max-content 1fr;
  place-items: center;
  gap: 4px;
}

section.comment-container>button.up-vote {
  grid-area: up-vote;
}

section.comment-container>span.votes {
  grid-area: votes;
}

section.comment-container>button.down-vote {
  grid-area: down-vote;
}

section.comment-container>span.comment {
  grid-area: comment;
  width: 100%;
  height: 100%;
  overflow: auto;
}
<div style="max-width: 300px; display: flex; flex-direction: column-reverse;">
  <template id="comment-container">
      <section class="comment-container">
        <button class="up-vote">↑</button>
        <span class="votes">0</span>
        <button class="down-vote">↓</button>
        <span class="comment"></span>
      </section>
    </template>
  <form method="dialog" id="comment-form">
    <input id="comment" type="text" required minlength="1" placeholder="Enter to send">
  </form>
</div>

Вам предстоит ещё...

  • получить уникальный идентификатор пользователя и передать его в константу userIdentifier вместо обычной строки который я передал. По поводу уникального значеия посмотрите сюда,
  • усовершенствовать базу данных: не оставляя её просо открытым массивом.
  • стилизовать все это.

Ещё момент

Написано с поддержкой JSDoc, но если оно мешает, я уберу со скриптов.