Here is a solution I came up with for a project a while back. Definitely not plug+play since it is integrated with my javascript architecture but hopefully can get you started:
"use strict";
var Facebook = function(sb, options) {
options = options || {};
var language = options.language || "en_US";
var self = this;
var access_token = encodeURIComponent(YOUR ACCESS TOKEN);
var listenerQueue = [];
var loading = false;
var FACEBOOK;
var appId = YOUR APP ID;
if (window.FB) {
FACEBOOK = window.FB;
}
(function _load() {
if (!loading) {
loading = true;
window.fbAsyncInit = function() {
// init the FB JS SDK
FACEBOOK = window.FB;
FACEBOOK.init({
appId : appId,
status : true,
oauth : true,
cookie : true,
xfbml : true
});
sb.publish("facebook:initialized");
};
// Load the SDK asynchronously
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/" + language + "/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
}
})();
(function() {
sb.subscribe('facebook:initialized', function() {
listenForLogin();
if (listenerQueue.length) {
clearListenerQueue();
}
});
})();
function listenForLogin() {
FACEBOOK.Event.subscribe('auth.authResponseChange', function(response) {
if (response.status === 'connected') {
getLoggedInUserData();
} else {
}
});
}
function getLoggedInUserData() {
FACEBOOK.api('/me', function(response) {
sb.publish('facebook:loggedIn', response);
});
}
function clearListenerQueue() {
if (FACEBOOK) {
for (var i=0; i<listenerQueue.length; i++) {
listenerQueue[i].fn.apply(this, listenerQueue[i].args);
}
listenerQueue = [];
}
}
function sharePage(url, options) {
var opts = options || {};
if (FACEBOOK) {
FACEBOOK.ui(
{
method: 'feed',
name: opts.name || '',
caption: opts.caption || '',
description: opts.description || '',
link: url,
picture: opts.picture || ''
},
function(response) {
var success = (response && response.post_id);
sb.publish('facebook:shared', {response : response, success : success});
}
);
} else {
listenerQueue.push({fn : sharePage, args : [url, options]});
}
return self;
}
function getPosts(fbHandleOrId, options) {
options = options || {};
if (FACEBOOK) {
var limit = options.limit || '10';
var graphPOSTS = '/' + fbHandleOrId +'/posts/?date_format=U&access_token=' + access_token + "&limit=" + limit;
FACEBOOK.api(graphPOSTS, function(response) {
sb.publish('facebook:gotPosts', {response : response, handleUsed : fbHandleOrId});
});
} else {
listenerQueue.push({fn : getPosts, args : [fbHandleOrId, options]});
}
}
function getStatuses(fbHandleOrId, options) {
options = options || {};
if (FACEBOOK) {
var limit = options.limit || '10';
var graphStatuses = '/' + fbHandleOrId + "/feed/?access_token=" + access_token + "&limit=" + limit;
FACEBOOK.api(graphStatuses, function(response) {
sb.publish('facebook:gotStatuses', {response : response, handleUsed: fbHandleOrId});
});
} else {
listenerQueue.push({fn : getStatuses, args : [fbHandleOrId, options]});
}
}
function getNextPageOfPosts(nextPostsUrl, options) {
options = options || {};
if (FACEBOOK) {
FACEBOOK.api(nextPostsUrl, function(response) {
sb.publish('facebook:gotNextPosts', {response : response, handleUsed : fbHandleOrId});
});
} else {
listenerQueue.push({fn : getNextPageOfPosts, args : [nextPostsUrl, options]});
}
}
function getPublicUserInfo(fbHandleOrId, options) {
options = options || {};
var graphUSER = '/'+ fbHandleOrId +'/?fields=name,picture&callback=?';
if (FACEBOOK) {
FACEBOOK.api(graphUSER, function(response) {
var returnObj = {response : response, handleUsed : fbHandleOrId};
sb.publish('facebook:gotPublicUserInfo', returnObj);
});
} else {
listenerQueue.push({fn : getPublicUserInfo, args : [fbHandleOrId, options]});
}
}
function getLikes(pageHandle, options) {
options = options || {};
var graphLIKES = '/' + pageHandle + '/?fields=likes';
if (FACEBOOK) {
FACEBOOK.api(graphLIKES, function(response) {
var returnObj = {response : response, handleUsed: pageHandle};
sb.publish('facebook:gotLikes', returnObj);
});
} else {
listenerQueue.push({fn : getLikes, args : [pageHandle, options]});
}
}
function login() {
if (FACEBOOK) {
FACEBOOK.getLoginStatus(function(response) {
if (response.status !== "connected") {
// not logged in
FACEBOOK.login(function() {}, {scope : 'email'});
} else {
getLoggedInUserData();
}
});
} else {
listenerQueue.push({fn : login, args : []});
}
}
function getNextPageOfPosts(callback) {
callback = callback || function() {};
}
return {
getLikes : getLikes,
getPublicUserInfo : getPublicUserInfo,
getCurrentUser : getLoggedInUserData,
getNextPageOfPosts : getNextPageOfPosts,
getPosts : getPosts,
getStatuses : getStatuses,
sharePage : sharePage,
login : login
}
};