2011-10-12 8 views
9

Sto tentando di aggiungere un pulsante Mi Piace a un widget che sto creando. Il codice che uso per aggiungere il pulsante mi piace di Facebook alla mia pagina è il seguente:L'FB non è definito anche se l'ho appena usato

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

* La funzione ChangeView esiste pure nel JavaScript.

Quando si esegue il codice, viene visualizzato un messaggio di errore: Uncaught ReferenceError: FB is not defined anche se il pulsante è stato creato. L'errore punta alla riga contenente il codice FB.XFBML.parse. C'è qualcosa che devo fare in modo diverso nel mio JavaScript?

+0

Provare a utilizzare window.FB o document.FB –

risposta

14

Il punto centrale di quel grande blocco di script a partire window.fbAsyncInit è che il Facebook SDK viene caricato in modo asincrono .

Anche se le chiamate effettuate su FB all'interno di un callback di documento jQuery sono pronte, ciò non è sufficiente per garantire che l'SDK sia caricato quando viene eseguito quel codice.

Fortunatamente, esiste window.fbAsyncInit per esattamente questo scopo: non verrà eseguita fino a quando l'SDK è stato caricato.

Da Facebook's docs:

The function assigned to window.fbAsyncInit is run as soon as the SDK is loaded. Any code that you want to run after the SDK is loaded should be placed within this function and after the call to FB.init. For example, this is where you would test the logged in status of the user or subscribe to any Facebook events in which your application is interested.

+2

OK. Quindi c'è qualcosa come window.fbSyncInit che lo farebbe in modo sincrono? O un evento che verrebbe eseguito quando verrà caricato il resto del documento? Non sono davvero sicuro di come combinare $ (document) .ready() con fb init dove so che ci sono tutti gli elementi HTML. –

5

FB non è stato ancora definito in quel punto del tempo. Non l'hai ancora usato, l'hai semplicemente digitato prima. La riga FB.XFMBL.parse verrà eseguita quando il documento è pronto. Lo stesso vale per la linea //connect.facebook.net/en_US/all.js. Quindi non è veramente affidabile quale codice verrà eseguito per primo se viene eseguito dallo stesso evento.

Ciò che si può fare è avere in qualche modo il codice che si desidera venga eseguito da window.fbAsyncInit. Da quel momento in poi, puoi star sicuro che FB è pronto per essere utilizzato.

Un modo che puoi fare se non vuoi mescolare il codice che hai in widget.js è usando l'evento personalizzato di jQuery. Così, invece di avere $(function() { ... });, avrete qualcosa su questa linea:

$(window).bind('fbAsyncInit', function() { 
    // Your code here 
}); 

allora si avrà window.fbAsyncInit chiamata $(window).triggerHandler('fbAsyncInit') subito dopo la linea FB.init().

13

Ho riscontrato questo problema e l'ho risolto in modo simile alla soluzione fornita da Amry, quindi la inserisco qui nel caso in cui qualcun altro debba usarlo.

Ho fatto l'ipotesi iniziale che la chiamata di inizializzazione FB effettuata nel metodo fbAsyncInit si inizializzasse immediatamente, quindi anch'io ho codificato il mio utilizzo dell'oggetto FB in un metodo $(document).ready(). Questo non è il caso. fbAsyncInit richiede un po 'di tempo dopo il caricamento della pagina per completare l'inizializzazione. Qui è la mia soluzione, quando si utilizza jQuery sul mio sito:

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

L'ultimo compito è quello di cambiare semplicemente il codice $(document).ready() ad un vicolo cieco per il vostro evento. Questo va dove mai stai usando l'oggetto FB.

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

})(jQuery); 

Una cosa posso dimenticare: Firefox è molto più tollerante di questa rispetto ai browser Webkit come Chrome. Non riuscivo a capire perché NONE il mio jQuery funzionasse correttamente in Chrome ... beh, questo era il motivo.

Spero che questo aiuti qualcuno.

+0

Ti amo uomo !!! –

+0

Felice di aver aiutato qualcuno! – Brandon

+0

La risposta di Brandon è azzeccata e funziona. Tuttavia, ci sono anche istruzioni per l'implementazione suggerita usando jQuery e FB con getScript(): https://developers.facebook.com/docs/javascript/howto/jquery/v2.5 –