Today we are going to get feeds from Twitter, Facebook, Youtube and Flickr all in one place for your website using JSON and the JQuery library:
Be careful on this page with wrapped lines!
Firstly we declare the jquery library in our head section (obviously download it first and change the path to match your system:
<script src="lib/jquery-1.4.2.min.js"></script>
Now we define a div to put all the feeds in:
<div id="l_tweets"><br /><br />Social Networks Update:</div>
Now let’s write some Javascript! We’ll start with Twitter:
<script type="text/javascript">
//twitter - use your own username in the getJSON line
//we'll get the feed and work out how many days ago the content was posted
$.getJSON("http://twitter.com/statuses/user_timeline.json?screen_name=username&include_entities=true&count=5&callback=?",
function(data){
$.each(data, function(i,item){
dp = item.created_at.split(" ");
cr = Date.parse(dp[1]+' '+dp[2]+' '+dp[5]);
tm = (new Date()).getTime();
dy = (tm - cr) / 86400000;
ct = item.text;
ct = ct.replace(/http:\/\/\S+/g,'<a href="$&" target="_blank">$&</a>'); //make urls into links, do the same for hashtags etc:
ct = ct.replace(/\s(@)(\w+)/g,' @<a onclick="javascript:pageTracker._trackPageview(\'/outgoing/twitter.com/\');" href="http://twitter.com/$2" target="_blank">$2</a>');
ct = ct.replace(/\s(#)(\w+)/g,' #<a onclick="javascript:pageTracker._trackPageview(\'/outgoing/search.twitter.com/search?q=%23\');" href="http://search.twitter.com/search?q=%23$2" target="_blank">$2</a>');
//add the feed to the div
$("#l_tweets").append('<div> '+ct+'<br />'+Math.round(dy)+' days ago</div><br />');
}); //each
} //function
); //json
Note that the # and @ replace lines may wrap here, but they should be on one line.
[EDIT – this no longer works for Facebook since they change their authentication methods, please see my new post to get the Facebook feed]
Let’s do the same thing for Facebook now – getting the date into a format that Javascript understands is a little more complicated this time:
//facebook - again use your own username
$.getJSON("http://graph.facebook.com/username/posts?limit=5&callback=?",
function(json){
$.each(json.data, function(i,fb){
if (fb.type=='video' || fb.type=='link') {
if (fb.link) fb.message = '<a href="' + fb.link + '" target="_blank">' + fb.name + '</a>';
else fb.message = '<a href="' + fb.source + '" target="_blank">' + fb.name + '</a>';
}
else fb.message = fb.message.replace(/http:\/\/\S+/g,'<a href="$&" target="_blank">$&</a>');
var d=new Date();
dt1 = fb.created_time.split("T");
dt2 = dt1[0].split("-");
d.setDate(dt2[2]);
d.setFullYear(dt2[0]);
d.setMonth(dt2[1]-1);
cr = Date.parse(d);
tm = (new Date()).getTime();
dy = (tm - cr) / 86400000;
$("#l_tweets").append('<div>' + '' + fb.message + '' + '<br />(' + Math.round(dy) + ' days ago)</div><br />');
}); //each
} //function
); //json
The quotes either side of the fb.message counteract an Internet Explorer problem where content appears as undefined. Now on to Youtube, this is quite similar, but we are throwing images into the mix:
//youtube - as ever, replace your username
$.getJSON('http://gdata.youtube.com/feeds/users/username/uploads?alt=json-in-script&max-results=5&callback=?',
function(data) {
$.each(data.feed.entry, function(i, item) {
var published = item['published']['$t'];
var url = item['media$group']['media$content'][0]['url'];
var media_title = item['media$group']['media$title']['$t'];
var media_descr = item['media$group']['media$description']['$t'];
var thumb = item['media$group']['media$thumbnail'][0]['url'];
var d=new Date();
dt1 = published.split("T");
dt2 = dt1[0].split("-");
d.setDate(dt2[2]);
d.setFullYear(dt2[0]);
d.setMonth(dt2[1]-1);
cr = Date.parse(d);
tm = (new Date()).getTime();
dy = (tm - cr) / 86400000;
//note this next part is all one line
$("#l_tweets").append('<div><a href="' + url + '"><img src="' + thumb + '" width="64" height="36"><br />' + media_title + ' (' + media_descr + ')</a><br />(' + Math.round(dy) + ' days ago)</div><br />');
}); //each
} //function
); //json
Just one more to go – Flickr. A couple of things to note here. Firstly, your user id in the JSON link is not your username, you can map your username to the id here: http://idgettr.com. Secondly, all the other feeds have have a method of limiting results (I have chosen 5 results each so far). For this feed, we must create our own limiter.
//flickr - see the nore above about your user id
var i = 0;
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?id=user_id&lang=en-us&format=json&jsoncallback=?",
function(data){
$.each(data.items, function(i,item){
if (i<5) {
var d=new Date();
dt1 = item.published.split("T");
dt2 = dt1[0].split("-");
d.setDate(dt2[2]);
d.setFullYear(dt2[0]);
d.setMonth(dt2[1]-1);
cr = Date.parse(d);
tm = (new Date()).getTime();
dy = (tm - cr) / 86400000;
//this is all one line again
$("#l_tweets").append('<div><a href="' + item.link + '"><img src="' + item.media.m + '" width="64" height="36"><br />' + item.title + '</a><br />(' + Math.round(dy) + ' days ago)</div><br />');
i++;
} //i
}); //each
} //function
); //json
In the websites I have implemented this on, I haven’t needed to return the feeds in date order (currently they are in order of social network). To order them, this is what I would do:
1) create an array to hold the feeds
2) instead of appending the feeds to the div, add them to the array with days first, then a delimiter, then the feed
(e.g. socnet_updates.push(Math.round(dy)+’_DELIMITER_<div>’+ct+'<br />’+Math.round(dy)+’ days ago</div><br />’);)
3) after the scripts have run, wait a couple of seconds for the data to be filled out (use setTimeout counting the number of feeds returned until you have them all) and the order the array by date (use a natural order algorithm)
4) finally, iterate through the array, split the strings by your delimiter and append the second part to the div
If anyone wants me to show you that code, let me know.
Thanks a lot!
I have been searching the whole day for a script like this one.
Could you please post the code for the view which is sorted by date?
I looked in vain for one, so I had to write it myself.
So to sort by date, instead of appending the info to the div we need to put it in an array so that we can sort it. Also, we don’t know how long it will take to retrieve all the feeds and obviously we have to wait until they are all done until we can sort them, so before anything runs, define 2 arrays:
//define array
var socnet_updates = new Array();
var completed = 0;
Then replace the append lines with a line that adds the feed to that array (putting the date first so that we can sort by date and then some delimiter text so it is easy to remove the date part later), for example:
socnet_updates.push(Math.round(dy)+'DELIMITER_'+ct+''+Math.round(dy)+' days ago');)
At the end of each JSON function increase the number of completed feeds with:
completed++;
Then we need a function to do the ordering, this assumes you have found a natural sort script to do this as normal javascript sorting is not numerical. I can find the one I used if you need me to. So the function checks if all the feeds are done and then sorts and outputs them; if they’re not done it waits half a second and tries again:
//function to output
function doSocNet(socnet_updates) {
if (completed>3) {
socnet_updates.sort(naturalSort);
for(i=0;i<socnet_updates.length;i++) {
exploded = socnet_updates[i].split("DELIMITER_");
$("#l_tweets").append(exploded[1]);
}
}
else setTimeout('doSocNet(socnet_updates)',500);
}
Then finally at the end of all the javascript (or onload), call the function a second after the page loads to give the feeds a chance:
//delay to take loading into account
setTimeout('doSocNet(socnet_updates)',1000);
Does that make sense?
Yes, now it is working perfectly fine.
For anyone who is interested here is a link to my current script:
http://www.cranoxinteractive.com/cranoxsite/templates/cranox20/scripts/socialchannel.js
The next thing I have to do is to change the time display to be dynamic so it show “hours ago” then after 24 hours, “days ago” and after 7 days “weeks ago.
I would put the $completed++; parts at the end of the function (after the each), and count per social network (less confusing if you change your feed options later), but either way you should have two equals signs when testing that variable: if(completed==4).
Oops. I always make the mistake with the two equal signs.
Anyway I also put the completed++; after the each function.
Thanks again!
It looks like Facebook have updated the graph API authentication methods which breaks this code. I’ll read up on the new specs and post an update.
Pingback: Javascript (JQuery): Social networking feeds – new Facebook authentication « Ze Cheesefather's Oracle of Geek
Please see my new post to update the script for the new Facebook authentication methods.