Make Related Post

Copy from Purple Moggy
Copied to NEWS
"If I copy your articles, I give the source to your site"


I first got the idea for this after seeing Hoctro's similar hack. Unfortunately his requires that you change all your post titles to have the same prefix for related articles. I wanted one that would show related posts based on labels. I also wanted to do something with the new JSON format. I also looked at some of the already made hacks from Beautiful Beta to figure out how to parse the JSON properly.

FYI, this probably won't work correctly if your labels use any reserved url characters, like question marks (?) or the slash character (/). I'm not url encoding anything here.

First of all, go to Template -> Edit HTML and paste the following into the page header:
<script type="text/javascript">
//<![CDATA[
var relatedTitles = new Array();
var relatedTitlesNum = 0;
var relatedUrls = new Array();
function related_results_labels(json) {
for (var i = 0; i < json.feed.entry.length; i++) {
var entry = json.feed.entry[i];
relatedTitles[relatedTitlesNum] = entry.title.$t;
for (var k = 0; k < entry.link.length; k++) {
if (entry.link[k].rel == 'alternate') {
relatedUrls[relatedTitlesNum] = entry.link[k].href;
relatedTitlesNum++;
break;
}
}
}
}
function removeRelatedDuplicates() {
var tmp = new Array(0);
var tmp2 = new Array(0);
for(var i = 0; i < relatedUrls.length; i++) {
if(!contains(tmp, relatedUrls[i])) {
tmp.length += 1;
tmp[tmp.length - 1] = relatedUrls[i];
tmp2.length += 1;
tmp2[tmp2.length - 1] = relatedTitles[i];
}
}
relatedTitles = tmp2;
relatedUrls = tmp;
}
function contains(a, e) {
for(var j = 0; j < a.length; j++) if (a[j]==e) return true;
return false;
}
function printRelatedLabels() {
var r = Math.floor((relatedTitles.length - 1) * Math.random());
var i = 0;
document.write('<ul>');
while (i < relatedTitles.length && i < 20) {
document.write('<li><a href="' + relatedUrls[r] + '">' + relatedTitles[r] + '</a></li>');
if (r < relatedTitles.length - 1) {
r++;
} else {
r = 0;
}
i++;
}
document.write('</ul>');
}
//]]>
</script>

Save it, and then click the Expand Widget Template checkbox. Scroll down to the blog1 widget, and find the following:
        <b:if cond='data:post.labels'>
<data:postLabelsLabel/>
<b:loop values='data:post.labels' var='label'>
<a expr:href='data:label.url' rel='tag'><data:label.name/></a><b:if cond='data:label.isLast != "true"'>,</b:if>
</b:loop>
</b:if>

It'll probably be down in the post-footer-line section (whether that be line-1, -2, or -3)

Change that to:
        <b:if cond='data:post.labels'>
<data:postLabelsLabel/>
<b:loop values='data:post.labels' var='label'>
<a expr:href='data:label.url' rel='tag'><data:label.name/></a><b:if cond='data:label.isLast != "true"'>,</b:if>
<b:if cond='data:blog.pageType == "item"'>
<script expr:src='"/feeds/posts/default/-/" + data:label.name + "?alt=json-in-script&amp;callback=related_results_labels&amp;max-results=10"' type='text/javascript'/>
</b:if>

</b:loop>
</b:if>

The 3 lines in bold are what I added ;)

Save it, and now go to Template -> Page Elements and add a new HTML/Javascript widget. I added mine underneath the main blog posts widget. You'll need to add it after (in the page) the above codebox for it to work correctly. Paste the following into it:
<script type="text/javascript">
removeRelatedDuplicates();
printRelatedLabels();
</script>

Now go back to Template -> Edit HTML, check the checkbox to expand the template code, and find the HTML/Javascript widget you just added. It'll look something like the following. Add the lines in bold:
<b:widget id='HTML13' locked='false' title='Related Posts' type='HTML'>
<b:includable id='main'>
<b:if cond='data:blog.pageType == "item"'>
<!-- only display title if it's non-empty -->
<b:if cond='data:title != ""'>
<h2 class='title'><data:title/></h2>
</b:if>
<div class='widget-content'>
<data:content/>
</div>

<b:include name='quickedit'/>
</b:if>
</b:includable>
</b:widget>


There's a few numbers you can tweak to show more or less related posts. In the first codebox there's a part that says i < 20 and the 3rd codebox has a part that says max-results=10. You can play around with these numbers if you want. After playing around a little these numbers seem to give a good trade-off between the speed of page-load and the number of related posts displayed.

0 comments: