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
    }
};