We've moved!

TechKnack.blogspot.com has officially moved to TechKnack.net. You should be redirected in 3-5 seconds. Thank you.

January 31, 2008

The JS behind "Most Popular Posts"

Add this post to Del.icio.us. Del.icio.us (0 saved)

Original article: Most Popular Posts list for blogger

In my last article "Most Popular Posts list for blogger," I presented my version of Chris Riley's Analytics API workaround. I also promised to go through the JavaScript for those who were interested :)

The JS

Without further ado, the code:
<div id="popularposts"><noscript>Please enable javascript to view the most popular posts list.</noscript></div> <script type="text/javascript"> <!-- function topcontentCallback(obj) { try { var url,title,output; output='<ul>'; for (i=0; i< obj.count; i++) { url = obj.value.items[i].url; try { title = obj.value.items[i].name[0].content; title = title.replace('<title>', ''); title = title.replace('</title>', ''); title = title.replace('Tech Knack: ', ''); } // if we didn't get the title (bad Pipe!), give a pseudo- // title from the URL catch (e) { title = url.substring(url.lastIndexOf("/")+1, url.lastIndexOf(".html")) .replace(/\-/g, " "); } //remove the <title> tags the pipe leaves in. output+= '<li><a href="'+url+ '" title="'+title+'">'+title+'</a></li>'; } output += '</ul>'; document.getElementById("popularposts").innerHTML = output; } catch (e) { var error = "Error fetching data: "+e; if (e.toString().indexOf('i')!=-1) error += "<br />i: "+i; document.getElementById("popularposts").innerHTML=error; } } //--> </script> <script src="http://pipes.yahoo.com/pipes/pipe.run?_id=bi6F5qPK3BGfvuxf1vC6Jw&_render=json&_callback=topcontentCallback" type="text/javascript"> </script>

The Div

<div id="popularposts"><noscript>Please enable javascript to view the most popular posts list.</noscript></div>
The div with id "popularposts" is the div whose content will be replaced with our list. It initially contains some noscript text for those without JS.

The Function

function topcontentCallback(obj) {
The topcontentCallback function is the function used to handle the JSON output by the Yahoo! Pipe. "obj" is the JSON string passed in by the Pipe.

try { ...... } catch (e) { var error = "Error fetching data: "+e; if (e.toString().indexOf('i')!=-1) error += "<br />i: "+i; document.getElementById("popularposts").innerHTML=error; }
We enclose the main processing code in a try block. Firefox2 and IE6 (and presumably 7 and 8) support try blocks in JS. This way, if there is a problem processing the data (a referrenced node is missing, etc) the user gets a nice little error message rather than a JS error thrown by the browser. In te case of an error, the previously mentioned div's content is set to "Error: ". Not useful to visitors, per se, but good for debugging your script. The "if (e.toString().indexOf('i')!=-1)" part simply appends i's value (from within the try block) to the error message. Again, good for debugging.

var url,title,output; output='<ul>';
Declare some variables, initialize the output variable (we use an unordered list for display).

for (i=0; i< obj.count; i++) { url = obj.value.items[i].url;
We loop over the items given by the Pipe. First we pull the url of the popular page.

try { title = obj.value.items[i].name[0].content; title = title.replace('<title>', ''); title = title.replace('</title>', ''); title = title.replace('Tech Knack: ', ''); } // if we didn't get the title (bad Pipe!), give a pseudo- // title from the URL catch (e) { title = url.substring(url.lastIndexOf("/")+1, url.lastIndexOf(".html")) .replace(/\-/g, " "); } //remove the <title> tags the pipe leaves in.
Here we try to pull the page's title, as pulled by the Pipe. I've noticed that, occasionally, the Pipe will have trouble getting the page's title, and so leaves the title blank, which doesn't play well with our script. Within the try block, I get the content of the title; I then try to replace (remove) the title tags and the site's title. If there is no title text from the Pipe, this will throw an error. In the catch block, we use the page's url to "guess" the title, removing the ".html" at the end using url.substring(), and replacing the intermittent dashes which replace punctuation and spaces with .replace(). These two commands are strung together to be url.substring().replace(). The result: if the article titled "CSS trick - two background images" doesn't have a title attribute in our JSON, the title is given as "css trick two background images". For this reason, you should enable "post pages" in your template's preferences.

output+= '<li><a href="'+url+ '" title="'+title+'">'+title+'</a></li>';
Here we append to our ul an li containing a link to the popular page.

} output += '</ul>'; document.getElementById("popularposts").innerHTML = output;
After the for loop, we add the final </ul> and replace the div's contents.

All this is just a function; without calling it, it is no good.

<script src="http://pipes.yahoo.com/pipes/pipe.run?_id=bi6F5qPK3BGfvuxf1vC6Jw&_render=json&_callback=topcontentCallback" type="text/javascript"> </script>
This imports the JSON created by the Pipe, telling it to render in JSON format (&_render=json) and to call our function to handle the JSON (&_callback=topcontentCallback). If you copy and paste the src to a browser window, you'll see that the content is simply a function call with the JSON as the parameter:
topcontentCallback({"count":7,"value":{"title":"TechKnack".......}});

No comments: