Masalah Threaded Comment Pada Template Blogger Lama

Berawal dari pertanyaan teman blogger dari Malaysia Haz Issac tentang Threaded Comments yang ada pada salah satu template buatan saya (Mas paper), yang menanyakan bagaimana caranya agar Threaded Comments pada template bisa berfungsi? Setelah mengganti beberapa kode script yang ada, tampilan komentar sudah ada fungsi reply dan delete, tapi permasalahan yang terjadi kemudian fitur reply tidak berfungsi normal, atau ketika diklik hanya ada tulisan javascript pada bagian bawah browser.

threaded comments

Terus terang kebanyakan dari template yang saya buat masih menggunakan fitur blogger lama, sehingga secara default belum dilengkapi fungsi reply atau Threaded Comments yang sudah dikembangkan oleh Blogger baru-baru ini. Kali ini saya akan mencoba memberikan satu tutorial bagi para pengguna template blogger lama (bukan klasik), bagaimana cara mengatasi permasalahan Threaded Comment khususnya bagi mereka yang sudah mengganti kode dengan menambahkan Threaded Comments tapi fitur reply tidak berfungsi normal.

Langkah Pertama

Cara atau metode pertama ini harus Anda lakukan agar Threaded Coments pada blog Anda berfungsi.
  1. Login ke blogger dengan akun Anda
  2. Pada dashboard pilih blog yang akan diberikan Threaded Comments (blogger new interface)
  3. Setelah itu masuk ke Settings >> Posts and Comments
  4. Kemudian pilih Comment Location setting pada posisi Embedded.
  5. Kembali lagi ke Setting, kali ini klik Other, pada Allow blog post pada baris pertama pilih posisi Full.
  6. Terakhir Save, kemudian lihat hasilnya apakah Threaded Comments sudah ada pada blog Anda. Jika belum ikuti langkah kedua di bawah ini.
Langkah Kedua
  1. Masuk ke Template kemudian pilih Edit HTML.
  2. Jangan lupa untuk centang Expand Widget Templates. Untuk berjaga-jaga agar tidak terjadi kesalahan dalam pengeditan nantinya, lebih baik backup dulu template Anda.
  3. Kemudian cari kode di bawah ini :
            <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
    <b:include data='post' name='comments'/>
    </b:if>
    <b:if cond='data:blog.pageType == &quot;item&quot;'>
    <b:include data='post' name='comments'/>
    </b:if>
  4. Setelah ketemu ganti dengan kode berikut :
            <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
    <b:if cond='data:post.showThreadedComments'>
    <b:include data='post' name='threaded_comments'/>
    <b:else/>
    <b:include data='post' name='comments'/>
    </b:if>
    </b:if>
    <b:if cond='data:blog.pageType == &quot;item&quot;'>
    <b:if cond='data:post.showThreadedComments'>
    <b:include data='post' name='threaded_comments'/>
    <b:else/>
    <b:include data='post' name='comments'/>
    </b:if>
    </b:if>
  5. Terakhir Save template, lihat dulu hasilnya.
Biasanya setelah Anda melakukan langkah kedua ini, Threaded Comments sudah ada pada blog Anda, tapi harus dicek satu persatu fungsinya. Permasalahan yang sering muncul adalah banyak sekali template yang masih menggunakan script blogger classic sehingga fitur reply (balas) tidak berfungsi normal. Jika fungsi Reply tidak berjalan, ikuti langkah ketiga berikut ini :

Langkah Ketiga

Langkah ini hanya dilakukan jika fungsi Reply tidak berjalan atau biasanya hanya keluar tulisan javascript pada browser bawah. Jika pada langkah kedua Threaded Comments sudah berfungsi normal langkah ini tinggalkan saja.
  1. Masih pada posisi Edit HTML (centang Expand Widget Templates), cari kode di bawah ini :
    <script type='text/javascript'>
    (function() {
    var items = <data:post.commentJso/>;
    var msgs = <data:post.commentMsgs/>;
    var postId = &#39;<data:post.id/>&#39;;
    var feed = &#39;<data:post.commentFeed/>&#39;;
    var authorName = &#39;<data:post.author/>&#39;;
    var authorUrl = &#39;<data:post.authorUrl/>&#39;;
    var blogId = &#39;<data:top.id/>&#39;;
    var baseUri = &#39;<data:post.commentBase/>&#39;;

    // <![CDATA[
    feed += '?alt=json&v=2&orderby=published&reverse=false&max-results=50';
    var cursor = null;
    if (items && items.length > 0) {
    cursor = parseInt(items[items.length - 1].timestamp) + 1;
    }

    var bodyFromEntry = function(entry) {
    if (entry.gd$extendedProperty) {
    for (var k in entry.gd$extendedProperty) {
    if (entry.gd$extendedProperty[k].name == 'blogger.contentRemoved') {
    return '<span class="deleted-comment">' + entry.content.$t + '</span>';
    }
    }
    }
    return entry.content.$t;
    }

    var parse = function(data) {
    cursor = null;
    var comments = [];
    if (data && data.feed && data.feed.entry) {
    for (var i = 0, entry; entry = data.feed.entry[i]; i++) {
    var comment = {};
    // comment ID, parsed out of the original id format
    var id = /blog-(\d+).post-(\d+)/.exec(entry.id.$t);
    comment.id = id ? id[2] : null;
    comment.body = bodyFromEntry(entry);
    comment.timestamp = Date.parse(entry.published.$t) + '';
    if (entry.author && entry.author.constructor === Array) {
    var auth = entry.author[0];
    if (auth) {
    comment.author = {
    name: (auth.name ? auth.name.$t : undefined),
    profileUrl: (auth.uri ? auth.uri.$t : undefined),
    avatarUrl: (auth.gd$image ? auth.gd$image.src : undefined)
    };
    }
    }
    if (entry.link) {
    if (entry.link[2]) {
    comment.link = comment.permalink = entry.link[2].href;
    }
    if (entry.link[3]) {
    var pid = /.*comments\/default\/(\d+)\?.*/.exec(entry.link[3].href);
    if (pid && pid[1]) {
    comment.parentId = pid[1];
    }
    }
    }
    comment.deleteclass = 'item-control blog-admin';
    if (entry.gd$extendedProperty) {
    for (var k in entry.gd$extendedProperty) {
    console.log(entry.gd$extendedProperty[k].name + ' - ' + entry.gd$extendedProperty[k].value);
    if (entry.gd$extendedProperty[k].name == 'blogger.itemClass') {
    comment.deleteclass += ' ' + entry.gd$extendedProperty[k].value;
    }
    }
    }
    comments.push(comment);
    }
    }
    return comments;
    };

    var paginator = function(callback) {
    if (hasMore()) {
    var url = feed;
    if (cursor) {
    url += '&published-min=' + new Date(cursor).toISOString();
    }
    window.bloggercomments = function(data) {
    var parsed = parse(data);
    cursor = parsed.length < 50 ? null
    : parseInt(parsed[parsed.length - 1].timestamp) + 1
    callback(parsed);
    window.bloggercomments = null;
    }
    url += '&callback=bloggercomments';
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
    }
    };
    var hasMore = function() {
    return !!cursor;
    };
    var getMeta = function(key, comment) {
    if ('iswriter' == key) {
    var matches = !!comment.author
    && comment.author.name == authorName
    && comment.author.profileUrl == authorUrl;
    return matches ? 'true' : '';
    } else if ('deletelink' == key) {
    return baseUri + '/delete-comment.g?blogID=' + blogId + '&postID=' + comment.id;
    } else if ('deleteclass' == key) {
    return comment.deleteclass;
    }
    return '';
    };

    var replybox = null;
    var replyUrlParts = null;
    var replyParent = undefined;

    var onReply = function(commentId, domId) {
    if (replybox == null) {
    // lazily cache replybox, and adjust to suit this style:
    replybox = document.getElementById('comment-editor');
    if (replybox != null) {
    replybox.height = '250px';
    replybox.style.display = 'block';
    replyUrlParts = replybox.src.split('#');
    }
    }
    if (replybox && (commentId !== replyParent)) {
    document.getElementById(domId).insertBefore(replybox, null);
    replybox.src = replyUrlParts[0]
    + (commentId ? '&parentID=' + commentId : '')
    + '#' + replyUrlParts[1];
    replyParent = commentId;
    }
    };

    var tok = 'comment-form_';
    var hash = window.location.hash || '';
    var startThread = hash.indexOf(tok) == 1 ? hash.substring(tok.length + 1) : undefined;

    // Configure commenting API:
    var configJso = {
    'maxDepth': 2
    };
    var provider = {
    'id': postId,
    'data': items,
    'loadNext': paginator,
    'hasMore': hasMore,
    'getMeta': getMeta,
    'onReply': onReply,
    'rendered': true,
    'initReplyThread': startThread,
    'config': configJso,
    'messages': msgs
    };

    var render = function() {
    if (window.goog && window.goog.comments) {
    var holder = document.getElementById('comment-holder');
    window.goog.comments.render(holder, provider);
    }
    };

    // render now, or queue to render when library loads:
    if (window.goog && window.goog.comments) {
    render();
    } else {
    window.goog = window.goog || {};
    window.goog.comments = window.goog.comments || {};
    window.goog.comments.loadQueue = window.goog.comments.loadQueue || [];
    window.goog.comments.loadQueue.push(render);
    }
    })();
    // ]]>
    </script>
  2. Setelah ketemu ganti dengan kode berikut :
    <script type='text/javascript'>
    (function() {
    var items = <data:post.commentJso/>;
    var msgs = <data:post.commentMsgs/>;
    var config = <data:post.commentConfig/>;

    // <![CDATA[
    var cursor = null;
    if (items && items.length > 0) {
    cursor = parseInt(items[items.length - 1].timestamp) + 1;
    }

    var bodyFromEntry = function(entry) {
    if (entry.gd$extendedProperty) {
    for (var k in entry.gd$extendedProperty) {
    if (entry.gd$extendedProperty[k].name == 'blogger.contentRemoved') {
    return '<span class="deleted-comment">' + entry.content.$t + '</span>';
    }
    }
    }
    return entry.content.$t;
    }

    var parse = function(data) {
    cursor = null;
    var comments = [];
    if (data && data.feed && data.feed.entry) {
    for (var i = 0, entry; entry = data.feed.entry[i]; i++) {
    var comment = {};
    // comment ID, parsed out of the original id format
    var id = /blog-(\d+).post-(\d+)/.exec(entry.id.$t);
    comment.id = id ? id[2] : null;
    comment.body = bodyFromEntry(entry);
    comment.timestamp = Date.parse(entry.published.$t) + '';
    if (entry.author && entry.author.constructor === Array) {
    var auth = entry.author[0];
    if (auth) {
    comment.author = {
    name: (auth.name ? auth.name.$t : undefined),
    profileUrl: (auth.uri ? auth.uri.$t : undefined),
    avatarUrl: (auth.gd$image ? auth.gd$image.src : undefined)
    };
    }
    }
    if (entry.link) {
    if (entry.link[2]) {
    comment.link = comment.permalink = entry.link[2].href;
    }
    if (entry.link[3]) {
    var pid = /.*comments\/default\/(\d+)\?.*/.exec(entry.link[3].href);
    if (pid && pid[1]) {
    comment.parentId = pid[1];
    }
    }
    }
    comment.deleteclass = 'item-control blog-admin';
    if (entry.gd$extendedProperty) {
    for (var k in entry.gd$extendedProperty) {
    if (entry.gd$extendedProperty[k].name == 'blogger.itemClass') {
    comment.deleteclass += ' ' + entry.gd$extendedProperty[k].value;
    }
    }
    }
    comments.push(comment);
    }
    }
    return comments;
    };

    var paginator = function(callback) {
    if (hasMore()) {
    var url = config.feed + '?alt=json&v=2&orderby=published&reverse=false&max-results=50';
    if (cursor) {
    url += '&published-min=' + new Date(cursor).toISOString();
    }
    window.bloggercomments = function(data) {
    var parsed = parse(data);
    cursor = parsed.length < 50 ? null
    : parseInt(parsed[parsed.length - 1].timestamp) + 1
    callback(parsed);
    window.bloggercomments = null;
    }
    url += '&callback=bloggercomments';
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
    }
    };
    var hasMore = function() {
    return !!cursor;
    };
    var getMeta = function(key, comment) {
    if ('iswriter' == key) {
    var matches = !!comment.author
    && comment.author.name == config.authorName
    && comment.author.profileUrl == config.authorUrl;
    return matches ? 'true' : '';
    } else if ('deletelink' == key) {
    return config.baseUri + '/delete-comment.g?blogID='
    + config.blogId + '&postID=' + comment.id;
    } else if ('deleteclass' == key) {
    return comment.deleteclass;
    }
    return '';
    };

    var replybox = null;
    var replyUrlParts = null;
    var replyParent = undefined;

    var onReply = function(commentId, domId) {
    if (replybox == null) {
    // lazily cache replybox, and adjust to suit this style:
    replybox = document.getElementById('comment-editor');
    if (replybox != null) {
    replybox.height = '250px';
    replybox.style.display = 'block';
    replyUrlParts = replybox.src.split('#');
    }
    }
    if (replybox && (commentId !== replyParent)) {
    document.getElementById(domId).insertBefore(replybox, null);
    replybox.src = replyUrlParts[0]
    + (commentId ? '&parentID=' + commentId : '')
    + '#' + replyUrlParts[1];
    replyParent = commentId;
    }
    };

    var hash = (window.location.hash || '#').substring(1);
    var startThread, targetComment;
    if (/^comment-form_/.test(hash)) {
    startThread = hash.substring('comment-form_'.length);
    } else if (/^c[0-9]+$/.test(hash)) {
    targetComment = hash.substring(1);
    }

    // Configure commenting API:
    var configJso = {
    'maxDepth': config.maxThreadDepth
    };
    var provider = {
    'id': config.postId,
    'data': items,
    'loadNext': paginator,
    'hasMore': hasMore,
    'getMeta': getMeta,
    'onReply': onReply,
    'rendered': true,
    'initComment': targetComment,
    'initReplyThread': startThread,
    'config': configJso,
    'messages': msgs
    };

    var render = function() {
    if (window.goog && window.goog.comments) {
    var holder = document.getElementById('comment-holder');
    window.goog.comments.render(holder, provider);
    }
    };

    // render now, or queue to render when library loads:
    if (window.goog && window.goog.comments) {
    render();
    } else {
    window.goog = window.goog || {};
    window.goog.comments = window.goog.comments || {};
    window.goog.comments.loadQueue = window.goog.comments.loadQueue || [];
    window.goog.comments.loadQueue.push(render);
    }
    })();
    // ]]>
    </script>
  3. Setelah itu save templates.
Langkah ketiga ini dibuat oleh http://modification-blog.blogspot.com. Setelah Anda melakukan langkah ini fungsi Reply bisa berjalan normal, tapi permasalahan yang saya dapat kemudian (setelah Anda melakukan langkah ini) jika Anda masih memakai browser internet lama terkadang akan susah untuk membuka postingan yang ada pada blog.

Threaded Comment di blog Anda sekarang sudah ada, sekarang anda tinggal modifikasi sendiri bentuk dari kotak komentar. Jika Anda menginginkan kotak komentar Admin berbeda, ikuti langkah sederhana berikut ini (contohnya seperti gambar diatas) :
  1. Pada posisi Edit HTML letakkan kode berikut ini persis diatas kode </body> :
    <script src='http://code.jquery.com/jquery-latest.js'/>
    <script>
    $(function() {
    function highlight(){
    $('.user.blog-author,.ssyby').closest('.comment-block')
    .css('border', '1px solid #e1e1e1')
    .css('background','#f1f1f1 url("https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1kMi1Oaf7kjHhKd5JwotoGg_UKcFQeu3Srs0y0r54R1xCrdVrmE9uV6PLzwCOQbPsrbapJQ3zWgkuM3DAwwns9Yi_SpxUyNNHsHc1ydMvBj3dBC_lm1zjZEY_Qqu98D3x0w8nQ21Wop0/s1600/admin2.png") no-repeat bottom right')
    .css('padding', '10px');
    }
    $(document).bind('ready scroll click', highlight);
    });
    </script>
  2. Kemudian save templates.
Demikian tadi tutorial singkat untuk mengatasi masalah yang sering muncul dalam membuat Threaded Comments pada template blogger classic. Jika masih ada yang kurang jelas silahkan tinggalkan komentar Anda di bawah. Selamat mencoba dan semoga bermanfaat.