A simple Twitter widget

Wednesday, 25 May 2011

This blog’s sidebar displays my latest Twitter update. I did this manually instead of using a plugin because I couldn’t find a lightweight plugin that did what I want, and I thought it would be a quick and simple project. So here’s how I did it.

My Twitter widget is written purely in HTML and JavaScript. This means that I can simply put the code into a WordPress Text widget. I don’t have to edit my theme or write a plugin.

Initially I got the code for the widget straight from the Twitter website. There was a section where you could copy a little bit of HTML to paste into your site (or in a Text widget). This was great because the code was structured to be easily modifiable. They’ve changed to a more opaque implementation now, but they still serve the old scripts from their site. I’ve used these, plus an undocumented feature of the Twitter API, to make my own little Twitter widget.

Here’s the code, with interesting bits highlighted:

<div id="twitter_div">
<ul id="twitter_update_list"></ul>
<div><a href="http://www.twitter.com/bnnt"><img alt="Follow bnnt on Twitter" src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png"></a></div>
</div>
<script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script>
<script type="text/javascript">
function twitterCallback2_filtered(timeline) {
	// Try to select a non-reply
	var select = 0, i;
	for (i = 0; i &lt; timeline.length; ++i) {
		if (timeline[i].text.charAt(0) != '@') {
			select = i;
			break;
		}
	}
	var status = timeline[select];
	// Edit the status
	status.text = status.text.replace(/ #(?:yam|fb|in)\b/g, '');
	twitterCallback2([status]);
}
</script>
<script type="text/javascript" src="http://api.twitter.com/1/statuses/user_timeline.json?screen_name=bnnt&amp;count=5&amp;include_rts=true&amp;callback=twitterCallback2_filtered"></script>

Here’s a breakdown of the code.

The “Follow me on Twitter” button is taken straight from Twitter’s Follow Buttons page.

<a href="http://www.twitter.com/bnnt">
<img alt="Follow bnnt on Twitter" 
src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png">
</a>

Then the little formatting script Twitter have thoughtfully provided. It contains a function called twitterCallback2, which formats an array of tweets and writes them into a div with ID twitter_update_list.

<script type="text/javascript" 
src="http://twitter.com/javascripts/blogger.js">
</script>

Twitter no longer seem to link to this script from their site, but it’s still there if you know where to look. I suppose thousands of sites will break if they ever remove this. It’s pretty simple – at some point I will write my own even simpler one and ditch theirs.

At first I simply used the above script for my Twitter widget. But then I wanted to make a couple of changes. So I wrote a little filter which would tweak the returned tweets and then pass the result to the twitterCallback2 function.

function twitterCallback2_filtered(timeline) {

First, I wanted to avoid displaying @replies, since they usually make no sense without context. For example: @DavidPlumpton “They also serve who only stand and look out of the window” (apologies to Milton). (Actually, that doesn’t make much sense even with the context.)

To do this, I set the API call to fetch the last 5 tweets instead of the last one. Then I search through until I find one that isn’t an @reply. If they’re all @replies then I just give up and take the first one.

	// Try to select a non-reply
	var select = 0, i;
	for (i = 0; i &lt; timeline.length; ++i) {
		if (timeline[i].text.charAt(0) != '@') {
			select = i;
			break;
		}
	}
	var status = timeline[select];

I also wanted to filter out “control” hashtags that have nothing to do with the tweet. For example, the hashtag #in in a tweet will cross-post the tweet to my LinkedIn account. I don’t need this to show up in the widget. Likewise for #fb (Facebook) and #yam (Yammer).

	// Edit the status
	status.text = status.text.replace(/ #(?:yam|fb|in)\b/g, '');
	twitterCallback2([status]);
}

The last line of the function calls twitterCallback2 to render the tweet.

The last piece of the puzzle is the Twitter REST API call that actually fetches the tweets. I call user_timeline with the undocumented callback parameter to turn the response into JSONP and call my twitterCallback2_filtered function. (To use the raw JSON result I would have to contend with the same-origin policy, which would complicate things considerably.)

<script type="text/javascript" 
src="http://api.twitter.com/1/statuses/user_timeline.json?
screen_name=bnnt&amp;count=5&amp;include_rts=true&
amp;callback=twitterCallback2_filtered"></script>

As I mentioned, the final step is to paste the code into a Text widget in my WordPress Admin screens. If you want to use this too, just change the two occurrences of “bnnt” to your own Twitter handle (unless you want to display my tweets on your blog).

Tags: , ,

4 comments

You can leave a comment, or trackback from your own site.

  1. a demo would be nice…

  2. @dan, have a look at the top right of this page!

  3. This is great! But can’t seem to get it to display more than one tweet. I notice the one on your page only shows one, rather than five. Is that deliberate? Ben.

  4. @Ben it is deliberate! I fetch 5 tweets, search through them to find one that isn’t a reply, and display that. It wouldn’t be hard to make it display more than one. In fact, try changing twitterCallback2_filtered as follows:

    
    // Try to select non-replies
    var statuses = [], i;
    for (i = 0; i < timeline.length; ++i) {
    	if (timeline[i].text.charAt(0) != '@') {
    		statuses.push(timeline[i]);
    	}
    }
    if (statuses.length == 0) {
    	statuses = timeline;
    }
    // Edit the statuses
    for (i = 0; i < statuses.length; ++i) {
    	statuses[i].text = statuses[i].text.replace(/ #(?:yam|fb|in)\b/g, '');
    }
    twitterCallback2(statuses);
    

    I haven’t tested this, but it should display the last 5 tweets, with replies filtered out (so it might actually display fewer than 5). If all 5 most recent tweets are repies, then it will display them all.

Leave a comment