Hack; Related Articles by Labels (revised)  

By Hoctro
This new hack (based on JSON callback technique) makes use of your existing labeling system, as shown here:

The hack in effect with three labels with their belonging titles on the left column:



... because these are the very labels associated with that post:



To install this hack, first follow the instructions from this article Hacking Technique: How To Modify a (Beta) Template, in particular section B.4.


<b:widget id='Blog2' locked='false' title='Blog Posts' type='Blog'>
<b:includable id='comments' var='post'>
</b:includable>
<b:includable id='postQuickEdit' var='post'>
</b:includable>
<b:includable id='main'>
<!-- *****************http://hoctro.blogspot.com*****Jan,2007****************** -->
<!-- *****************Related Articles by Labels - Take Two****************** -->
<!--<b:if cond='data:blog.pageType == "item"'>-->
<div class='widget-content'>
<h2>Related Articles by Labels</h2>
<div id='data2007'/><br/><br/>
<div id='hoctro'>Widget by <u><a href='http://hoctro.blogspot.com'>Hoctro</a>

</u></div>
<script type='text/javascript'>

var homeUrl3 = "hoctro.blogspot.com";
var maxNumberOfPostsPerLabel = 4;
var maxNumberOfLabels = 10;

function listEntries10(json) {
  var ul = document.createElement('ul');
  var maxPosts = (json.feed.entry.length &lt;= maxNumberOfPostsPerLabel) ? 
                 json.feed.entry.length : maxNumberOfPostsPerLabel;
  for (var i = 0; i &lt; maxPosts; i++) {
    var entry = json.feed.entry[i];
    var alturl;

    for (var k = 0; k &lt; entry.link.length; k++) {
      if (entry.link[k].rel == 'alternate') {
        alturl = entry.link[k].href;
        break;
      }
    }
    var li = document.createElement('li');
    var a = document.createElement('a');
    a.href = alturl;

    var txt = document.createTextNode(entry.title.$t);
    a.appendChild(txt);
    li.appendChild(a);
    ul.appendChild(li);
  }

  for (var l = 0; l &lt; json.feed.link.length; l++) {
    if (json.feed.link[l].rel == 'alternate') {
      var raw = json.feed.link[l].href;
      var label = raw.substr(homeUrl3.length+21);
      var k;
      for (k=0; k&lt;20; k++)
       label = label.replace("%20", " ");
      var txt = document.createTextNode(label);
      var h = document.createElement('h4');
      h.appendChild(txt);
      var div1 = document.createElement('div');
      div1.appendChild(h);
      div1.appendChild(ul);
      document.getElementById('data2007').appendChild(div1);
    }
  }
}

function search10(query, label) {

var script = document.createElement('script');
script.setAttribute('src', 'http://' + query + '/feeds/posts/default/-/'
 + label +
'?alt=json-in-script&amp;callback=listEntries10');
script.setAttribute('type', 'text/javascript');
document.documentElement.firstChild.appendChild(script);
}

var labelArray = new Array();
var numLabel = 0;

<b:loop values='data:posts' var='post'>
  <b:loop values='data:post.labels' var='label'>
    textLabel = "<data:label.name/>";
    
    var test = 0;
    for (var i = 0; i &lt; labelArray.length; i++)
       if (labelArray[i] == textLabel) test = 1;
    if (test == 0) { 
       labelArray.push(textLabel);
       var maxLabels = (labelArray.length &lt;= maxNumberOfLabels) ? 
              labelArray.length : maxNumberOfLabels;

       if (numLabel &lt; maxLabels) {
          search10(homeUrl3, textLabel);
          numLabel++;
       }
    }
  </b:loop>
</b:loop>
</script>
</div>
<!--</b:if>--> 
</b:includable>
<b:includable id='backlinkDeleteIcon' var='backlink'>
</b:includable>
<b:includable id='feedLinksBody' var='links'>
</b:includable>
<b:includable id='backlinks' var='post'>
</b:includable>
<b:includable id='status-message'>
</b:includable>
<b:includable id='feedLinks'>
</b:includable>
<b:includable id='nextprev'>
</b:includable>
<b:includable id='commentDeleteIcon' var='comment'>
</b:includable>
<b:includable id='post' var='post'>
</b:includable>
</b:widget>



Then, cut this code below and paste it in between any two "b:widget" tags, save the template, and you're done with the installing part.

To make this hack working, make sure you turn your "feeds" on. This is "on" by default.

Next, replace the bold line with your blog's URL: (var homeUrl3 = "hoctro.blogspot.com";) and you're done, if you're happy with the other default parameters that I will mention shortly.

Important: these are new features, based on suggestions from Khong Co Ai and Elaine. Thank you for your input!

1. If you like this widget to work on item pages only, take out the "<!--" and "-->" (in bold )off this line (located at the front of the widget)

<!--<b:if cond='data:blog.pageType == "item"'>
-->

and those comment on this line, too, in bold:

</script>
</div>
<!--</b:if>--> 
</b:includable>

2. To set the maximum of posts per label, change the number on this line (right now it's 4.)

var maxNumberOfPostsPerLabel = 4;


3. To set the maximum of labels, change the number on this line (right now it's 10.)

var maxNumberOfLabels = 10;

4. To change the title from "Related Articles by Labels", change the text on this line:

<h2>Related Articles by Labels</h2>

5. Per Vivek Sanghi's request, I put in my name as the author of the widget, with a line at the bottom says "Widget by Hoctro". I think this would help spreading the words about my site too. But you have the choice of taking it out or leave it in, either way is fine with me. This is the line, in bold:

<div id='data2007'/><br/><br/>
<div id='hoctro'>Widget by <u><a href='http://hoctro.blogspot.com'>Hoctro</a>

***

Congratulations! Now your related items which share the same labels with your item post are available for your readers.

Notice that this hack still suffers from not being able to work for non-ascii languages.




Technical dicussion:
(not required for installing the hack.)

My hacker friends will notice that there are several things that keep this hack unique:

- I still keep my goal of one step installing for a complicated hack such as this one.

- The use of Blog widget, but cutting off all other template functions, and only use "main includable" to get to the labels. All others are just holders, to make sure they won't be replaced by the default ones from Blogger.

- To get to the labels, two template loops are needed: one for getting to the individual post items, and one to the labels of the item. This hack only works in item page, yet you still need two loops to do that.


- The use of two template loops right inside Javascript code, this is cool that Blogger code allows this mixing of two different kinds of code to happen in one place!!!

...

<b:loop values='data:posts' var='post'>
<b:loop values='data:post.labels' var='label'>
textLabel = "<data:label.name/>";
search10(homeUrl3, textLabel);
</b:loop>
</b:loop>
</script>

...


Cheers,

Hoctro
1/14/07

***
1/15/07: Update: I fix the bug reported by Protesto. Thanks.

1/15/07: Update: the hack is OK now for a long label with multiple words.

1/17/07: Update: Add code to make the hack works on all pages per comment by KCA; and also limit the post titles per label and number of labels shown per comment by Elaine.

1/17/07: Fixed bug of labels not having the right child posts. A new div will make sure the label header and its posts stay in one place.

      var div1 = document.createElement('div');
      div1.appendChild(h);
      div1.appendChild(ul);
      document.getElementById('data2007').appendChild(div1);