简体   繁体   中英

Can I use the Facebook Javascript SKD with a dynamic script tag insert?

What am I trying to achieve. To create a module that loads the Facebook Javascript SDK without having to paste that script tag into your HTML and manually enter your app details, yes this may seem like a waste of time but It seems to make more sense to me. For example this module would take a config with your details and everything could be set via Javascript instead of the initialization code being in your HTML file and the rest of your logic being in your script files.

My problem. When I dynamically append the script and

<div id="fb-root"></div>

I get an error

FB.init has already been called - this could indicate a problem

This seems strange to me because I only have once instance FB.init is called. Effectively my script is the same as if you would manually add the script tag into the html but I'm trying to achieve it dynamically.

What I have tried. I have read a lot of questions on here about using javascript to append and prepend elements, I have tried mostly all of those methods. I have read topics titled Dynamically Inserting Script with Javascript, these have been no help.

My method seems to be correct, but I still get these Facebook errors.

My Markup.

<!DOCTYPE html>
    <head>
       <title></title>
    <head>
    <body>
        <script src="facebook.js"></script>
    </body>
</html>

My Javascript:

var Facebook = {};

Facebook = {
        config: {
        APP_ID: 'APP_ID',
        APP_URL: 'APP_URL',
        CHANNEL_URL: 'CHANNEL_URL'
    }

};

var fbEl = document.createElement('div');
fbEl.id = 'fb-root';
document.body.insertBefore(fbEl,document.body.children[0]);

var fbScript = document.createElement('script');
fbScript.type = 'text/javascript';
fbScript.innerHTML = '';
fbScript.innerHTML += 'window.fbAsyncInit = function() {\n';
fbScript.innerHTML +=   'FB.init({\n';
fbScript.innerHTML +=       'appId      : '+Facebook.APP_ID+',\n';
fbScript.innerHTML +=       'channelUrl : '+Facebook.CHANNEL_URL+',\n';
fbScript.innerHTML +=       'status     : false,\n';
fbScript.innerHTML +=       'cookie     : true,\n';
fbScript.innerHTML +=       'xfbml      : false \n';
fbScript.innerHTML +=   '});\n';

fbScript.innerHTML +=   '};\n';

fbScript.innerHTML +=   '(function(d, debug){\n';
fbScript.innerHTML +=   'var js, id = "facebook-jssdk", ref = d.getElementsByTagName("script")[0];\n';
fbScript.innerHTML +=   'if (d.getElementById(id)) {return;}\n';
fbScript.innerHTML +=   'js = d.createElement("script"); js.id = id; js.async = true;\n';
fbScript.innerHTML +=   'js.src = "//connect.facebook.net/en_US/all" + (debug ? "/debug" : "") + ".js";\n';
fbScript.innerHTML +=   'ref.parentNode.insertBefore(js, ref);\n';
fbScript.innerHTML +=   '}(document, /*debug*/ false));';

document.body.insertBefore(fbScript,document.body.children[1]);

I do have the Facebook variables set correctly in my code this is for demonstrations sake. I have read the Facebook Docs on this many times.

Is there a way to dynamically add the block for tje FB JS SKD using ONLY Javascript?

I'm not sure what's actually going wrong, but you have one more level of indirection than you need and that's making the whole thing too complicated. Why not something like:

var Facebook = {
   config:{ //etc
   }
};

window.fbAsyncInit = function() {
  FB.init(//etc
  )
};

(function(d, debug){
  var js, id = //etc - this injects the SDK script reference into the dom.
})(document, false);

The asynchronous JS code FB provide is a way to generate the FB SDK code only in javascript. Right now it seems like you try to code PHP style into JS...

If you need to load modules asynchronously, you should use a module loader (RequireJS or YepNope, etc).

The error message triggered may be because you added some parameter in the FB SDK URL (eg //connect.facebook.net/fr_CA/all.js#xfbml=1&appId=123456789" ). If so, just remove everything after the hash # . Also, make sure you're not loading the SDK twice.

The method I was trying was causing a strange load order, the init code would load before the SDK was loaded causing strange errors.

A revision of the logic solved this. Not much different but now it works perfectly.

Facebook = {};

Facebook = {
    config: {
        APP_ID: 'APP_ID',
        APP_URL: 'APP_URL',
        CHANNEL_URL: 'CHANNEL_URL'
    }

};
Facebook.init = function() {
    var fbEl = document.createElement('div');
    fbEl.id = 'fb-root';
    document.body.insertBefore(fbEl,document.body.children[0]);
    window.fbAsyncInit = function() {
    // init the FB JS SDK
        FB.init({
            appId      : 'APP_ID', // App ID from the App Dashboard
            channelUrl : 'CHANNEL_URL', // Channel File for x-domain communication
            status     : true, // check the login status upon init?
            cookie     : true, // set sessions cookies to allow your server to access the session?
            xfbml      : true  // parse XFBML tags on this page?
        });

        // Additional initialization code such as adding Event Listeners goes here

    };

    // Load the SDK's source Asynchronously
    // Note that the debug version is being actively developed and might 
    // contain some type checks that are overly strict. 
    // Please report such bugs using the bugs tool.
    (function(d, debug){
        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" + (debug ? "/debug" : "") + ".js";
        ref.parentNode.insertBefore(js, ref);
    }(document, /*debug*/ false));
};

Facebook.init();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM