DTE :]

Wednesday, January 9, 2013

Membuat Fitur Komentar Berbalas (Threaded Comments) pada Blogger dengan Fungsional yang Asli

Pembaharuan 2018/05/17: Sintaks dan struktur HTML sudah berubah. Beberapa diskusi yang terdapat di dalam ruang komentar mungkin sudah tidak relevan lagi dengan isi artikel.

Membuat Fitur Komentar Berbalas (Threaded Comments) pada Blogger dengan Fungsional yang Asli
Mengaktifkan fitur threaded commenting non-standar pada Blogger.

Setelah berhasil menemukan beberapa metode untuk menciptakan komentar bersarang (atau berbalas??) pada Blogger, Saya rasa metode dari bX-NicoNico adalah yang paling bagus. Mengapa?

  1. Dia tidak menggunakan elemen <data:post.commentJso/> sebagai salah satu elemen yang dibutuhkan untuk sistem ini, sehingga markup HTML akan menjadi lebih pendek dari markup HTML pada template dengan fitur komentar bersarang yang masih standar. (Fitur komentar bersarang yang masih standar akan menampilkan JSON komentar sebelum daftar komentar, sehingga jumlah karakter markup HTML pada fitur komentar bersarang yang masih standar akan menjadi dua kali lipat lebih panjang dibandingkan markup komentar biasa.
  2. Layout komentar tertata secara otomatis. JavaScript hanya digunakan untuk mengubah URL pada iframe formulir komentar dan juga untuk memindahkan posisinya sesuai dengan ID komentar induk masing-masing.
  3. Karena layout komentar ditata secara otomatis oleh Blogger, maka saat JavaScript dimatikan, tata letak komentar balasan akan tetap berada pada posisi yang benar. Ini berbeda dengan beberapa hack komentar bersarang Blogger yang hanya menggunakan JavaScript (yang juga telah Saya pakai sampai sekarang) untuk memposisikan komentar-komentar balasan, sehingga saat JavaScript dimatikan, layout komentar akan berantakan.

Berikut ini adalah fitur komentar versi Saya yang lebih pendek dan lebih mudah dalam hal instalasi yang Saya buat berdasarkan konsep dari Felipe, yaitu dengan cara menggunakan elemen data baru bernama <data:comment.inReplyTo/> untuk menyaring anak-anak komentar yang tampil. Elemen ini berfungsi untuk menampilkan ID komentar induk pada masing-masing komentar balasan. Saya bisa mengatakan bahwa metode ini adalah metode yang paling tepat dan bukan merupakan “hack”, karena kita menerapkan elemen yang ada dari Blogger untuk dimanfaatkan sesuai dengan tugasnya:

Lihat Demo


Mengaktifkan Fitur Komentar Bersarang pada Blogger

Pertama-tama buka editor HTML template Anda kemudian cek Expand Template Widget. Temukan kode ini:

]]></b:skin>

Salin kode CSS ini dan letakkan di atasnya:

/* Begin custom comments */

.comments,
.comment {
  margin: 0;
  padding: 0;
  list-style: none;
  letter-spacing: 0;
}
.comments::after,
.comment::after,
.comment-header::after,
.comment-body::after,
.comment-footer::after {
  content: "";
  display: table;
  clear: both;
}
.custom-comments {
  margin: 3em 0 0;
  font: normal normal 13px/1.4 Tahoma, Helmet, FreeSans, sans-serif;
}
.custom-comments a {
  color: #2143b4;
  text-decoration: none;
}
.custom-comments a:hover {
  text-decoration: underline;
}
.custom-comments .comment {
  margin: 0 0 .5em;
  padding: 0 0 .75em 0;
  border-bottom: 1px solid #eee;
  position: relative;
}
.custom-comments .comment-header {
  margin: 0 0 1em 0;
}
.custom-comments .comment-author {
  float: left;
}
.custom-comments .comment-url {
  float: right;
}
.custom-comments .comment-avatar {
  width: 65px;
  float: left;
}
.custom-comments .comment-avatar a,
.custom-comments .comment-avatar img {
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  display: block;
  float: none;
  width: 50px;
  height: 50px;
  min-width: 0;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
}
.custom-comments .comment-avatar img {
  border: 1px solid #ddd;
  padding: 4px;
  background: #fafafa;
}
.custom-comments .comment-body {
  margin: -5px 0 1em 75px;
}
.custom-comments .comment.reply {
  margin: 0 0 1em 75px;
  padding: 1em 1.2em;
  background: #fff7d1;
  border: 0;
  position: relative;
  font-size: 86%;
}
.custom-comments .comment.reply::after {
  content: "";
  display: block;
  width: 0;
  height: 0;
  position: absolute;
  top: 0;
  left: 0;
  border: 10px solid transparent;
  border-color: #fff #f5f2d8 #f5f2d8 #fff;
}
.custom-comments .comment.reply .comment-author {
  margin-left: 15px;
}
.custom-comments .comment.reply a {
  color: #767643;
}
.custom-comments .comment.reply .comment-avatar img {
  border-color: #eae5c4;
  background: #f5f0d3;
}
.custom-comments .comment-footer {
  margin: 0 0 .125em 75px;
  text-align: right;
}
.custom-comments .comment-footer a,
.custom-comments .a-undo {
  display: inline-block;
  border: 1px solid #ddd;
  padding: .15em .65em .2em;
  margin: 0 0 0 .25em;
  border-radius: 1em;
  text-decoration: none;
  outline: none;
}
.custom-comments .comment.reply .comment-footer a {
  border-color: #eae5c4;
}
.custom-comments .comment-footer .a-reply::before {
  content: '\2714';
  color: #3db537;
  display: inherit;
  margin: 0 .25em 0 -.125em;
}
.custom-comments .comment-footer .a-delete::before {
  content: '\2718';
  color: #b42a21;
  display: inherit;
  margin: 0 .25em 0 -.125em;
}
.custom-comments .comment-footer a:hover,
.custom-comments .a-undo:hover {
  border-color: #ccc;
  text-decoration: none;
}
.custom-comments .comment-footer a:focus,
.custom-comments .comment-footer a:active,
.custom-comments .a-undo:focus,
.custom-comments .a-undo:active {
  border-color: #aaa;
}
.custom-comments .comment.reply .comment-footer a {
  background: #fffad6;
  border-color: #e3deb7;
}
.custom-comments .comment.reply .comment-footer a:hover {
  border-color: #d6d1aa;
}
.custom-comments .comment.reply .comment-footer a:focus,
.custom-comments .comment.reply .comment-footer a:active {
  border-color: #bcb795;
}
.custom-comments .custom-comment-form {
  margin: 1em 0 2em;
  clear: both;
}
.custom-comments .comment .custom-comment-form {
  border: 1px solid #eee;
  padding: 1em;
  margin-left: 75px;
}
.custom-comments #comment-editor {
  max-width: none;
  width: 100%;
  height: 250px;
  background: none;
  border: 0;
}
.custom-comments .custom-comment-form .a-undo {
  display: none;
}
.custom-comments .comment .custom-comment-form .a-undo {
  display: inline-block;
}
.custom-comments .comment .custom-comment-form h4 {
  display: none;
}
.custom-comments .custom-comment-editor-wrapper {
  background: transparent url('data:image/gif;base64,R0lGODlhEgAEAKEAAH9/fwAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJDwACACwAAAAAEgAEAAACB5SPqcvtrwoAIfkECQ8AAgAsAAAAAAQABAAAAgSEjwkFACH5BAkPAAIALAAAAAALAAQAAAIMjCMJC4fKXBKsnVkLACH5BAkPAAIALAAAAAASAAQAAAIRjCN5mOCwkojt0Xnkg1l1sRUAIfkECQ8AAgAsAAAAABIABAAAAhGEIRkbKRwOUsxBaStdeDdfAAAh+QQJDwACACwHAAAACwAEAAACDIQhGRuHylwSrJ1ZCwAh+QQFDwACACwOAAAABAAEAAACBISPCQUAOw==') no-repeat 50% 50%;
}
.custom-comments-pager {
  font-size: 80%;
  text-align: center;
  width: auto;
  height: auto;
  line-height: normal;
  margin: 1em 0;
  float: none;
  display: block;
  clear: both;
  border: 1px solid #eee;
  padding: .5em 1em;
  overflow: hidden;
}
.custom-comments-pager .unneeded-paging-control {
  display: none;
}
.custom-comments-pager .paging-control {
  display: inline;
}

/* Author comment style */
.custom-comments .comment.is-author {}
.custom-comments .comment.is-author > .comment-header {}

/* Deleted comment style */
.custom-comments .comment.is-deleted > .comment-body {
  font-style: italic;
  color: #aaa;
}

/* End custom comments */

Kemudian cari kode ini:

<b:includable id='comments' var='post'>

Salin kode ini, dan letakkan di atasnya:

<b:includable id='custom-comments' var='post'>
  <b:with value='{
      delete: &quot;Delete&quot;,
      reply: &quot;Reply&quot;,
      undo: &quot;Cancel Reply&quot;
  }' var='text'>
    <section class='custom-comments' id='custom-comments'>
      <b:if cond='data:post.allowComments'>
        <h4>
          <b:if cond='data:post.numComments == 1'>
            <span>1</span> <data:commentLabel/>
          <b:else/>
            <span><data:post.numComments/></span> <data:commentLabelPlural/>
          </b:if>
        </h4>
        <b:if cond='data:post.comments.size &gt; 0'>
          <ul class='comments'>
            <b:loop values='data:post.comments' var='comment'>
              <b:if cond='!data:comment.inReplyTo'>
                <b:include data='comment' name='custom-comments-comment'/>
              </b:if>
            </b:loop>
          </ul>
        </b:if>
        <b:include data='post' name='custom-comments-pager'/>
        <b:include data='post' name='custom-comments-form'/>
      </b:if>
    </section>
  </b:with>
</b:includable>
<b:includable id='custom-comments-comment' var='comment'>
  <li class='comment' expr:id='data:comment.anchorName'>
    <b:class cond='data:comment.authorClass' name='is-author'/>
    <b:class cond='data:comment.isDeleted' name='is-deleted'/>
    <header class='comment-header'>
      <strong class='comment-author'>
        <b:if cond='data:comment.authorUrl'>
          <a expr:href='data:comment.authorUrl' rel='nofollow' target='_blank'><data:comment.author/></a>
        <b:else/>
          <data:comment.author/>
        </b:if> <data:commentPostedByMsg/>
      </strong>
      <a class='comment-url' expr:href='data:comment.url'><data:comment.timestamp/></a>
    </header>
    <figure class='comment-avatar'>
      <img alt='' expr:src='resizeImage(data:comment.authorAvatarSrc, 50)'/>
    </figure>
    <div class='comment-body'>
      <data:comment.body/>
    </div>
    <b:with value='data:post.comments filter (i =&gt; i.inReplyTo == data:comment.id)' var='replies'>
      <b:if cond='data:replies.size &gt; 0'>
        <ul class='comments replies'>
          <b:loop values='data:replies' var='reply'>
            <b:include data='reply' name='custom-comments-comment-reply'/>
          </b:loop>
        </ul>
      </b:if>
    </b:with>
    <footer class='comment-footer'>
      <b:if cond='!data:comment.isDeleted'>
        <a class='a-reply' expr:href='&quot;javascript:replyTo(&amp;quot;&quot; + data:comment.id + &quot;&amp;quot;);&quot;'><data:text.reply/></a>
      </b:if>
      <a class='a-delete' expr:href='data:comment.deleteUrl' expr:title='data:top.deleteCommentMsg'><data:text.delete/></a>
    </footer>
  </li>
</b:includable>
<b:includable id='custom-comments-comment-reply' var='reply'>
  <li class='comment reply' expr:id='data:reply.anchorName'>
    <b:class cond='data:reply.authorClass' name='is-author'/>
    <b:class cond='data:reply.isDeleted' name='is-deleted'/>
    <header class='comment-header'>
      <strong class='comment-author'>
        <b:if cond='data:reply.authorUrl'>
          <a expr:href='data:reply.authorUrl' rel='nofollow' target='_blank'><data:reply.author/></a>
        <b:else/>
          <data:reply.author/>
        </b:if> <data:commentPostedByMsg/>
      </strong>
      <a class='comment-url' expr:href='data:reply.url'><data:reply.timestamp/></a>
    </header>
    <figure class='comment-avatar'>
      <img alt='' expr:src='resizeImage(data:reply.authorAvatarSrc, 50)'/>
    </figure>
    <div class='comment-body'>
      <data:reply.body/>
    </div>
    <footer class='comment-footer'>
      <a class='a-delete' expr:href='data:reply.deleteUrl' expr:title='data:top.deleteCommentMsg'><data:text.delete/></a>
    </footer>
  </li>
</b:includable>
<b:includable id='custom-comments-form' var='post'>
  <div class='custom-comment-form' id='custom-comment-form'>
    <h4><data:postCommentMsg/></h4>
    <p><data:blogCommentMessage/></p>
    <data:blogTeamBlogMessage/>
    <a expr:href='data:post.commentFormIframeSrc' id='comment-editor-src'/>
    <div class='custom-comment-editor-wrapper'>
      <iframe class='blogger-iframe-colorize blogger-comment-from-post' id='comment-editor' name='comment-editor' src=''/>
    </div>
    <data:post.friendConnectJs/>
    <data:post.cmtfpIframe/>
    <script>BLOG_CMT_createIframe(&#39;<data:post.appRpcRelayPath/>&#39;, &#39;<data:post.communityId/>&#39;);</script>
    <a class='a-undo' href='javascript:replyTo(0);'><data:text.undo/></a>
  </div>

  <script>
    //<![CDATA[
    var originalSource = document.getElementById('comment-editor').src.split('#');
    function replyTo(id) {
      var frame = document.getElementById('comment-editor'),
          form = document.getElementById('custom-comment-form'),
          container = id ? document.getElementById('c' + id) : document.getElementById('custom-comments'),
          part = originalSource;
      frame.style.height = "50px";
      frame.style.visibility = "hidden";
      frame.src = id ? part[0] + '&parentID=' + id + '#' + part[1] : part[0] + '#' + part[1];
      container.insertBefore(form, null);
      frame.onload = function() {
        this.style.height = "250px";
        this.style.visibility = "visible";
      };
    }
    //]]>
  </script>
</b:includable>
<b:includable id='custom-comments-pager' var='post'>
  <b:if cond='data:post.commentPagingRequired'>
    <nav class='custom-comments-pager'>
      <a expr:class='data:post.oldLinkClass' expr:href='data:post.olderLinkUrl'><data:post.olderLinkText/></a>&#160;
      <a expr:class='data:post.oldLinkClass' expr:href='data:post.oldestLinkUrl'><data:post.oldestLinkText/></a>&#160;
      <data:post.commentRangeText/>&#160;
      <a expr:class='data:post.newLinkClass' expr:href='data:post.newestLinkUrl'><data:post.newestLinkText/></a>&#160;
      <a expr:class='data:post.newLinkClass' expr:href='data:post.newerLinkUrl'><data:post.newerLinkText/></a>
    </nav>
  </b:if>
</b:includable>

Terakhir tinggal mengaktifkan fitur komentar kita. Cari semua kode yang tampak seperti ini:

<b:include data='post' name='threaded_comments'/>

atau seperti ini:

<b:include data='post' name='comments'/>

Di manapun Anda menemukan kode itu, segera ganti dengan kode ini:

<b:include data='post' name='custom-comments'/>

Klik Simpan Template.

Konfigurasi

Kode-kode yang Saya beri tanda adalah label-label tombol dan bisa Anda ganti teksnya sesuka hati sesuai dengan bahasa pada negara dimana Anda tinggal. Fitur penanda komentar administrator juga ada. Untuk mengaktifkannya, Anda bisa menggunakan selektor-selektor CSS yang tercantum di atas, kemudian awali dengan kelas .is-author untuk menandai komentar penulis. Sebagai contoh, Saya akan memberikan border warna merah dan latar warna kuning pada komentar administrator, maka yang harus Anda lakukan adalah seperti ini:

.comment.is-author {
  border: 5px solid #900;
  background-color: #ff0;
}
.comment.is-author > .comment-body {
  font-size: 200%;
}

Catatan: Bagi Anda yang selama ini telah lama menggunakan fitur komentar bersarang lebih dari dua level (seperti blog Saya), sangat disarankan untuk tidak menerapkan modifikasi di atas, karena Saya hanya menggunakan loop komentar balasan sebanyak satu kali:

<b:loop values='data:post.comments' var='reply'>
  <b:if cond='data:reply.inReplyTo == data:comment.id'>
    Komentar balasan muncul di sini…
  </b:if>
</b:loop>

Seperti yang Anda lihat bahwa Saya hanya membandingkan nilai data:var.inReplyTo pada komentar balasan dengan ID komentar induk sekali saja (satu kali loop), sehingga jika komentar balasan lama Anda berada di level ke tiga dan seterusnya, komentar-komentar tersebut tidak akan tampil dalam posting Anda dikarenakan ID komentar induknya tidak sempat lolos penyaringan terhadap data:var.inReplyTo pada anak komentar di level tersebut.

Blog yang masih baru atau blog lama dengan sedikit komentar dan blog dengan fitur komentar yang masih lama bisa melakukan modifikasi ini dengan aman.

Labels: ,

144 Comments:

Post a Comment



<< Home