I’m using Backbonejs for my app and I’m trying to add Facebook comments and like/send buttons to some of my views. I’m instantiating the JavaScript SDK before instantiating the Router object, like this :
// main.js
require([ "Router" ], function (Router) {
// Facebook authentication
// 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";
ref.parentNode.insertBefore(js, ref);
}(document));
// Init the SDK upon load
window.fbAsyncInit = function() {
FB.init({
appId : '302210766529054', // App ID
channelUrl : '//'+window.location.hostname+'/channel', // Path to your Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// If the user has auth'd the app, instantiate the router object.
FB.Event.subscribe('auth.statusChange', function(response) {
if (response.authResponse) {
// user has auth'd your app and is logged into Facebook
FB.api('/me', function(me){
if (me.username) {
window.currentUser = me;
$('#username').html(window.currentUser.name);
new Router();
Backbone.history.start();
}
});
}
});
}
});
I can easily use the windows.currentUser variable in any of the views called by the Router. However, when I add
<div class="fb-comments" data-href="http://mywebsite/i/#items/" data-num-posts="2" data-width="470"></div>
to one the templates called by a view in the router, the comments (nor the like/send) div doesn’t appear. When I add it to one of the static elements of the index.html file, it works fine.
Am I missing anything here?
EDIT
Here is my router and views code as it was before i post the question.
router.js
define(
[
'models/song',
'models/user',
'models/spotlight',
'models/user-playlist',
'views/spotlight-view',
'views/playlist-view',
'views/single-playlist-view',
],
function(Song, User, SpotlightModel,UserPlaylist, SpotlightView, PlaylistView, SinglePlaylistView){
return Backbone.Router.extend({
initialize: function(){
window.songQue = new Array();
},
routes:{
'': 'index',
'spotlight': 'index',
'playlists': 'allPlaylist',
'playlists/:id':'onePlaylist',
},
index: function(){
var spotlight = new SpotlightModel({id:1});
var spotlightView = new SpotlightView({spotlight: spotlight});
spotlight.fetch();
$('.content').html(spotlightView.el);
},
allPlaylist: function(){
$('.content').html('');
var user = new User({id:window.currentUser.id});
/*
* once user details are fetched from the server,
* loop through the arrays of their playlists and
* render them in the template.
*/
user.bind('change', function(){
console.log(this);
for(var i=0; i<this.get('objects')[0].playlists.length; i++){
var playlistView = new PlaylistView({
playlist: user.get('objects')[0].playlists[i],
user: this.get('objects')[0]
});
$('.content').prepend(playlistView.el);
}
});
},
onePlaylist: function(playlist_id){
var userPlaylist = new UserPlaylist({id:playlist_id});
var singlePlaylistView = new SinglePlaylistView({playlist: userPlaylist});
$('.content').html(singlePlaylistView.el);
}
});
}
);
// single-playlist-view.js
define(
[
'text!templates/single-playlist/single-playlist.html',
'text!templates/single-playlist/single-playlist-details.html',
'text!templates/playlist/song-row.html',
],
function(SinglePlaylistTemplate, SinglePlaylistDetailsTemplate, SongRowTemplate){
return Backbone.View.extend({
initialize:function(options){
this.playlistTemplate = _.template(SinglePlaylistTemplate);
this.playlistDetailsTemplate = _.template(SinglePlaylistDetailsTemplate);
this.songRowTemplate = _.template(SongRowTemplate);
this.playlist = options.playlist;
$(this.el).prepend(this.playlistTemplate);
this.playlist.bind('change', this.render, this);
this.playlist.fetch();
},
render:function(){
this.renderSongs();
this.renderDetails();
},
renderSongs: function(){
// Put the size of songs in a variable
var size = this.playlist.get('objects')[0].songs.length;
// Extra loop just for the sake of filling the page.
for(var j=0; j<5; j++){
for(var i=0; i<size; i++){
this.$("#song-row").prepend(this.songRowTemplate({
song: this.playlist.get('objects')[0].songs[i]
}));
}
}
},
renderDetails: function(){
this.$('.single-playlist-details').prepend(this.playlistDetailsTemplate({
playlist: this.playlist,
thumbnail: this.playlist.get('objects')[0].songs[0].song_thumbnail,
total:this.playlist.get('objects')[0].songs.length,
}));
}
});
}
);
The backbone views will are being rendered after the Facebook API Call – at the stage when you make the Facebook call the element does not exist.
You really want to do the Facebook call inside your Router in the route for the page you want to display the facebook API results.
If its something that you want to display on every page – e.g. Username/Profile pic consider putting the code in a separate function eg initUserInfoView() and then call it from each route where you want to display the info.
To be honest this stuff actually belongs in your View – the router should initialize and render the view, and the view is responsible for fetching from Facebook and displaying