不切换到新模板使用Blogger的嵌套回复

Blogger Thread Comments

今天打开Google+,发现Blogger竟然新增了这个无数用户喊了很久的嵌套回复功能,有点意外,之前一直不理不睬的我都以为他们又忘了,而不意外的是,这玩意在我的Blog上没有出现……

其实要让你的模板实现这个功能有个非常简单的方法:直接换个官方的新模板,当然这对于使用非官方模板的人显然有些难以接受……不过我发现要保留原模板的同时使用嵌套回复也是可以的,不过…比较麻烦。

1.更改设置


怀念古老的整页或弹出窗口评论的同学,这次你们又被无视了,你首先需要到设置>帖子和评论里把评论位置改为嵌入才行。我知道这样方便了方校长,但显然这与时代的发展格格不入……当然,@回复也是不错的选择。

2.修改代码


熟悉的模板>修改HTML>继续>扩展窗口小部件模板,然后找到最后一个</b:widget>,在它上面添加以下代码:

<b:includable id='threaded_comments' var='post'>
<b:include name='threaded_comment_css'/>

<div class='comments' id='comments'>
<a name='comments'/>
<h4>
<b:if cond='data:post.numComments == 1'>
1 <data:commentLabel/>:
<b:else/>
<data:post.numComments/> <data:commentLabelPlural/>:
</b:if>
</h4>

<div class='comments-content'>
<b:if cond='data:post.embedCommentForm'>
<b:include data='post' name='threaded_comment_js'/>
</b:if>
<div id='comment-holder'>
<data:post.commentHtml/>
</div>
</div>

<p class='comment-footer'>
<b:if cond='data:post.allowNewComments'>
<b:include data='post' name='threaded-comment-form'/>
<b:else/>
<data:post.noNewCommentsText/>
</b:if>
</p>

<b:if cond='data:showCmtPopup'>
<div id='comment-popup'>
<iframe allowtransparency='true' frameborder='0' id='comment-actions' name='comment-actions' scrolling='no'>
</iframe>
</div>
</b:if>

<div id='backlinks-container'>
<div expr:id='data:widget.instanceId + &quot;_backlinks-container&quot;'>
<b:if cond='data:post.showBacklinks'>
<b:include data='post' name='backlinks'/>
</b:if>
</div>
</div>
</div>
</b:includable>
<b:includable id='threaded-comment-form' var='post'>
<div class='comment-form'>
<a name='comment-form'/>
<b:if cond='data:mobile'>
<p><data:blogCommentMessage/></p>
<data:blogTeamBlogMessage/>
<a expr:href='data:post.commentFormIframeSrc' id='comment-editor-src'/>
<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' frameborder='0' height='410' id='comment-editor' name='comment-editor' src='' style='display: none' width='100%'/>
<b:else/>
<p><data:blogCommentMessage/></p>
<data:blogTeamBlogMessage/>
<a expr:href='data:post.commentFormIframeSrc' id='comment-editor-src'/>
<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' frameborder='0' height='410' id='comment-editor' name='comment-editor' src='' width='100%'/>
</b:if>
<data:post.friendConnectJs/>
<data:post.cmtfpIframe/>
<script type='text/javascript'>
BLOG_CMT_createIframe(&#39;<data:post.appRpcRelayPath/>&#39;, &#39;<data:post.communityId/>&#39;);
</script>
</div>
</b:includable><b:includable id='threaded_comment_css'>
<style>
.comments {
clear: both;
margin-top: 10px;
margin-bottom: 0px;
line-height: 1em;
}
.comments .comments-content {
font-size: 13px;
margin-bottom: 16px;
}
.comments .comment .comment-actions a {
padding-top: 5px;
padding-right: 5px;
}
.comments .comment .comment-actions a:hover {
text-decoration: underline;
}
.comments .comments-content .comment-thread ol {
list-style-type: none;
padding: 0;
text-align: left;
}
.comments .comments-content .inline-thread {
padding: 0.5em 1em;
}
.comments .comments-content .comment-thread {
margin: 8px 0px;
}
.comments .comments-content .comment-thread:empty {
display: none;
}
.comments .comments-content .comment-replies {
margin-top: 1em;
margin-left: 36px;
}
.comments .comments-content .comment {
margin-bottom:16px;
padding-bottom:8px;
}
.comments .comments-content .comment:first-child {
padding-top:16px;
}
.comments .comments-content .comment:last-child {
border-bottom:0;
padding-bottom:0;
}
.comments .comments-content .comment-body {
position:relative;
}
.comments .comments-content .user {
font-style:normal;
font-weight:bold;
}
.comments .comments-content .icon.blog-author {
width: 18px;
height: 18px;
display: inline-block;
margin: 0 0 -4px 6px;
}
.comments .comments-content .datetime {
margin-left:6px;
}
.comments .comments-content .comment-header,
.comments .comments-content .comment-content {
margin:0 0 8px;
}
.comments .comments-content .comment-content {
text-align:justify;
}
.comments .comments-content .owner-actions {
position:absolute;
right:0;
top:0;
}
.comments .comments-replybox {
border: none;
height: 250px;
width: 100%;
}
.comments .comment-replybox-single {
margin-top: 5px;
margin-left: 48px;
}
.comments .comment-replybox-thread {
margin-top: 5px;
}
.comments .comments-content .loadmore a {
display: block;
padding: 10px 16px;
text-align: center;
}
.comments .thread-toggle {
cursor: pointer;
display: inline-block;
}
.comments .continue {
cursor: pointer;
}
.comments .continue a {
display: block;
padding: 0.5em;
font-weight: bold;
}
.comments .comments-content .loadmore {
cursor: pointer;
max-height: 3em;
margin-top: 3em;
}
.comments .comments-content .loadmore.loaded {
max-height: 0px;
opacity: 0;
overflow: hidden;
}
.comments .thread-chrome.thread-collapsed {
display: none;
}
.comments .thread-toggle {
display: inline-block;
}
.comments .thread-toggle .thread-arrow {
display: inline-block;
height: 6px;
width: 7px;
overflow: visible;
margin: 0.3em;
padding-right: 4px;
}
.comments .thread-expanded .thread-arrow {
background: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAG0lEQVR42mNgwAfKy8v/48I4FeA0AacVDFQBAP9wJkE/KhUMAAAAAElFTkSuQmCC&quot;) no-repeat scroll 0 0 transparent;
}
.comments .thread-collapsed .thread-arrow {
background: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAJUlEQVR42mNgAILy8vL/DLgASBKnApgkVgXIkhgKiNKJ005s4gDLbCZBiSxfygAAAABJRU5ErkJggg==&quot;) no-repeat scroll 0 0 transparent;
}
.comments .avatar-image-container {
float: left;
width: 36px;
max-height: 36px;
overflow: hidden;
}
.comments .avatar-image-container img {
width: 36px;
}
.comments .comment-block {
margin-left: 48px;
position: relative;
}

/* Responsive styles. */
@media screen and (max-device-width: 480px) {
.comments .comments-content .comment-replies {
margin-left: 0;
}
}
</style>
</b:includable>
<b:includable id='threaded_comment_js' var='post'>
<script defer='defer' expr:src='data:post.commentSrc' type='text/javascript'/>

<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>
</b:includable>


接着,找到所有的<b:include data='post' name='comments'/>,把它们全部替换成<b:include data='post' name='threaded_comments'/>

3.完成了?


此时,你已经可以在你的Blog上看到嵌套回复了,但是,你之前精心设计的样式也没了……前文所说的麻烦也在于此,为了原来的样式,你只能再重新折腾一番了。

17 comments now

  1. 失败了……看到回复的字眼,不过点了后没有效果……

    回复删除
    回复
    1. 是吗?我在这个模板和之前的一个测试都成功了,我再研究一下看看……

      删除
    2. 不对啊,我在你的Blog上也可以回复啊?

      删除
    3. 可是我怎么按都没有反应啊……太伤心了……T.T

      删除
    4. 不会是你们国家也引进了GFW吧……

      删除
    5. 可是按你的就没问题啊……:(

      删除
    6. 经测试,FF下没问题,可是Chrome下有问题,目前正在寻找方法解决……

      删除
    7. 汗……太汗了……我在另一个部落格测试成功,想来是主部落的功能太多了导致问题了……

      删除
  2. Blogger真是太强大了,现在基本不用折腾都已经很好用。
    后台也改观好多了,好几个月没有进后台,这段时间进去很惊奇

    回复删除
  3. 請問我的BLOG為什麼套用了您的教學仍然無法使用嵌套回覆呢?
    我連模版都換成官方模板了
    http://chcooboo.blogspot.com/

    懇請解答 謝謝

    回复删除
    回复
    1. 你的情况和Han Lin Gan类似,在Firefox下没问题,Chrome就不行,具体原因我也不知道,可能是Plurk或者Twitter还是哪个侧栏导致的吧
      在后台一个一个禁用一下试试看吧

      删除
    2. 原來如此,問題已解決,謝謝您的協助!

      删除
  4. blogger真的越来越强大了,可惜仍然被GFW着,好可惜啊。

    回复删除
  5. 可是我的blog不知道为什么就是不能正常使用这项功能,我可怎么办呀?%>_<%
    我家网址:http://vivrecipe.blogspot.com/

    回复删除
    回复
    1. 楼下这个Vivien是我啦~我刚刚去换了头像哦

      删除
  6. 谢谢~谢谢你的分享~
    我刚刚搞定了我的留言回复功能,超开心的~
    现在2.03凌晨了我才搞定~累哦~
    ⊙﹏⊙b汗

    回复删除