My pair and I were recently working on an app that asynchronously loaded the Facebook Javascript SDK but synchronously loaded the jQuery library. We had to invoke some javascript once Facebook and jQuery were both loaded, and this post describes how we did it.
First, we followed Facebook’s recommendation and asynchronously loaded the Facebook SDK right after the start of the body tag. Then for other reasons we put all other javascript includes right before the end of the body tag. The resulting html looked like this:
<html>
<head>
</head>
<body>
<div id="fb-root"></div>
<script>
(function() {
var e = document.createElement('script');
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
</script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
</body>
</html>
When the Facebook js loads, it looks for a function named fbAsyncInit
and invokes it if it’s there. When jQuery detects that the document has loaded, it triggers a document ready event. Since the Facebook js is being loaded asynchronously, though, the sequence of these events is unpredictable. Things could happen in one of 2 ways:
fbAsyncInit
is called then$(document).ready()
is triggered$(document).ready()
is triggered thenfbAsyncInit
is called
We needed to run code once Facebook and jQuery were both loaded. If Facebook loaded first, this code worked:
$(document).ready(function(){
$("#content").html("Welcome!")
FB.init({
appId : 'YOUR APP ID',
status : true,
cookie : true,
xfbml : true
});
});
However, if Facebook hadn’t loaded, it blew up on FB
being undefined.
If jQuery loaded first, then this code worked:
window.fbAsyncInit = function() {
$("#content").html("Welcome!")
FB.init({
appId : 'YOUR APP ID',
status : true,
cookie : true,
xfbml : true
});
}
However, if jQuery hadn’t loaded, it blew up on $
being undefined.
After a bit of head scratching we came up with this:
$(document).ready(function(){
function init(){
$("#content").html("Welcome!")
FB.init({
appId : 'YOUR APP ID',
status : true,
cookie : true,
xfbml : true
});
}
if(window.FB) {
init();
} else {
window.fbAsyncInit = init;
}
});
On document ready, if Facebook is loaded, invoke the function immediately. If Facebook is not loaded, define the fbAsyncInit
function, which will be called when Facebook loads.
Going one step further, we moved the page-specific javascript into an event listener, then triggered a custom event that page-specific js could listen for:
$(document).ready(function(){
function facebookReady(){
FB.init({
appId : 'YOUR APP ID',
status : true,
cookie : true,
xfbml : true
});
$(document).trigger("facebook:ready");
}
if(window.FB) {
facebookReady();
} else {
window.fbAsyncInit = facebookReady;
}
});
// elsewhere in the code
$(document).live("facebook:ready", function(){
$("#content").html("Welcome!")
});
Thanks to Evan Farrar and Rachel Heaton for making this work!
About the Author