<form id="commentForm" class="comment-form">
  <fieldset id="commentFormBody" class="comment-form-body">
    <div class="comment-form-title">Post a comment</div>
    <textarea id="commentText" class="comment-form-textarea">
What if I quickly click Submit multiple times?
    </textarea>
    <div class="comment-form-actions">
      <input id="commentSubmitButton" class="comment-form-action-submit" type="submit" value="Submit"> 
    </div>
  </fieldset>
</form>

<div class="comment-feed">
  <div class="comment-feed-title">Comments</div>
  <ol id="commentFeedList" class="comment-feed-list">
  </ol>
</div>


<script id="commentTemplate" type="text/x-handlebars-template">
  <li class="comment-feed-item">
     <div class="comment-feed-item-timestamp">
       <time datetime="{{isoDate}}">{{humanDate}}</time>
     </div>
     <div class="comment-feed-item-message">{{comment}}</div>
   </li>
</script>
*
  box-sizing: border-box

.comment-form-title,
.comment-feed-title
  font-size: 1.5em
  margin-bottom: .5em
  
.comment-form
  .comment-form-body
    border: none
    margin: 0
    padding: 0
  
  .comment-form-textarea
    width: 300px
    height: 70px
    padding: .5em
      
  .comment-form-action-submit
    padding: .5em 2em
  
.comment-feed
  margin-top: 2em
  
  .comment-feed-list
    list-style: none
    padding: 0
    margin: 1em 0 0 0
    
    .comment-feed-item
      padding: 0
      margin-top: 1em
      border-top: solid 1px #ccc
      padding: .5em 0
      &:first-child
        border-top: none
      
      .comment-feed-item-timestamp
        color: #444
        margin-bottom: .5em
      
      .comment-feed-item-message
        font-size: 1.2em

 
View Compiled
function submitComment() {
  let comment = $('#commentText').val().trim();
  setLoading();
  fakePost(comment)
    .then(insertComment)
    .finally(resetLoading);
}

function fakePost(comment) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      let data = {
        comment: comment,
        date: new Date()
      }
      resolve(data);
    }, 2000);
  }); 
}

function setLoading() {
  $('#commentSubmitButton').val('Submitting...');
  $('#commentFormBody').attr('disabled', true);
}

function resetLoading() {
  $('#commentSubmitButton').val('Submit');
  $('#commentFormBody').attr('disabled', false);
}

function insertComment(data) {
  let comment = {
    comment: data.comment,
    isoDate: data.date.toISOString(),
    humanDate: data.date.toLocaleString()
  };
  let html = commentView(comment);
  $('#commentFeedList').prepend(html);  
}

const commentView = Handlebars.compile($('#commentTemplate').html());

function main() {
  const mockComment = {
    comment: 'Great post!',
    date: new Date()
  };

  insertComment(mockComment);

  $('#commentForm').on('submit', (e) => {
    submitComment();
    e.preventDefault();
    return false;
  });
}

main();

View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.1/handlebars.min.js