bX- NicoNico

Custom threaded comments in Blogger

Publication date: February 9th / 2012.
Last update: March 13th / 2017.

Blogger started the year introducing a new threaded comment system that let natively add replies to individual comments.
More of half-dozen of problems appeared after the release of the feature, but now all them are fixed.

Comentarios Anidados de Blogger Personalizados

The new system generates the comments via Javascript, and even when Googlebot can execute some Ajax and Javascript instructions for indexing, it is preferable that the server (in this case Blogger) generates the comments's content and be sure that them will be indexed.

Comments adds value and content to a blog, so I decided to adjust the system in order that Blogger generates directly the content, and additionally being able to customize it as I want, keeping old hacks such as emoticons, numbering, highlight author's comments, relative dates, among others.

This new system utilize a new Blogger data tag named data:comment.inReplyTo that returns the ID of the parent comment (if exists), and uses Blogger's loops to show the replies to a comment.


» Opening remarks
  1. Back-up your blog template.
  2. It's not necessary that blog's feed is set to "Full", it can be "Short" or "Until jump break".
  3. Currently with the "classic comments" the pagination is not working. Until Blogger Team fix this issue, I recommend to fix it by ourselves.
» Step by step

1. Go to Edit HTML - Expand Widget Template and search for this code, adding what is in blue.

<b:includable id='comment-form' var='post'>
  <div class='comment-form' id='comment-form-thread'>

  ...we leave this code intact...

  </div>
</b:includable>

2. Search for the loop that generates the comments,

<b:loop values='data:post.comments' var='comment'>
 ......
</b:loop>

And add the code that is highlighted in blue (note that you just have to add a code just after the loop opening and other just before it closing, the rest of the current code is left intact)

<b:loop values='data:post.comments' var='comment'> <b:if cond='data:comment.inReplyTo'> <!--FIX--> <b:else/> ... here comes the current code ... that is in the template ... that generates the comments ... and what we won't touch <div class='replies-container'> <b:loop values='data:post.comments' var='childComment'> <b:if cond='data:childComment.inReplyTo == data:comment.id'> <div class='comment-replies' expr:id='data:childComment.id'> <div expr:class='&quot;comment-author-thread &quot; + data:childComment.authorClass' expr:id='data:childComment.anchorName'> <b:if cond='data:childComment.favicon'> <img expr:src='data:childComment.favicon' height='16px' style='margin-bottom:-2px;' width='16px'/> </b:if> <a expr:name='data:childComment.anchorName'/> <b:if cond='data:blog.enabledCommentProfileImages'> <data:childComment.authorAvatarImage/> </b:if> </div> <div class='reply-to'> <b:if cond='data:childComment.authorUrl'> <a expr:href='data:childComment.authorUrl' rel='nofollow'><data:childComment.author/></a> <b:else/> <data:childComment.author/> </b:if> replied... <div class='comment-body-thread'> <b:if cond='data:childComment.isDeleted'> <span class='deleted-comment'><data:childComment.body/></span> <b:else/> <p><data:childComment.body/></p> </b:if> </div> <div class='comment-footer-thread'> <span class='comment-timestamp'> <a expr:href='data:childComment.url' title='Comment permalink'> <data:childComment.timestamp/> </a> <b:include data='childComment' name='commentDeleteIcon'/> </span> </div> </div> </div> </b:if> </b:loop> </div> <b:if cond='data:post.allowNewComments'> <b:if cond='data:post.numComments &lt; 200'> <a class='reply-action' expr:onclick='&quot;reply(&apos;&quot; + data:comment.id + &quot;&apos;);return false;&quot;' href='#'>Reply</a><br/> <b:else/> <script type='text/javascript'> var indexc = &#39;<data:post.numComments/>&#39; var indexcomment = &#39;<data:comment.id/>&#39; //<![CDATA[ var indexpage = indexc/200; indexpage = Math.ceil(indexpage); var indexl = window.location.href; indexl = indexl.indexOf("commentPage=" + indexpage + ""); var replyAction = "<a class='reply-action' onclick='reply(&quot;" + indexcomment + "&quot;);return false;' href='#'>Reply</a><br/>"; if(indexl!=-1)if(indexc<indexpage*200)document.write(replyAction); //]]> </script> </b:if> <div class='contenedorreply' expr:id='&quot;contenedorreply-&quot; + data:comment.id'/> </b:if> </b:if> </b:loop>


The text in red "replied..." can be customized, or even deleted.

3. Add the following code just after <b:includable id='comments' var='post'>

<b:if cond='data:blog.pageType == &quot;item&quot;'> <script type='text/javascript'>var flagItem = 0;</script> </b:if> <b:if cond='data:blog.pageType == &quot;static_page&quot;'> <script type='text/javascript'>var flagItem = 1;</script> </b:if> <script type='text/javascript'> /* Code under Creative Commons License 3.0 (Attribution-Non Comercial) Felipe @ http://gplus.to/iFelipeCalvo */ var indexa = &#39;<data:top.id/>&#39;; var indexb = &#39;<data:post.id/>&#39;; //<![CDATA[ // Differentiate between a post or a static page flagItem="0"==flagItem?"&postID=":"&pageID="; function replyOriginal() { // Set Iframe colors var b = document.getElementById("comment-editor").getAttribute("src"), a = b.indexOf("#"), b = b.substring(a), a = document.getElementById("comment-editor"); // Deletes the prev Iframe and the "add a comment" link a.parentNode.removeChild(a); a = document.getElementById("replypost"); a.parentNode.removeChild(a); // Set the new Iframe params and generates it b = "https://www.blogger.com/comment-iframe.g?blogID=" + (indexa + flagItem + indexb + b) + ""; a = document.createElement("iframe"); a.setAttribute("id", "comment-editor"); a.setAttribute("name", "comment-editor"); a.setAttribute("src", b); a.setAttribute("height", "250px"); a.setAttribute("width", "100%"); a.setAttribute("frameBorder", "0"); a.setAttribute("allowtransparency", "true"); document.getElementById("comment-form-thread").appendChild(a) } function reply(b) { // Set iframe colors var a = document.getElementById("comment-editor").getAttribute("src"), c = a.indexOf("#"), a = a.substring(c), c = document.getElementById("comment-editor"); // Deletes the prev Iframe c.parentNode.removeChild(c); // Set the new Iframe params and generates it a = "https://www.blogger.com/comment-iframe.g?blogID=" + (indexa + flagItem + indexb) + "&parentID=" + (b + a) + ""; c = document.createElement("iframe"); c.setAttribute("id", "comment-editor"); c.setAttribute("name", "comment-editor"); c.setAttribute("src", a); c.setAttribute("height", "250px"); c.setAttribute("width", "100%"); c.setAttribute("frameBorder", "0"); c.setAttribute("allowtransparency", "true"); document.getElementById("contenedorreply-" + b + "").appendChild(c); // Creates a "add a comment" link document.getElementById("replypost") || (b = document.createElement("a"), b.innerHTML = "Add a comment", b.setAttribute("id", "replypost"), b.setAttribute("href", "javascript:void(0)"), b.setAttribute("class", "LoadMore"), document.getElementById("comment-form-thread").appendChild(b)); var clickOn = document.getElementById("replypost"); clickOn.addEventListener ? clickOn.addEventListener("click", replyOriginal, !1) : clickOn.attachEvent("onclick", replyOriginal); } //]]> </script>


Value in red of 250px refers to Iframe's height and can be customized to taste.

4. Finally we add some styles for the threaded comments:

.comment-replies {margin:1.3em 0;line-height: 1.2em;padding: 12px;} .comment-author-thread {float:left;} #comments .replies-container .avatar-image-container {position:static;} .replies-container {margin-left:50px;} .comment-body-thread {padding:0.5em 0;margin-bottom:0.4em;} .comment-body-thread p {margin:0;word-wrap: break-word;} .comment-footer {margin: 0.5em 25px 1em;} .reply-action {display:block;font-weight:bold;} #comment-editor {border:0;}


This new setup lets us keeping customizing the way the comments are displayed, both first and second level comments, eliminates the restrictions of Blogger's initial system, like display the comments within <blockquote> tags and the date next to the comment author name, and lets adjust more easily the old hacks for comments.

The most remarkable is that all the content of the comments section is generated by the own Blogger server securing their indexing, in addition that the comments load more faster and hence the whole page.

You can test this new system right here right now, or also in my blog. (◠‿◠)

28 comments :

Felipe said...

There are 10 types of people in the world - those who know binary and those who have friends :(

Responder
Syndicate OS said...

test :)

Responder
Boho Vanity said...

you are a genius- i have been searching for this exact way to insert the 'reply' button for hours. thank you so so so much!

www.bohovanity.com

Responder
Võ Quốc An said...

test comments :)

Responder
laurice-with-love said...

Hi! Where do we add this code:

.comment-replies {margin:1.3em 0;line-height: 1.2em;padding: 12px;}
.comment-author-thread {float:left;}
#comments .replies-container .avatar-image-container {position:static;}
.replies-container {margin-left:50px;}
.comment-body-thread {padding:0.5em 0;margin-bottom:0.4em;}
.comment-body-thread p {margin:0;word-wrap: break-word;}
.comment-footer {margin: 0.5em 25px 1em;}
.reply-action {display:block;font-weight:bold;}
#comment-editor {border:0;}

Felipe Calvo replied...

Just before </b:skin> tag or within <style> tags.

Responder
Ahmad Alqurniawan said...

Test

Responder
Alan Singgih said...

test :)

Responder
Damar Zaky said...

Hi Bx nico nico, can you make the blogger comment form without iframe?, i mean like using google drive, just embed a form src :)
thx

Felipe Calvo replied...

It's not possible Damar Zaky (keeping the comments in Blogger internal database) unless you save the comments in a Google Drive spreadsheet serving as a database.

Responder
randy yang penting share said...

testo to the threado comentato :)

Responder
Felipe Calvo said...

Comments for this post are now closed.

Responder