johngirvin.com

John Girvin

This is the blog of John Girvin, a software engineer and web developer based in Belfast, Northern Ireland. He draws on over 14 years of hard won, real world experience of different projects, clients and working environments. Visit the rest of the site to find out more and get in touch.

John is currently working with the Art Technology Group (ATG), developing J2EE based, market leading e-commerce technology.

reading friendfeed with jquery

April 4th, 2009 by John Girvin

FriendFeed is an aggregation service that allows you to gather together your activities on various social media services – such as Facebook, Twitter, digg, delicious and so on – and makes them available in one easily digestible news feed. In Web 2.0 parlance, it builds a “lifestream” of your activities on these other sites, ostensibly so you can share your activities with your equally social media aware friends and colleagues. This stream of updates is made available as a web page, as a RSS feed and, perhaps most interestingly, via a publically accessible API.

On one of my personal sites, Wee Doors Banging, I’ve used this public API to make a sidebar box displaying the latest entries from my FriendFeed stream. It uses the jQuery javascript library to make an AJAX call to the FriendFeed API to retrieve the latest entries from my public feed in JSON format, then insert suitable markup to the page document to display the results.

The main Javascript code is shown below. Wee Doors Banging is a Wordpress powered blog and I needed to make some minor modifications to the theme and configuration in order to integrate the FriendFeed box.

//
// example code to read entries from a user's friendfeed.com public feed
// and insert into the current document, using jQuery AJAX facilities.
//
// see:
//    friendfeed API: http://code.google.com/p/friendfeed-api/wiki/ApiDocumentation
//    jquery        : http://jquery.com/
//
// john girvin, december 2009
// public domain
//
 
// convert rfc3339 formatted date (as returned by friendfeed api) to
// a normal javascript date object
//
// adapted from: http://www.ibm.com/developerworks/library/x-atom2json.html
function rfc3339ToDate(val) {
    var pattern = /^(\d{4})(?:-(\d{2}))?(?:-(\d{2}))?(?:[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d*))?)?([Zz])?(?:([+-])(\d{2}):(\d{2}))?$/;
 
    var m = pattern.exec(val);
    var year = new Number(m[1] ? m[1] : 0);
    var month = new Number(m[2] ? m[2]-1 : 0);
    var day = new Number(m[3] ? m[3] : 0);
    var hour = new Number(m[4] ? m[4] : 0);
    var minute = new Number(m[5] ? m[5] : 0);
    var second = new Number(m[6] ? m[6] : 0);
    var millis = new Number(m[7] ? m[7] : 0);
    var gmt = m[8];
    var dir = m[9];
    var offhour = new Number(m[10] ? m[10] : 0);
    var offmin = new Number(m[11] ? m[11] : 0);
 
    if (dir && offhour && offmin) {
        var offset = ((offhour * 60) + offmin);
        if (dir == "+") {
            minute -= offset;
        } else if (dir == "-") {
            minute += offset;
        }
    }
 
    return new Date(Date.UTC(year, month, day, hour, minute, second, millis));
}
 
// zeropad a number to two digits
function pad(v) {
    if (v < 10) {
        v = "0" + v;
    }
    return v;
}
 
// format a date returned from friendfeed api for display
function formatFriendFeedDate(ffdate) {
    var m = new Array('jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec');
    var d = rfc3339ToDate(ffdate);
    return d.getDate() + ' ' + m[d.getMonth()] + ', ' + pad(d.getHours()) + ':' + pad(d.getMinutes());
}
 
// populate friendfeed container via ajax
jQuery(document).ready(function() {
    // friendfeed: name of user who's feed we want to retrieve
    var usr = 'johngirvin';
    var nam = 'John Girvin';
    // friendfeed: number of entries to retrieve
    var num = 5;
 
    // call friendfeed api
    jQuery.getJSON(
        // construct the fetch url
        'http://friendfeed.com/api/feed/user/' + usr + '?num=' + num + '&amp;callback=?',
 
        // build content from api results
        function(data) {
            // reference container to hold generated content
            var container = jQuery('#friendfeed');
 
            // loop for each friendfeed entry retrieved
            jQuery.each(data.entries, function(i, entry) {
                // ignore entry if it is marked as 'hidden'
                if (entry.hidden != true) {
                    // reference the service details
                    var svc = entry.service;
 
                    // build markup for entry - adapt as you require
                    var t = '';
 
                    t += '<li>';
 
                    t += '<div class="friendfeed_text">';
                    t += '<a href="'+entry.link+'" target="_blank">';
                    t += entry.title;
                    t += '</a>';
 
                    t += '<div class="friendfeed_date">';
                    t += formatFriendFeedDate(entry.published);
                    t += ' via '
 
                    t += '<a title="View '+nam+'\'s profile on '+svc.name+'" href="'+svc.profileUrl+'" target="_blank">';
                    t += svc.name;
                    t += '</a>';
 
                    t += '</div>';
                    t += '</div>';
 
                    t += '</li>';
 
                    // append content to container
                    container.append(t);
                }
            });
        }
    );
});

Notice that I use the full form of the main jQuery variable rather than the more usual $ shortcut. This is necessary when operating in the Wordpress environment, since Wordpress invokes the jQuery.noConflict method to remove the $ shortcut, in order to avoid potential conflicts with other scripts that may be in use.

At line 61, the population of the sidebar is hooked into the document completion event. Lines 62-66 are some simple configuration, then line 69 makes the AJAX call to fetch the entries from FriendFeed. Lines 81-113 are a simple loop over the returned results that builds the HTML markup to display the feed output. I’ll show how this is inserted into the Wordpress output shortly.

One minor problem is that the FriendFeed API returns dates in RFC 3339 format, which Javascript can’t handle directly. The function rfc3339ToDate() is therefore used to convert strings returned in RFC 3339 format to regular Javascript Date objects so that we can go on to process them as required.

In order to incorporate the generated markup with the Wordpress output, two further simple steps are required.

Firstly, the above Javascript code is saved into the Wordpress theme directory as js/friendfeed.js then the theme’s header.php modified to load the script.

Add friendfeed.js to the Wordpress theme

Add friendfeed.js to the Wordpress theme

The following line is added to header.php, in the <head> section, just before the call to wp_head().

<?php wp_enqueue_script('friendfeed', get_bloginfo('template_directory').'/js/friendfeed.js', array('jquery')); ?>

This call to the wp_enqueue_script function ensures that the new script is loaded along with the jQuery library on which it depends. Note the use of the get_bloginfo(‘template_directory’) call to determine the correct path to the script file; using this approach is recommended as it will behave correctly even if theĀ  wp-content directory has been moved or renamed.

Secondly, I add a new Text widget to the Wordpress dynamic sidebar to insert the markup for the container for the Friendfeed entries. To do this, I log into the Wordpress administration area and select the Appearance->Widgets menu option, then, from the Widgets configuration screen, add a new Text widget and drag it to the appropriate position in the Widget stack on the right of the display.

reading-friendfeed-with-jquery-2

Wordpress Widget Configuration (click for larger version)

I click the Edit option on the new Text widget and enter the following HTML:

<ul id="friendfeed"></ul>

The ID attribute is used by the Javascript code above to select the <UL> element that is to contain the generated markup. Any markup scheme may be used, eg: <TABLE>, <DIV>, so long as the Javascript has a way of uniquely identifying where to insert the generated code.

Finally, having entered the required HTML code, I click Done and Save Changes to save the new widget configuration.

That’s all that is required. When viewing the modified blog, I should see something like the following in the sidebar:

reading-friendfeed-with-jquery-3

I imagine there’s a lot that could be done to tidy up or improve the above code, but I’m going to leave any improvements as an exercise for the reader and their imagination.

As an aside, it is possible to display FriendFeed entries from the RSS feed provided by FriendFeed themselves using the standard Wordpress RSS Widget. However I found that the FriendFeed site doesn’t always return results quickly enough for the Widget and, when this happens, the sidebar box is filled with cryptic PHP error messages. This is perhaps not the best experience for readers, so I devised the approach described in this article which does not suffer from the same problem, displaying a blank box if no entries can be retrieved. It has the further advantage of working asyncronusly and not directly slowing down the display of the blog’s pages.

A zip file containing a working example of the code is available here (33Kb), or visit Wee Doors Banging to see it in action, live. Happy hacking.

John Girvin
Bookmark and Share

John Girvin is an experienced a software engineer and web developer based in Belfast, Northern Ireland. He draws on over 14 years of hard won, real world experience of different projects, clients and working environments.

John is currently working with the Art Technology Group (ATG), developing J2EE based, market leading e-commerce technology.

If you liked this article, why not subscribe to the RSS feed for more?

one comment on “reading friendfeed with jquery”

April 5 2009, 10:43 pm

[...] and later . With Tabbed Widgets you can create tab and accordion type blocks of content without reading friendfeed with jquery – johngirvin.com 04/04/2009 FriendFeed is an aggregation service that allows you to gather together [...]

share your thoughts?

design & content © 2008-2010 john girvin, all rights reserved.