FB is undefined even though I just used it

Dave Long picture Dave Long · Oct 13, 2011 · Viewed 24.5k times · Source

I am trying to add a Facebook Like button to a widget that I am creating. The code that I use to add the Facebook like button to my page is as follows:

widget.html

<body>
<div id="fb-root"></div>
<script>
    window.fbAsyncInit = function() {
        FB.init({
            appId  : '263071593731910',
            status : false, // check login status
            cookie : true, // enable cookies to allow the server to access the session
            xfbml  : true  // parse XFBML
        });
    };
    (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>
<div id="fb-button"></div>
<script type="text/javascript" src="widget.js"></script>

widget.js

$(function(){
var fb = $(document.createElement("fb:like"));
fb.attr({
    href: data.facebook,
    send: false,
    layout: 'button_count',
    width: 70,
    'show_faces': false
});
$("#fb-button").empty().append(fb);
FB.XFBML.parse($("#fb-button").get(0));
FB.Event.subscribe('edge.create',changeView);
});

*The changeView function does exist as well in the JavaScript.

When I run the code, I get an error: Uncaught ReferenceError: FB is not defined even though the button is created. The error is pointing to the line containing FB.XFBML.parse code. Is there something I need to do differently in my JavaScript?

Answer

Brandon picture Brandon · Dec 19, 2012

I had this problem and solved it similarly to the solution that Amry provided so I'm posting it here in case someone else needs to use it.

I made the initial assumption that the FB initialization call made in the fbAsyncInit method would initialize immediately, so I too coded my use of the FB object in a $(document).ready() method. That is not the case. fbAsyncInit takes quite some time after the page loads to finish initializing. Here is my solution, when using jQuery on my site:

<script type="text/javascript">

  window.fbAsyncInit = function() {

    FB.init({
      appId      : 'your_app_id', // App ID
      channelUrl : 'your channel',
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
    });
    jQuery(document).trigger('FBSDKLoaded'); //This is the most important line to solving the issue
  };

  // Load the SDK Asynchronously
  (function(d){
     var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement('script'); js.id = id; js.async = true;
     js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=269187653191150";
     ref.parentNode.insertBefore(js, ref);
   }(document));

</script>

The last task is to simply switch your $(document).ready() code to a bind for your event. This goes where ever you are using the FB object.

(function($) {
    $(document).bind('FBSDKLoaded', function() {
        //Code using the FB object goes here.
    });

})(jQuery);

One thing I should also mention: Firefox is a lot more tolerant of this than Webkit browsers like Chrome. I couldn't figure out why NONE of my jQuery was working properly in Chrome... well, this was why.

I hope this helps someone.