Hướng dẫn thêm một cấp reply comment cho Blogger layout v3

Chắc bạn cũng đã biết nhận xét mặc định của Blogger chỉ có môt cấp reply comment. Cụ thể, bạn chỉ có thể reply lại những người đã bình luận bài viết mà không có tùy chọn reply phản hồi lại những bình luận đó. Lấy ví dụ, có người nào đó bình luận bài viết, người đó cùng những người khác có thể reply phản hồi lại bình luận đó, tuy nhiên lại không có tùy chọn reply phản hồi lại những bình luận đó.

blogger comment thread

Với hướng dẫn của mình dưới đây, bạn có thể tạo thêm nhiều cấp reply nhưng chỉ nên tạo thêm một cấp nữa là đủ.

Tất cả bình luận trong một bài viết được lấy từ một thẻ data duy nhất có tên <data:post.commentHtml/>, và để tạo được phân cấp điều bạn cần làm là xóa bỏ thẻ này đi và thay bằng các thẻ data bên trong thẻ này hay nói các khác là mổ xẻ thẻ này ra.

Lợi ích khi bạn mổ thẻ dữ liệu <data:post.commentHtml/> bạn có thể giải quyết về vấn đề về SEO, chèn thuộc tính rel, title vào thẻ tag a, loại bỏ các element thừa hay thay thế bằng các thẻ elemnet khác, hiển thị số bình luận chính thay vì 200 nó quá nhiều.

Phần hướng dẫn dưới đây, mình chỉ bung thẻ <data:post.commentHtml/> ra thôi còn tùy biến thế nào là do bạn

Bước 1: Thêm một thẻ b:includable cùng với các thẻ b:includable khác trong widget Blog1

<b:includable id='commentsContent' var='post'>
  <div class='comment-thread toplevel-thread'>
    <ol id='top-ra'>
      <b:loop values='data:post.comments' var='firstlevel'>
        <b:if cond='!data:firstlevel.inReplyTo'>
          <li class='comment hidden' expr:id='&quot;c&quot; + data:firstlevel.id'>
            <div class='avatar-image-container'>
              <b:if cond='data:firstlevel.authorPhoto.url'>
                <img expr:alt='data:firstlevel.author' expr:src='resizeImage(data:firstlevel.authorPhoto.url, 40, &quot;1:1&quot;)'/>
              <b:else/>
                <img expr:alt='data:firstlevel.author' src='https://lh3.googleusercontent.com/zFdxGE77vvD2w5xHy6jkVuElKv-U9_9qLkRYK8OnbDeJPtjSZ82UPq5w6hJ-SA=s40'/>
              </b:if>
            </div>
            <div class='comment-block'>
              <div class='comment-header'>
                <cite class='user'><a expr:href='data:firstlevel.authorUrl' expr:title='data:firstlevel.author' rel='noopener nofollow' target='_blank'><data:firstlevel.author/></a></cite>
                <span class='datetime secondary-text'>
                  <a expr:href='data:firstlevel.url' expr:title='data:firstlevel.timestamp' rel='nofollow' target='_self'><data:firstlevel.timestamp/></a>
                </span>
              </div>
              <p class='comment-content'><data:firstlevel.body/></p>
              <span class='comment-actions secondary-text'>
                <a class='comment-reply' expr:data-comment-id='data:firstlevel.id' expr:href='&quot;#&quot; + data:firstlevel.id' rel='nofollow' target='_self' title='Trả lời'>Trả lời</a>
                <span expr:class='&quot;item-control &quot; + data:firstlevel.adminClass'><a expr:href='data:firstlevel.deleteUrl' expr:title='data:messages.deleteComment' rel='nofollow' target='_self'>Xóa</a></span>
              </span>
            </div>
            <div class='comment-replies'>
              <div class='comment-thread secondlevel-thread' expr:id='&quot;c&quot; + data:firstlevel.id + &quot;-rt&quot;'>
                <ol class='thread-chrome thread-expanded' expr:id='&quot;c&quot; + data:firstlevel.id + &quot;-ra&quot;'>
                  <b:loop values='data:post.comments' var='secondlevel'>
                    <b:if cond='data:secondlevel.inReplyTo == data:firstlevel.id'>
                      <li class='comment' expr:id='&quot;c&quot; + data:secondlevel.id'>
                        <div class='avatar-image-container'>
                          <b:if cond='data:secondlevel.authorPhoto.url'>
                            <img expr:alt='data:secondlevel.author' expr:src='resizeImage(data:secondlevel.authorPhoto.url, 35, &quot;1:1&quot;)'/>
                          <b:else/>
                            <img expr:alt='data:secondlevel.author' src='https://lh3.googleusercontent.com/zFdxGE77vvD2w5xHy6jkVuElKv-U9_9qLkRYK8OnbDeJPtjSZ82UPq5w6hJ-SA=s35'/>
                          </b:if>
                        </div>
                        <div class='comment-block'>
                          <div class='comment-header'>
                            <cite class='user'><a expr:href='data:secondlevel.authorUrl' expr:title='data:secondlevel.author' rel='noopener nofollow' target='_blank'><data:secondlevel.author/></a></cite>
                            <span class='datetime secondary-text'><a expr:href='data:secondlevel.url' expr:title='data:secondlevel.timestamp' rel='nofollow' target='_self'><data:secondlevel.timestamp/></a></span>
                          </div>
                          <p class='comment-content'><data:secondlevel.body/></p>
                          <span class='comment-actions secondary-text'>
                            <a class='comment-reply' expr:data-comment-id='data:secondlevel.id' expr:href='&quot;#&quot; + data:secondlevel.id' rel='nofollow' target='_self' title='Trả lời'>Trả lời</a>
                            <span expr:class='&quot;item-control &quot; + data:secondlevel.adminClass'><a expr:href='data:secondlevel.deleteUrl' expr:title='data:messages.deleteComment' rel='nofollow' target='_self'>Xóa</a></span>
                          </span>
                        </div>
                        <div class='comment-replies'>
                          <div class='comment-thread thirdlevel-thread' expr:id='&quot;c&quot; + data:secondlevel.id + &quot;-rt&quot;'>
                            <ol class='thread-chrome thread-expanded' expr:id='&quot;c&quot; + data:secondlevel.id + &quot;-ra&quot;'>
                              <b:loop values='data:post.comments' var='thirdlevel'>
                                <b:if cond='data:thirdlevel.inReplyTo == data:secondlevel.id'>
                                  <li class='comment' expr:id='&quot;c&quot; + data:thirdlevel.id'>
                                    <div class='avatar-image-container'>
                                      <b:if cond='data:thirdlevel.authorPhoto.url'>
                                        <img expr:alt='data:thirdlevel.author' expr:src='resizeImage(data:thirdlevel.authorPhoto.url, 35, &quot;1:1&quot;)'/>
                                      <b:else/>
                                        <img expr:alt='data:thirdlevel.author' src='https://lh3.googleusercontent.com/zFdxGE77vvD2w5xHy6jkVuElKv-U9_9qLkRYK8OnbDeJPtjSZ82UPq5w6hJ-SA=s35'/>
                                      </b:if>
                                    </div>
                                    <div class='comment-block'>
                                      <div class='comment-header'>
                                        <cite class='user'><a expr:href='data:thirdlevel.authorUrl' expr:title='data:thirdlevel.author' rel='noopener nofollow' target='_blank'><data:thirdlevel.author/></a></cite>
                                        <span class='datetime secondary-text'><a expr:href='data:thirdlevel.url' expr:title='data:thirdlevel.timestamp' rel='nofollow' target='_self'><data:thirdlevel.timestamp/></a></span>
                                      </div>
                                      <p class='comment-content'><data:thirdlevel.body/></p>
                                      <span class='comment-actions secondary-text'>
                                        <span expr:class='&quot;item-control &quot; + data:thirdlevel.adminClass'><a expr:href='data:thirdlevel.deleteUrl' expr:title='data:messages.deleteComment' rel='nofollow' target='_self'>Xóa</a></span>
                                      </span>
                                    </div>
                                  </li>
                                </b:if>
                              </b:loop>
                            </ol>
                          </div>
                        </div>
                        <div class='comment-replybox-single' expr:id='&quot;c&quot; + data:secondlevel.id + &quot;-ce&quot;'/>
                      </li>
                    </b:if>
                  </b:loop>
                </ol>
              </div>
            </div>
            <div class='comment-replybox-single' expr:id='&quot;c&quot; + data:firstlevel.id + &quot;-ce&quot;'/>
          </li>
        </b:if>
      </b:loop>
    </ol>
    <div class='comment-replybox-thread' id='top-ce'/>
    <div class='loadmore hidden' expr:data-post-id='data:post.id'><a expr:title='data:messages.showMore' href='#loadmore' rel='nofollow' target='_self'><data:messages.showMore/></a></div>
    <div class='continue' id='top-continue'><a class='comment-reply' expr:href='data:post.commentFormIframeSrc' rel='nofollow' target='_self' title='Thêm nhận xét'>Thêm nhận xét</a></div>
  </div>
</b:includable>

Bước 2: Thay thế thẻ <data:post.commentHtml/>

Thẻ này nằm trong thẻ b:includable tên <b:includable id='threadedComments' var='post'>, các bạn thay thế bằng thẻ <b:include data='post' name='commentsContent'/>

Bước 3: Chèn script trước thẻ đóng </body>

Đoạn script này mình viết bằng jquery cho nên theme cần có thư viện jquery

<script>//<![CDATA[
$(function() {
  var url = window.location.href,
    str = $('.toplevel-thread>ol>li'),
    l = '',
    id = '',
    li = '',
    m = 10, // Số bình luận hiển thị chính
    n = str.length,
    k = 0,
    p = 0
  // Gọi iframe khi click vào nút reply
  $('.comment a.comment-reply').click(function(e) {
    l = $('#comment-editor').attr('src')
    $('.calcel-reply').remove()
    $('.comment-actions').removeAttr('style')
    $('#top-continue.continue').hide()
    var $this = $(this),
      id = $this.attr('data-comment-id')
    l = l + '&parentID=' + id
    li = $this.parent().parent().parent().attr('id')
    $('#comment-editor').attr('src', l)
    $this.parent().hide()
    $('#comment-editor').appendTo($('#' + li + '>.comment-replybox-single'))
    $('#' + li + '>.comment-replybox-single').append('<div class="calcel-reply"><button class="theme-button green" type="button">Hủy</button></div>')
    $('.calcel-reply').click(function() {
      $(this).remove()
      $('.comment-actions,#top-continue.continue').removeAttr('style')
      $('#comment-editor').appendTo($('.comment-form'))
    })
  })
  // Gọi iframe khi click vào nút Thêm nhận xét dưới cùng
  $('#top-continue.continue>a.comment-reply').click(function(e) {
    e.preventDefault()
    $(this).parent().hide()
    $('.calcel-reply').remove()
    $('.comment-actions').removeAttr('style')
    $('#comment-editor').appendTo($(this).parent().next())
    $('.comment-replybox-thread').append('<div class="calcel-reply"><button class="theme-button green" type="button">Hủy</button></div>')
    $('.calcel-reply').click(function() {
      $(this).remove()
      $('.comment-actions,#top-continue.continue').removeAttr('style')
      $('#comment-editor').appendTo($('.comment-form'))
    })
  })
  // Xử lý địa chỉ trình duyệt nếu có liên kết đến bình luận
  if (url.indexOf('?showComment') != -1) {
    if (url.indexOf('#c') != -1) {
      var li = '#' + url.substring(url.indexOf('#c') + 1, url.length)
      if ($(li).parents('.comment-thread').hasClass('thirdlevel-thread')) {
        k = $(li).parents('li').parents('li').index()
      } else if ($(li).parents('.comment-thread').hasClass('secondlevel-thread')) {
        k = $(li).parents('li').index()
      } else {
        k = $(li).index()
      }
      if (k >= m) {
        for (var i = 0; i < k + 1; i++) {
          $(str[i]).removeClass('hidden')
        }
      } else {
        for (var i = 0; i < m; i++) {
          $(str[i]).removeClass('hidden')
        }
      }
      if (k < n) {
        $('#comments .loadmore').removeClass('hidden')
      }
    } else {
      for (var i = 0; i < m; i++) {
        $(str[i]).removeClass('hidden')
      }
      if (n > m) {
        $('#comments .loadmore').removeClass('hidden')
      }
    }
  } else {
    for (var i = 0; i < m; i++) {
      $(str[i]).removeClass('hidden')
    }
    if (n > m) {
      $('#comments .loadmore').removeClass('hidden')
    }
  }
  // Hiển thị thêm bình luận chính
  $('#comments .loadmore>a').click(function() {
    p = $('.toplevel-thread>ol>li.comment.hidden').length
    k = n - p
    if (p == 0) {
      $(this).parent().addClass('hidden')
    } else {
      for (var i = k; i < k + m; i++) {
        $(str[i]).removeClass('hidden')
      }
    }
  })
})
//]]></script>

Phần css cho giao diện bình luận, bạn tự design theo sở thích của bạn, lưu ý thêm một class .hidden với display:none; nha các bạn

4.5/5 - (1312 bình chọn)

14 Nhận xét
  1. Anh có thể share commentsContent của anh được không ạ?
    Phần comments của blog a đẹp quá

    Trả lờiXóa
    Trả lời
    1. thread comment theme anh nó phức tạp lắm, nó liên quan đến nhiều thứ, em tham khảo link https://anotepad.com/notes/kmhkqs5, em thay lại 4 thẻ b:includable, chèn script trước thẻ đóng </body>

      Xóa
  2. Em làm nó lại lỗi như này a ơi.
    link: https://newspaper-tinh.blogspot.com/2018/05/how-good-team-can-positively-influence.html

    Trả lờiXóa
    Trả lời
    1. trong thẻ b:includable commentsContent, anh ghi nhầm thẻ img gần cuối, em kiểm tra thuộc tính expr:data-src và sửa lại thành expr:src nhé

      Xóa
    2. oke rồi a. mà a cho e hỏi làm sao xóa 2 cái border-top+bottom của khung comment vậy a

      Xóa
    3. Cái này em phải thay thuộc tính b:templateUrl có trong html đầu trang, sửa indie.xml thành vegeclub.xml

      Xóa
    4. thay nó error form comments mất a :(

      Xóa
    5. Thêm 1 dòng Variable
      <Variable name="posts.link.color" description="Post link color" type="color" default="#385898" value="#385898"/>
      em thay lại mã màu tùy thích

      Xóa
    6. Nếu thuộc tính cũ là indie.xml (theme Contempo), trong em tìm đến đoạn <Group description="Posts" selector="div.widget.Blog"> bên trong group này em thêm 1 đoạn Variable nữa vì nó đang bị thiếu

      Xóa
    7. thanks anh, nhưng template này nó không có b:templateUrl luôn.
      Nếu a rảnh thì gửi mail e add vào a làm giúp e . em gửi ít công

      Xóa
    8. Nhận xét này đã bị tác giả xóa.

      Xóa
  3. Hi anh, anh có thể cho em xin source của các includable liên quan đến comment không anh? Em làm theo hướng dẫn bài trước và bài này đều không được ạ. Cảm ơn anh!
    Email: vantaile.1990@gmail.com

    Trả lờiXóa
  4. Cho mình hỏi chút là chỉnh sửa đoạn nào để hệ thống tự nhận biết là comment của admin blog ạ?

    Trả lờiXóa
    Trả lời
    1. Saya menerapkan seperti ini
      <cite class='user'><b:if cond='data:firstlevel.author == data:post.author.name'>
      <span class='icon user blog-author'><data:firstlevel.author/></span><b:else/><span><data:firstlevel.author/></span>
      </b:if></cite>

      Xóa