A Reddit widget using jQuery and JSONP
A very important part of the experience of reading blogs is the ability to see other people’s opinions on the subject, which in many cases turn out to be more insightful than the post itself. Also, social news sites like Reddit or Hacker News tend to generate discussions that engage many more users than traditional blog comments do, and it’s important to make it easier for readers to access them.
When creating this blog, I checked whether Reddit provides a way of embedding information about the submissions for an URL inside a page, such as the number of comments, a link to the actual submission and, of lesser importance, the number of upvotes. Unfortunately, while they do have both a button widget and a submission list widget, neither of them are very customizable nor do they display exactly what I wanted, so I decided to make something myself. The end result looks something like this:

Reddit API to the rescue!
Reddit has been exposing a pretty good RESTful API for quite some time now, and fortunately, about two months ago, they also added support for JSONP. What that means is that their API can now be used directly from the browser using standard XmlHttpRequests. The docs can be found here: http://code.reddit.com/wiki/API .
Luckily, the functionality I want requires a single API call: http://reddit.com/api/info.json?url=URL . Here’s what it returns when asked about microsoft.com:
{ "data" : {
"after" : null,
"before" : null,
"children" : [ {
"data" : {
"id" : "a1ql9",
"num_comments" : 2,
"permalink" : "/r/programming/comments/a1ql9/developer/",
"subreddit" : "programming",
"subreddit_id" : "t5_2fwo",
"title" : "developer",
"ups" : 2,
"downs" : 9,
"url" : "http://www.microsoft.com",
..............
},
"kind" : "t3"
},
............
] } } }
The children field’s value is a list containing an entry for each submission of the specified URL on Reddit. I’ll assume that my posts will not be submitted to Reddit multiple times and just use the first element.
Creating the widget
Ideally, a widget such as this would not depend on any JavaScript libraries, since it should be easy to include it in any page, but since this is only more of a demo I decided to use jQuery anyway. It also doesn’t hurt that the Tumblr theme I’m using already includes it.
The nice thing about using jQuery is that it already has built-in support for JSONP. The $.ajax function can handle the creation of the <script> element, as well as managing the callback function. Here’s what a call to the above API URL looks like:
$.ajax({
url: "http://www.reddit.com/api/info.json?url=" +
encodeURI(location.href),
jsonp: "jsonp",
dataType: "jsonp",
success: function(json) {
console.log(json);
}
});
The jsonp: "jsonp" option tells jQuery that the callback parameter (which contains the name of the callback function) is called “jsonp”.
To render the JSON received from Reddit, I wrote a small function that takes a string of HTML and an object, and replaces fields of the form $propertyName with properties from an object:
function replaceFields(html, data) {
for(var prop in data) {
html = html.replace("$" + prop, data[prop]);
}
return html;
};
You could call this function “the poor man’s template engine”. This will be called with the first submission found in the JSON returned by Reddit (i.e. json.data.children[0].data).
Putting it all together
The final widget combines the two above bits of JavaScript with a bit of glue code:
function loadRedditInfo(target) {
function replaceFields(html, data) {
for(var prop in data) {
html = html.replace("$" + prop, data[prop]);
}
return html;
};
function processResponse(json) {
if(json.kind != "Listing" ||
json.data.children.size == 0) {
// don't show anything if this url hasn't been
// submitted to reddit
return;
}
// we only care about the first entry
var entry = json.data.children[0].data;
target = $(target);
target.html(replaceFields(target.html(), entry));
target.show();
};
$.ajax({
url: "http://www.reddit.com/api/info.json?url=" +
encodeURI(location.href),
jsonp: "jsonp",
dataType: "jsonp",
// the try/catch is ugly, but somewhat necessary in case
// Reddit is down or they change their API
success: function(json) {
try { processResponse(json); }
catch(e) { };
}
});
};
$(function() { loadRedditInfo("#reddit-info-widget"); });
This can be added to a <script> element anywhere on the page (of course, after jQuery).
Here’s an example of an HTML template which can be used together with the above unction that displays the number of upvotes and comments, as well as providing a link to the reddit submission page:
<div id="reddit-info-widget" style="display: none"> This post has gathered $ups upvotes and <a class='comments' href='http://reddit.com$permalink'>
$num_comments comments
</a>
on Reddit!
</div>
Note how the HTML above contains the $ups, $permalink and $num_comments fields. These will get replaced with the number of upvotes, link to the submission and number of comments respectively.
To view how this script and html template render together, visit this page.
The code is also available on GitHub.