Making a Custom Facebook Wall with jQuery Templates

Making a Custom Facebook Wall with jQuery Templates

In this tutorial, we are going to create our own version of Facebook’s wall. We will be using Facebook’s Graph API with jQuery, and the template plugin. The jQuery.tmpl plugin will allow us to define templates within our page, and convert the posts we’ve obtained from the API into a real HTML page.

You can use today’s example to display a feed of the latest posts on your FB page or profile on your website.

Before we begin, lets say a few words about the Facebook API.

Update on June 19th, 2011: Recently Facebook introduced some changes to their API that broke this script. They now require that you use an access token in order to fetch the page feed, used by this example. The last section of this tutorial explains how to obtain such an access token.

The Graph API

The Graph is Facebook’s solution to providing an interface to every object that exists in the site, along with its connections to other objects. Every page that you see on the site has a corresponding graph representation, be it a user, photo, group, status update or anything else. The API also supports JSONP requests, which makes it really easy to use with jQuery.

We will be using two API datapoints – one for selecting the latest posts, and the other for selecting the full name and avatar of the page. You can see sample responses below:

http://graph.facebook.com/smashmag/posts/

{
    "data": [{
        "id": "45576747489_10150136051797490",
        "from": {
            "name": "Smashing Magazine",
            "category": "Website",
            "id": "45576747489"
        },
        "message": "Creating a sphere with 3D CSS",
        "picture": "http://platform.ak.fbcdn..",
        "link": "http://bit.ly/epqBBv",
        "name": "Creating a sphere with 3D CSS \u2013 Paul Hayes",
        "caption": "www.paulrhayes.com",
        "description": "A professional slice of newly..",
        "icon": "http://photos-d.ak.fbcdn.net/photos..",
        "actions": [{
            "name": "Share",
            "link": "http://www.facebook.com/share.."
        }],
        "type": "link",
        "application": {
            "name": "Sendible",
            "id": "26065877776"
        },
        "created_time": 1301325483,
        "updated_time": 1301325483,
        "likes": {
            "data": [{
                "name": "Zome Lia",
                "id": "100000643422735"
            }],
            "count": 16
        }
    }]
}

The JSON response above contains information on every one of the posts published by Smashing Magazine. Some of the fields contain data about the creation/modification date, number of likes and comments, title and description, and a type. This request could return status updates, shared links, uploaded photos and videos, and more.

We also need to make an additional request so we can obtain the avatar, associated with the page (it is not contained in the post responses):

http://graph.facebook.com/smashmag/

{
    "id": "45576747489",
    "name": "Smashing Magazine",
    "picture": "http://profile.ak.fbcdn.net/hp..",
    "link": "http://www.facebook.com/smashmag",
    "category": "Website",
    "likes": 42696,
    "website": "http://www.smashingmagazine.com/",
    "username": "smashmag",
    "company_overview": "Founded in September 2006..",
    "mission": "The offical Smashing Magazine pa..!",
    "products": "Looking for a web design job? Che.."
}

The picture field above gives us what we need. It is a bit of a waste to request so much data, so in the plugin we are actually limiting the returned fields to only what we need.

Custom Facebook Wall with jQuery

Custom Facebook Wall with jQuery

The Templates

Now lets say a few words about the jQuery templates. As the Graph API returns valid JSON data, it is a great candidate to experiment with jQuery’s template plugin. This official plugin enables us to define HTML building blocks with an easy to use markup. This saves us from having to manually create HTML elements, concatenate strings and escape character sequences.

The templates themselves may be inserted inline in a special script tag, or can be received via an AJAX call from a separate file. In this tutorial, I’ve chosen the first approach as it is simple and straightforward.

Each template has the following form:

<script id="someID" type="text/x-jquery-tmpl">
<!-- HTML markup coupled with template tags -->
</script>

This is a script tag which, because of the type attribute, is not recognized by the browser, so it is not evaluated nor shown. What is more, its content is treated as character data and is not parsed, which is perfect for the task of holding our templates. We can then use jQuery’s tmpl() method and render it into actual HTML markup (more on that in a moment).

Here is the first template, which creates the heading of the page:

<script id="headingTpl" type="text/x-jquery-tmpl">
<h1>${name}<span>on Facebook</span></h1>
</script>

The ${} template tag gets replaced with the value of the name property of the object, that is passed to the tmpl() method, which in our case is the name of the facebook page.

For a complete list of template tags and methods, read through the jQuery Template documentation.

The other template, which displays the individual posts is a bit more complex and employs some of the more advanced templating features:

<script id="feedTpl" type="text/x-jquery-tmpl">
<li>
	<img src="${from.picture}" />

	<div>
		<h2><a href="http://www.facebook.com/profile.php?id=${from.id}" target="_blank">${from.name}</a></h2>
		<p>{{html message}}</p>
		{{if type == "link" }}
			<div>
				{{if picture}}
					<img src="${picture}" />
				{{/if}}
				<div>
					<p><a href="${link}" target="_blank">${name}</a></p>
					<p>${caption}</p>
					<p>${description}</p>
				</div>
			</div>
		{{/if}}
	</div>

	<p>${created_time} ·
	{{if comments}}
		${comments.count} Comment{{if comments.count>1}}s{{/if}}
	{{else}}
		0 Comments
	{{/if}} ·
	{{if likes}}
		${likes.count} Like{{if likes.count>1}}s{{/if}}
	{{else}}
		0 Likes
	{{/if}}
	</p>

</li>
</script>

Inside the template tags we can have any JavaScript expressions, even method and function calls. This is especially helpful when building the {{if}} statements, as you can see from the code above, where we check the number of likes and comments.

One feature of the ${} tag is that it escapes the textual value before inserting it into the template. However in some cases this is not what you need. For example the message variable holds HTML code that we want to display as is. This is why we use the {{html}} tag instead, which preserves the original format of the code.

And here is the HTML document we end up with:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Making a Custom Facebook Wall with jQuery | Tutorialzine Demo</title>
<link rel="stylesheet" type="text/css" href="css/styles.css" />

</head>
<body>

<div id="page">

	<div id="wall"></div>

</div>

<!-- jQuery templates. Not rendered by the browser. Notice the type attributes -->

<script id="headingTpl" type="text/x-jquery-tmpl">
<h1>${name}<span>on Facebook</span></h1>
</script>

<script id="feedTpl" type="text/x-jquery-tmpl">
<li>
	<img src="${from.picture}" class="avatar" />

	<div class="status">
		<h2><a href="http://www.facebook.com/profile.php?id=${from.id}" target="_blank">${from.name}</a></h2>
		<p class="message">{{html message}}</p>
		{{if type == "link" }}
			<div class="attachment">
				{{if picture}}
					<img class="picture" src="${picture}" />
				{{/if}}
				<div class="attachment-data">
					<p class="name"><a href="${link}" target="_blank">${name}</a></p>
					<p class="caption">${caption}</p>
					<p class="description">${description}</p>
				</div>
			</div>
		{{/if}}
	</div>

	<p class="meta">${created_time} ·
	{{if comments}}
		${comments.count} Comment{{if comments.count>1}}s{{/if}}
	{{else}}
		0 Comments
	{{/if}} ·
	{{if likes}}
		${likes.count} Like{{if likes.count>1}}s{{/if}}
	{{else}}
		0 Likes
	{{/if}}
	</p>

</li>
</script>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script src="js/jquery.tmpl.min.js"></script>
<script src="js/script.js"></script>

</body>
</html>

The #wall div is going to be dynamically populated with the Graph API data, after it has been rendered using our templates. You can see the templates themselves at the bottom of the file. Before the closing body tag, I have included the jQuery library, the jQuery.tmpl plugin, and our script.js file, which we will be discussing next.

jQuery Code

As we have all the pieces in place, we can finally get down to writing our facebook wall plugin.

script.js

// Creating our plugin.

(function($){

	$.fn.facebookWall = function(options){

		options = options || {};

		if(!options.id){
			throw new Error('You need to provide an user/page id!');
		}

		// Default options of the plugin:

		options = $.extend({
			limit: 15	// You can also pass a custom limit as a parameter.
		},options);

		// Putting together the Facebook Graph API URLs:

		var graphUSER = 'http://graph.facebook.com/'+options.id+'/?fields=name,picture&callback=?',
			graphPOSTS = 'http://graph.facebook.com/'+options.id+'/posts/?callback=?&date_format=U&limit='+options.limit;

		var wall = this;

		$.when($.getJSON(graphUSER),$.getJSON(graphPOSTS)).done(function(user,posts){

			// user[0] contains information about the user (name and picture);
			// posts[0].data is an array with wall posts;

			var fb = {
				user : user[0],
				posts : []
			};

			$.each(posts[0].data,function(){

				// We only show links and statuses from the posts feed:
				if(this.type != 'link' && this.type!='status'){
					return true;
				}

				// Copying the user avatar to each post, so it is
				// easier to generate the templates:
				this.from.picture = fb.user.picture.data.url;

				// Converting the created_time (a UNIX timestamp) to
				// a relative time offset (e.g. 5 minutes ago):
				this.created_time = relativeTime(this.created_time*1000);

				// Converting URL strings to actual hyperlinks:
				this.message = urlHyperlinks(this.message);

				fb.posts.push(this);
			});

			// Rendering the templates:
			$('#headingTpl').tmpl(fb.user).appendTo(wall);

			// Creating an unordered list for the posts:
			var ul = $('<ul>').appendTo(wall);

			// Generating the feed template and appending:
			$('#feedTpl').tmpl(fb.posts).appendTo(ul);
		});

		return this;

	};

	// Helper functions:

	function urlHyperlinks(str){
		return str.replace(/\b((http|https):\/\/\S+)/g,'<a href="$1" target="_blank">$1</a>');
	}

	function relativeTime(time){

		// Adapted from James Herdman's http://bit.ly/e5Jnxe

		var period = new Date(time);
		var delta = new Date() - period;

		if (delta <= 10000) {	// Less than 10 seconds ago
			return 'Just now';
		}

		var units = null;

		var conversions = {
			millisecond: 1,		// ms -> ms
			second: 1000,		// ms -> sec
			minute: 60,			// sec -> min
			hour: 60,			// min -> hour
			day: 24,			// hour -> day
			month: 30,			// day -> month (roughly)
			year: 12			// month -> year
		};

		for (var key in conversions) {
			if (delta < conversions[key]) {
				break;
			}
			else {
				units = key;
				delta = delta / conversions[key];
			}
		}

		// Pluralize if necessary:

		delta = Math.floor(delta);
		if (delta !== 1) { units += 's'; }
		return [delta, units, "ago"].join(' ');

	}

})(jQuery);

We are using the $.getJSON functions to request information from the Graph API. But you may notice that we are not using it as we have in previous tutorials, namely by providing a callback function as its second parameter. This is because we want both calls to the Graph API to be run in the same time (speed all the way), which is not possible with a simple callback.

As of jQuery 1.5, all AJAX methods return a deferred object, which basically allows us to group a number of AJAX calls in a $.when(). After both of the AJAX requests complete successfully, the done method is executed once.

After this, we can simply render the templates:

// Rendering the templates:
$('#headingTpl').tmpl(fb.user).appendTo(wall);

// Creating an unordered list for the posts:
var ul = $('<ul>').appendTo(wall);

// Generating the feed template and appending:
$('#feedTpl').tmpl(fb.posts).appendTo(ul);

The tmpl() method takes a JavaScript object or array, and renders the template once per each element. The templates are specified by their ids (the #headingTpl and #feedTpl script elements in our case).

Finally we only have to call the plugin in document.ready with the ID of your page, and your access token (more on this in a moment):

$(document).ready(function(){

	// Calling our plugin with a page id:
	$('#wall').facebookWall({
		id:'smashmag',
		access_token:'19304297594165|ZGyz1d0clt2XO3AyrjHmrKORo'
	});

});

Obtaining an access token

This section was added on June 19, 2011 to reflect the changes that Facebook introduced in their API. Namely to require an access token to fetch the page feed.

The first step to obtaining an access token is registering as a developer on http://developers.facebook.com. After this you will need to create a new Facebook App. It is a simple process and you don’t need to enter any data except for the name of the application. This will give you an App ID and an App Secret, which you can see from the “My Apps” page.

Next you need to visit the following URL, replacing APP_ID and APP_SECRET with the values for your App:

https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id=APP_ID&client_secret=APP_SECRET

This will give you a string, similar to this:

access_token=19304297594165|ZGyz1d0clt2XO3AyrjHmrKORo

This is your access token. You will need to include the string after the equal sign when calling the facebookWall plugin in the previous section.

With this our custom Facebook wall is complete!

Wrapping Up

Hopefully in today’s tutorial, you saw that templates are a great tool to have in your jQuery arsenal. The template plugin makes it really easy to define, render and store templates. Combined with some of its more advanced features, you can create easy to maintain web applications, without getting tangled in lengthy chains of jQuery selectors.

Do you like this tutorial? How would you improve the example? Share your thoughts in the comment section below.

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and publishes new tutorials weekly.

Tutorials

81 Comments

  1. Kudos on a great tutorial! Just what I needed!

  2. Justin H says:

    Great use of the facebook api, This will come in handy for future projects. Cheers.

  3. JP says:

    Hey Martin, nice tutorial as usual!

    Quick question though, how would I benefit from using a wall such as this?

    1. JP says:

      Benefit as in, how could I implement it into a website to enhance user experience etc. :D

    2. Martin Angelov says:

      You could use it to show a feed from your facebook page on your sidebar (the same way as people show their latest tweets).

      However this was more about demonstrating jQuery templates, the new $.when() function, and the Facebook API.

      1. Dear Martin,

        This doesn't work anymore since Facebook did an update.
        Could you perhaps find what they've updated and adjust the script so that we all can enjoy this script again? :)
        Thank you :)

        1. Martin Angelov says:

          Updated! But as it is explained in the tutorial, the bad news is that you will need to create a Facebook Application (or use an existing one), and obtain an access token which you will need to pass along with the page id when calling the plugin.

          The download was updated with the fix.

          1. TJ says:

            Hi Martin,

            I seriously appreciate your work. Even after getting the Access Token, I still can't see any of my posts? Any thoughts?

            Cheers,
            TJ

          2. Martin Angelov says:

            The first thing I can think of is that your wall might not be publicly accessible. I would advise you to inspect the response that Facebook gives you (you can use Chrome's dev tools or Firebug). Facebook give back descriptive error messages that might help you diagnose your problem.

  4. krypto says:

    dude I simply love you! XD

  5. Beben Koben says:

    awesome...thanks for tutor my master \m/

  6. vipin sahu says:

    is it working on just popular pages only ? like (smashing , mashable) . Caz i tested your code on my one and i got the blank result .have a look here

    'http://graph.facebook.com/teachforindia'

    1. Martin Angelov says:

      Nope, it should work on every page. There was a bug with photo type posts, but it was fixed. You can download it again.

    2. TJ says:

      I can see your posts man. Did you make any changes?

  7. Eugenio says:

    You continue surprising me!

    That is exactly what I was thinking to create when I had some time ;)

    Thank you! and continue the good work!

  8. Gomy says:

    I need a little help.
    Why doesnt work with my facebook page?
    http://www.facebook.com/gomymusiccom
    I replace
    $('#wall').facebookWall({id:'smashmag'});
    with
    $('#wall').facebookWall({id:'gomymusiccom'});
    and I see a black page.
    Should I do other things except that?

    1. Martin Angelov says:

      Thank you for catching this. Apparently photo posts also report a type "link" which got the script mixed up.

      The bug was fixed and the demo was updated. You can download the new version and replace your js/script.js with the new one.

      1. Martin,

        Great tutorial. I am sending you an email, need some help with a new project...

  9. pakboz says:

    Wow, this is really cool man...

  10. Gomy says:

    Is great.... but....
    It does'nt show all (my) posts from my page's wall....
    Can you fix that?

  11. Avangelist says:

    after spending a week reading about javascript templates and trying to understand what the real point or gain was this has gone towards proving the point.

    As I understand it now, templates are helping morph javascript code into a view layer controller. Basically allowing variables to be dropped into html markup to save time on writing myElem.text or .innerHtml.and having to traverse and insert into placeholders.

    Is that the general idea?

  12. Gomy says:

    The code not read all posts from the facebook page/profile.. I think is random...

  13. Gomy says:

    Anyone have idea how can make the script to read all posts from the facebook page/profile?

  14. Mikkel says:

    Am i the only one still getting a blank page? It renders my name, but no updates.

  15. Gomy says:

    unfinished script

  16. Mary Kay says:

    Thanks so much for publishing this script! It has saved me a lot of time and effort. I have one question -- I've changed the graph URL to call "feed" instead of "posts", because I want to see all the different kinds of wall updates, and that's working well. The thing that's *not* working now is the limit -- how exactly does your limit work? It appears to be counting your definition of "posts" -- my feed, composed of links and photos and status updates, goes on and on until there are a total # of links/status updates to match the given limit. I'm just not sure how to tell it to stop at 5 feed items. Any ideas?

  17. Mary Kay says:

    Sigh never mind - right after I posted that question I tried this:
    if(this.type != 'link' && this.type!='status' && this.type!='photo'){
    return true;
    }
    And that seems to have solved the problem. Not sure what it's doing, but it did the trick.

  18. Ryan says:

    Another excellent and practical tutorial, thanks! Question, can this script be tailored to apply to the events on a given page? For example, if I was using this script for a music group page, can the events on that page be pushed to this script so that they could be rendered on a website?

    Thanks for all the tips!
    Ryan

  19. channeljay says:

    very good. love it

  20. Antoine says:

    Facebook now needs an access token to use graph API (even for public profiles).
    So the code doesn't work anymore.

    Can somone modify the plugin to works with accesss token ?

    Thanks.

  21. Antonio says:

    I have implemented the plugin, it worked great... until June 3rd 2011, when Facebook decided to change Graph API. (Read more here: http://developers.facebook.com/blog/post/509/ )

    So it seems that we now need an access token in order to pull the feed.

    It would be very appreciated if you could update the script, however my bigger concerne is how can I get the access token?

    Thx guys!

  22. TJ says:

    Will only work when there is a wall for a person or a group. Thanks man, awesome work.

  23. Rey thibaut says:

    Hi,

    I like so much this post but I have a problem. I try to show the picture that I have post on my Facebook page but I don't succeed.

    First I have type those line
    if((this.type != 'link' && this.type!='status' && this.type!='photo') || !this.message){
    return true;
    }

    In replace of those

    if((this.type != 'link' && this.type!='status') || !this.message){
    return true;
    }

    But now I don't know what I have to do to show the pictures

    Think you to help me.

    PS : Sorry for english mistake I come from france

  24. ronie says:

    The Code

    // Rendering the templates:
    $('#headingTpl').tmpl(fb.user).appendTo(wall);

    // Creating an unordered list for the posts:
    var ul = $('').appendTo(wall);

    // Generating the feed template and appending:
    $('#feedTpl').tmpl(fb.posts).appendTo(ul);

    and

    $(document).ready(function(){

    // Calling our plugin with a page id:
    $('#wall').facebookWall({
    id:'smashmag',
    access_token:'19304297594165|ZGyz1d0clt2XO3AyrjHmrKORo'
    });

    });

    are not in the download, it should put in a new js?

  25. Bryan says:

    I'd like to pull in the link to the post itself. That way, if someone wanted to comment, they could click the comment link and be taken to that post on FB. Any thoughts on how to accomplish that?

    Love the script. Also went to using feed, not just posts, as Mary Kay suggested above.

  26. Hi there and thx for this great piece of code. i have one problem though. It shows three posts only, also it shows old ones, the latest is from yesterday. Though I didn't change the default limit of 15 or anything? Has anybody an idea what I could work on to get it working? Please help!

  27. Michael says:

    Folks, I figured my problem out. Seems that the type of post is decisive as these lines would have to be altered;

    // We only show links and statuses from the posts feed:
    if((this.type != 'link' && this.type!='status') || !this.message){
    	return true;
    }
    
    // Copying the user avatar to each post, so it is
    // easier to generate the templates:
    this.from.picture = fb.user.picture;
    				
    // Converting the created_time (a UNIX timestamp) to
    // a relative time offset (e.g. 5 minutes ago):
    this.created_time = relativeTime(this.created_time*1000);
    				
    // Converting URL strings to actual hyperlinks:
    this.message = urlHyperlinks(this.message);
    
    fb.posts.push(this);
    

    to show the posts oven if I post Videos, Pictures or any content. I am implementing this script to use for our B&B in Patagonia @ www.bordemundo.com. If any of you could help me out I promise you an extraordinary king and queen like treatment here at the cosy end of the world? Any help is highly appreciated!

    1. Michael says:

      Finally I made it. Nevertheless it doesn't show any posts containing videos, regardingless whether these are linked from YouTube or within Facebook itself. Has anyone an idea how I could solve this? Saludos!

  28. Dan says:

    Is there a way you can limit the number of posts show only the last 5 updates show?

  29. BS says:

    Hi Michael,

    could you please post your solution to show photoposts?

    if((this.type != 'link' && this.type!='status' && this.type!='photo') || !this.message){
    return true;
    }

    above is to show the message from a photo post, but how to display the corresponding image?

    Regards

  30. Jj says:

    Hi,
    I've got the same problem.. no latest posts and no picture of my posts... someone know how to fix it ?

  31. Matteo says:

    To get also photo & video, edit script.js

    Around line 64, like this:

    // We only show links photos and videos from the posts feed:
    if((this.type != 'link' && this.type!='photo' && this.type!='video') || !this.message){
    	return true;
    }
    

    I have edited also the graphPOSTS variable, using the /feed/ instead /posts/, like this:

    graphPOSTS = 'https://graph.facebook.com/'+options.id+'/feed/?access_token='+
    		options.access_token+'&callback=?&date_format=U&limit'+options.limit;
    

    Then, in my html page template, I've added two conditional codes for photos and videos, like this two:

    {{if type == "photo" }}
    	<div class="fb-photo-attachment">
    		{{if picture}}
    			<a href="${link}" target="_blank">
    				<img class="fb-picture alignleft" src="${picture}" />
    			</a>
    		{{/if}}
    		<div class="attachment-data">
    			
    			<p class="caption">${message}</p>
    			<p class="description">${description}</p>
    		</div>
    	</div>
    {{/if}}
    		
    {{if type == "video" }}
    	<p class="message">{{html message}}</p>
    	<div class="fb-attachment">
    		{{if picture}}
    			<a href="${link}" target="_blank">
    				<img class="picture alignleft" src="${picture}" />
    			</a>
    		{{/if}}
    		<div class="attachment-data">
    			<p class="name"><a href="${link}" target="_blank">${name}</a></p>
    			<p class="caption">${caption}</p>
    			<p class="description">${description}</p>
    		</div>
    	</div>
    {{/if}}
    

    In this way, you can adding custom structure and style for each type.

    Well...that is. For me works like a charm:

    http://mced.it/social/

    1. Mauricio says:

      Thanks Matteo, thats i need , really helpful, my best regards...

    2. shahab says:

      Matteo,
      there is a minor bug in your code ... it works fine but it breaks the limiting of number of posts functionality ... the line:
      graphPOSTS = 'https://graph.facebook.com/'+options.id+'/feed/?access_token='+options.access_token+'&callback=?&date_format=U&limit'+options.limit;

      should be:

      graphPOSTS = 'https://graph.facebook.com/'+options.id+'/feed/?access_token='+options.access_token+'&callback=?&date_format=U&limit='+options.limit;

      Note the missing "=" just before calling options.limit variable ...

    3. bulp says:

      Matteo...

      any chance to set size bigger for pic / video ?

  32. Christian says:

    Hi!
    Why works the demo with all posts (last 15)
    http://demo.tutorialzine.com/2011/03/custom-facebook-wall-jquery-graph/

    and with the same files (changed only my ID) i see only 2 random posts from my Facebookwall?

    Is there any differneces between the api`s?

    1. Martin Angelov says:

      Did you create an API key for use with the plugin?

  33. Christian says:

    Shure - i have a api key.

  34. Andrew says:

    Hey everyone, I am attempting to update this workup to work around the new data types facebook has added. I have everything working except now when I update anything in the profile facebook sends out a "page" data type (for example when you change your phone number or address). So what I want to do is filter out that data type so it is not counted in the number of updates. I have two ideas for this, I would appreciate any ideas or tips.
    1) Filter the json object before it is added to the array.
    2) filter the array the json object is saved too.

  35. daddyfristy says:

    great post!
    one question: how long will the access token created by method in this post last? Is there a way to auto-renew it when it expires .

    ( assuming I don't go and reset my password or the app secret which would kill the token right away)

  36. Hannes says:

    Hi,

    Great script. I'm trying to implement this on the startpage of a worpress site without success. Anyone know the reason for it not working? I get it to work as a stand alone page but not as a part of the existing layout. Please help me.

    Thanks in advance,
    Hannes

  37. mhazzard says:

    Good script/tutorial, but it is taking like 5 secs for the facebook json to return and that holds up the response.

    I tried caching w/

    $.ajaxSetup({
    cache: true
    });

    and setting the callback "?" as a static value but no dice.

    I'm sure it has to do w/ the expires "Expires Sat, 01 Jan 2000 00:00:00 GM"
    response from fb but I don't see a param to send to them to change it..

    Thanks,
    //mh

  38. Mauricio says:

    Great app thanks for your recomendations, you save my life ha.!!!

  39. andreas says:

    hi
    great tutorial! can you please add functionality to load more?

  40. david says:

    for thoses who dont know how to display the facebook avatar... That is because Facebook change their Json callback.

    replace in script.js at line 67 : this.from.picture = fb.user.picture;
    by :this.from.picture = fb.user.picture.data.url;

    work perfectly well. Great script !

    1. Mauricio says:

      Thank David, for this, you save me hehe.

    2. shahab says:

      Wonderful ! thanks for that !

    3. MikeL says:

      I spent so long trying to figure this out. Should have just scrolled down to your fix. Thanks so much!

  41. lifo says:

    in order to get this to work i've removed '&callback=?' from the graphUSER and de graphPOSTS strings in the script.js

    and use the working version of the template:
    https://raw.github.com/jquery/jquery-tmpl/master/jquery.tmpl.js

    thanks for de tutto!!

  42. Bart says:

    Title: Yes
    Posts: No

    Does dit have something to do with the privacy settings? I've entered public or did I miss a step in the tutorial?

  43. James says:

    A couple questions if anyone has a fix :)

    Is there away to make this display posts from mobile devices?

    Is there a way to make this play video inside the feed like the Facebook Wall and not open YouTube/Vimeo in a new window?

  44. Dan says:

    Thanks for the great code!

    One question, I can't seem to get it to display "link only" updates, in other words when there is no "message" line in the graph. See below for graph example.

    Anyone have any ideas for this?

    "story": "Dan shared a link.",
    "story_tags": {
    "0": [
    {
    "id": "88744960560",
    "name": "Dan",
    "offset": 0,
    "length": 23,
    "type": "page"
    }
    ]
    },
    "link": "url-here",
    "name": "name-here",
    "caption": "caption-here",
    "description": "desc-here",
    "icon": "http://static.ak.fbcdn.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif",
    "type": "link",
    "status_type": "shared_story",
    "created_time": "2012-10-25T14:29:18+0000",
    "updated_time": "2012-10-25T14:29:18+0000",
    "comments": {
    "count": 0
    }

  45. Tim says:

    First let me say this is a life saver. I do have one issue though, for some reason or another when setting limit of 12 it only shows 6 and when setting limit of 8 it shows 2. Any suggestions on how or why?

    1. There may be a conflict in other jquery libraries you call, for instance I had an issue that conflicted with Jquery 1.6 library, go through and systematically test each one by disabling the script call to until you find the conflicting call.

  46. Tim says:

    I think i figured it out, problem is it's counting posts that are just links or just pictures but isn't showing them. Is there a fix for this yet?

    1. Yes,
      Use this in the HTML template:

      <li>
      	<img src="${from.picture}" class="avatar" />
      	<div class="status">
      		<h2><a href="http://www.facebook.com/profile.php?id=${from.id}" target="_blank">${from.name}</a></h2>
      		<p class="message">{{html message}}</p>
      		{{if type == "link" }}
      			<div class="attachment">
      				{{if picture}}
      					<img class="picture" src="${picture}" />
      				{{/if}}
      				<div class="attachment-data">
      					<p class="name"><a href="${link}" target="_blank">${name}</a></p>
      					<p class="caption">${caption}</p>
      					<p class="description">${description}</p>
      				</div>
      			</div>
      		{{/if}}
      		{{if type == "photo" }}
      			<div class="fb-photo-attachment">
      				{{if picture}}
      					<a href="${link}" target="_blank">
      						<img class="fb-picture alignleft" src="${picture}" />
      					</a>
      				{{/if}}
      				<div class="attachment-data">
      					<p class="caption">${message}</p>
      					<p class="description">${description}</p>
      				</div>
      			</div>
      		{{/if}}
      		{{if type == "video" }}
      			<p class="message">{{html message}}</p>
      			<div class="fb-attachment">
      				{{if picture}}
      					<a href="${link}" target="_blank">
      						<img class="picture alignleft" src="${picture}" />
      					</a>
      				{{/if}}
      				<div class="attachment-data">
      					<p class="name"><a href="${link}" target="_blank">${name}</a></p>
      					<p class="caption">${caption}</p>
      					<p class="description">${description}</p>
      				</div>
      			</div>
      		{{/if}}
      	</div>
      	<p class="meta">${created_time} · 
      	{{if comments}}
      		${comments.count} Comment{{if comments.count>1}}s{{/if}}
      	{{else}}
      		0 Comments
      	{{/if}} · 
      	{{if likes}}
      		${likes.count} Like{{if likes.count>1}}s{{/if}}
      	{{else}}
      		0 Likes
      	{{/if}}
      	</p>
      </li>
      

      and this in the script file:

      if((this.type != 'link' && this.type!='status' && this.type!='photo' && this.type!='video') || !this.message)
      {
      	return true;
      }		
      

      the above script will replace the current script that looks similar. The one above just has the added data calls and the HTML above has the added output template calls.

      You will also need to change the following in the script files for it to work:

      graphPOSTS = 'https://graph.facebook.com/'+options.id+'/feed/?access_token='+options.access_token+'&callback=?&date_format=U&limit='+options.limit; 
      

      and to get the avatar to work correctly change the following in the script file:

      	this.from.picture = fb.user.picture.data.url;
      
      1. Andrea Moro says:

        Hi There,
        thanks for the additional implementation on the code. Do you have any idea on how to get the full HTML code passed by the JSON stream?

        I'd like to convert the \n\n in a new HTML paragraph and the \n in a <br>.

        Also, it would be nice linking every post to it's current URL to allow users commenting on FB if they want to. It's useless linking back all the time to the facebook home page.

  47. gaxt says:

    For those of you, who have troubles because of this message: "Uncaught TypeError: Cannot read property 'length' of undefined". You should try to delete the "callback=?" in the API-URLs.

  48. Elmman says:

    SOOOO Frustrating why can't I get this to woork??? I feel like it might have to do with this vague part: "This is your access token. You will need to include the string after the equal sign when calling the facebookWall plugin in the previous section."

    I thought that I just had to post it here:

    $('#wall').facebookWall({
    id:'MY_ID',
    access_token:'434471379966823|9J7f-YXtSLkZZFKa06pkp1yFkds'
    });

    At the beginning of the script.js but then I caught that line which completely confused me. I've tried pasting it directly after the equal sign, I've pasted it EVERYWHERE in the script.js file, I've even written it on a post-it and pasted it on my computer screen!!! Nothing works, I just get my facebook page name and it's blank beneath....

    Please help.

    1. You should only have to put in ONE SINGLE location, then it gets transferred throughout the code as an object. There is an error in the original assignment of the variable.

  49. mike says:

    Can this be used to query multiple facebook pages streams into one stream?

    1. It looks like it is possible. Add multiple objects for the different accounts in the script. then in the html file create a second template with the new created objects.

  50. Proze says:

    Hi, great tutorial and script..... Saved me a lot of time. Thanks.

    I just want to ask, when its displaying images from the posts, is there anyway to call larger image url ? No they seems to have the max height, width of 130px.

    Thanks.

    1. That would be in the CSS file.

      1. Jenny says:

        It seems like the code is linking to the smallest thumbnail image vs. the bigger image. So changing the size in the css will make it bigger, but super low res. Any Idea how to change this? Facebook creates each image in multiple sizes, but I can't figure out how to access them.

  51. qutek says:

    Great tutorial,,,
    Awesome,,

    Thanks a lot Martin

  52. Thank you, with Mateo's revision, Shahab's revision, and a few of my own, works great. Thank you again.

  53. Joseph says:

    Is there a way to change the date format to MMDDYYYY and make the like button, and comment button function as if the user were directly on the Facebook it's being called from?

    I'm mostly concerned with the MMDDYYYY format.

    Thanks!

  54. Dan says:

    Thanks Jeremy, your patch for photos/etc really helped me out!

  55. Geert says:

    The newest API update from 10th of July 2013 broke the like and comment count. Facebook removed the count and comment from the API. I hotfixed this by using likes.data.length instead of likes.count, but i doubt if that's a good solution. So if anyone has a better solution, let me know! Quote from the roadmap page:

    Removing 'count' from 'comments' Graph API connection
    We are removing the undocumented 'count' field on the 'comments' connection in the Graph API. Please request '{id}/comments?summary=true' explicitly if you would like the summary field which contains the count (now called 'total_count')

    https://developers.facebook.com/roadmap/

  56. Rashed says:

    Thanks for the code Martin. You used segoe UI font in the demo, is it free to use? Thanks.

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links