Do something after all FB API calls finish - javascript

I have some functions that are making some Facebook API calls, and an init one:
var fbAPI = {
init: function () {
this.friendList(), this.friendCount();
},
friendList: function (closure) {
var _self = this;
return FB.api(
"/me/taggable_friends",
function (data) {
_self.setFriends(data);
closure(data);
}
);
},
friendCount: function (closure) {
var _self = this;
return FB.api(
"/me/friends",
function (data) {
_self.setFriendsCount(data.summary.total_count);
closure(data);
}
);
},
friends: null,
friendsCount: null,
setFriends: function (data) {
this.friends = data;
},
setFriendsCount: function (count) {
this.friendsCount = count;
}
};
When all the calls are finished I want to remove the loading overlay.
Something like:
(fbAPI.init()).finish(function(){
//do something
});
How can I achieve this?

Related

JS observer pattern

I try the observer pattern (by these two Urls: https://davidwalsh.name/pubsub-javascript, http://www.dofactory.com/javascript/observer-design-pattern) but listeners array is empty when I call the publish function.
main.pagination.event= (function () {
var listeners = [];
return {
subscribe: function (fn) {
listeners.push(fn);
return {
unsubscribe: function (fn) {
listeners= listeners.filter(
function (item) {
if (item !== fn) {
return item;
}
}
);
}
};
},
publish: function () {
//it's empty
listeners.forEach(function (item) {
item("...");
});
}
};
})();
main.pagination.init = function () {
$('ul li').click(function () {
main.pagination.event.publish();
};
};
main.update.init = function() {
var event = main.pagination.event.subscribe(main.update.listener);
};
main.update.listener = function (tbl) {
alert(tbl);
};
Thanks for help.
It is empty because you call subscribe after publish which does not contain anything inside the listeners array. Just change the order of the calls like so
main.update.listener = function (tbl) {
alert(tbl);
};
main.pagination.init = function () {
$('ul li').click(function () {
main.pagination.event.publish();
};
};
main.update.init = function() {
var event = main.pagination.event.subscribe(main.update.listener);
};
main.update.init(); // invoke subscribe first to add the listener to the array
main.pagination.init();

How to return templates from cache or ajax load?

In my code I try to load templates from cache. If template does not present in cache - load template from server by ajax. When loading is finished, I want to put template to cache and return it. Here is it:
var manager = function () {
return {
cache: [],
getTemplate: function (templateId) {
this.templateId = templateId;
if (this.cache[this.templateId]) {
return this.cache[this.templateId];
}
return this.loadTemplate();
},
loadTemplate: function() {
var
self = this;
$.get('/assets/templates/' + this.templateId + '.html', function (templateHtml) {
self.cache[self.templateId] = templateHtml;
return self.getTemplate(self.templateId);
});
}
}
}
var
manager = manager();
$('body').append( manager.getTemplate('template') );
I know that my code does not working because ajax request finished after function loadTemplate end. I think code can be fixed with deferred object but don't know how. Can anyone help me to find a solution?
There are two way of achieving your goal:
Promises (there are a lot of libs/shims). I'll rewrite it to ES6 just for the learning:
let manager = function () {
return {
cache: [],
getTemplate(id) {
let cache = this.cache;
return new Promise((resolve, reject) => {
if (cache[id]) {
resolve(cache[id]);
} else {
this.loadTemplate(id)
.then(template => {
cache[id] = template;
resolve(template);
})
.fail(reject);
}
});
},
loadTemplate(id) {
return $.get('/assets/templates/' + id + '.html');
}
}
};
let manager = manager();
manager.getTemplate('template').then((template) => {
$('body').append(template);
});
Callbacks:
let manager = function () {
return {
cache: [],
getTemplate(id, cb) {
let cache = this.cache;
if (cache[id]) {
cb(cache[id]);
} else {
this.loadTemplate(id)
.then(template => {
cache[id] = template;
cb(template);
});
}
},
loadTemplate(id) {
return $.get('/assets/templates/' + id + '.html');
}
}
};
let manager = manager();
manager.getTemplate('template', (template) => {
$('body').append(template);
});
Here's how you would do it, supporting all major browsers, and caching the requests too. This way you will only perform 1 request per template. (The other answers only cache the response).
var Manager = function() {
return {
cache: [],
getTemplate(id) {
var that = this;
if (that.cache[id] && that.cache[id].then){
console.log("Promise cache");
return that.cache[id]; //return promise from cache
}
return $.Deferred(function() {
var def = this;
if (that.cache[id]) {
console.log("Retrieved from cache!");
return def.resolve(that.cache[id]); //return cached template
}
that.cache[id] = def; //Cache promise
console.log("Retrieving template...");
that.loadTemplate(id).then(function(template) {
that.cache[id] = template;
def.resolve(template)
}).fail(function() {
def.reject();
});
return that.cache[id]; //return promise
}).promise();
},
loadTemplate(id) {
return $.get('https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js');
}
}
};
var manager = Manager();
manager.getTemplate('template').then(function(template){
console.log("loaded 1");
});
//This will use the promise from the first call (1 Request only)
manager.getTemplate('template').then(function(template){
console.log("loaded 2");
manager.getTemplate('template').then(function(template){
console.log("loaded 3"); //This will be retrieved fully from cache
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
As you are fetching the template via AJAX, you will be able to append the result only in AJAX success. So you need to pass the append logic as callback.Check the below code.
var manager = function () {
return {
cache: [],
getTemplate: function (templateId,callback) {
this.templateId = templateId;
if (this.cache[this.templateId]) {
callback(this.cache[this.templateId]);
}
this.loadTemplate(callback);
},
loadTemplate: function(callback) {
var
self = this;
$.get('/assets/templates/' + this.templateId + '.html', function (templateHtml) {
self.cache[self.templateId] = templateHtml;
callback(templateHtml)
});
}
}
}
var
manager = manager();
manager.getTemplate('template',function(result) {
$('body').append( result );
});
You may not need 2 functions to do this. So you can make it as one

could not update a variable in an angular service with ajax response data and use is to filter

i'm using the same code from this article (internationalization with angularjs)
...
but i need the "tables" variable to be fetched from an ajax request response using "$http get" but couldn't !! ... here is the code,
var xlat = angular.module('xlat', []);
xlat.factory('xlatService', function ($http) {
var currentLanguage = 'en';
// var tables = $.extend(true, {}, initialXlatTables);
var tables = {
'en': {
'textKeys.events': 'Events'
}
};
var service = {
getData: function () {
var req = {
method: 'GET',
url: 'local/en_US.php',
cache: true,
headers: {
'Content-Type': 'json'
}
};
$http(req).success(function (data) {
tables = data;
});
},
setCurrentLanguage: function (newCurrentLanguage) {
currentLanguage = newCurrentLanguage;
},
getCurrentLanguage: function () {
return currentLanguage;
},
xlat: function (label, parameters) {
service.getData();
if (parameters === null || $.isEmptyObject(parameters)) {
return tables[currentLanguage][label];
} else {
return $interpolate(tables[currentLanguage][label])(parameters);
}
}
};
return service;
});
but the variable "tables" does not change when i use the filter...
var xlat = angular.module('xlat', []);
xlat.filter('xlat', ['xlatService', function (xlatService) {
return function (label, parameters) {
return xlatService.xlat(label, parameters);
};
}]);
Try this one:
var xlat = angular.module('xlat', []);
xlat.filter('xlat', ['xlatService', function (xlatService) {
function myfiler(label, parameters) {
return xlatService.xlat(label, parameters);
};
myfiler.$stateful = true;
return myfilter;
}]);
Stateful filters -
https://code.angularjs.org/1.3.9/docs/guide/filter
Secod: you should load tables in factory method not in xlat function.

How do I access a method outside of object while using a constructor function?

I'm trying to get the member ID for a Trello account and then use that member ID in a constructor function to generate boards. My problem is that I can't access the member ID that I return outside of the object I created. How do I access the memberID outside of the TrellloConnect object?
Here is the code:
var TrelloConnect = {
init: function(config) {
this.config = config;
this.doAuthorize();
this.updateLogStatus();
this.bindLogIn();
this.bindLogOut();
this.whenAuthorized();
this.getMemberID();
},
bindLogIn: function() {
this.config.connectButton.click(function() {
Trello.authorize({
type: "redirect",
success: this.doAuthorize,
name: "WonderBoard",
expiration: "never"
});
});
},
bindLogOut: function() {
this.config.disconnectButton.click(function() {
var self = TrelloConnect;
Trello.deauthorize();
self.updateLogStatus();
});
},
doAuthorize: function() {
var self = TrelloConnect;
self.updateLogStatus();
},
updateLogStatus: function() {
var isLoggedIn = Trello.authorized();
this.config.loggedOutContainer.toggle(!isLoggedIn);
this.config.loggedInContainer.toggle(isLoggedIn);
},
whenAuthorized: function() {
Trello.authorize({
interactive: false,
success: TrelloConnect.doAuthorize
});
},
getMemberID: function() {
Trello.members.get("me", function(member) {
console.log(member.id);
return member.id;
});
}
};
TrelloConnect.init({
connectButton: $('#connectLink'),
disconnectButton: $('#disconnect'),
loggedInContainer: $('#loggedin'),
loggedOutContainer: $('#loggedout')
});
function Board(memberID) {
console.log(memberID);
}
var board = new Board(TrelloConnect.getMemberID());
Trello.members.get is an asynchronous function (i.e. it takes a callback instead of returning a value); you'll need to use a callback if you want to do something with the data that it fetches.
If you change getMemberID to take a callback
...
getMemberID: function(callback) {
Trello.members.get("me", function(member){
callback(member.id);
});
}
...
... then you could do something like this:
TrelloConnect.getMemberId(function(id){
new Board(id);
});

OO(object-oriented) javascript

I've a fair amount of experience with JavaScript, and for this new project I'm on (cms for blog with notions of profitability) I thought I'd step it up and write the JavaScript in an MVC fashion. I've been using a bit of backbone and underscore, but it isn't clicking mentally. any way, I've written a bit of code to handle some events/effects but it just doesn't work. If anyone could sort me out I'd really appreciate it.
// Semi Perfect grade 0 JS - Golden age
//partial View Objects | Events
var pshare_dock = {
actor: $("#share_dock"),
drag: function () {
this.actor.draggable();
}
}
pshare_dock.expand = function () {
this.actor.dblclick(function () {
$(this).toggleClass("share_close");
});
}
var pmenu = {
hover: function () {
$("ul.drop li.drop").hover(function () {
$(this).find('ul').fadeIn(1);
}, function () {
$(this).find('ul').hide();
})
},
navigate: function () {
$("a.ajx").click(function (e) {
var link;
var container = $("#content_pane");
e.preventDefault();
link = $(this).attr("href") + "#content_pane";
container.load(link);
})
}
}
var pcontent_pane = {}
var ppost = {}
var pdatabase_entry = {}
//Views
var Homepage = function () {
this.share_dock = function () {
new pshare_dock();
}
this.menu = function () {
new pmenu();
}
this.content_pane = function () {
new pcontent_pane();
}
this.posts = function () {
new ppost();
}
}
//Controller
var GoldenAgeRouter = Backbone.Router.extend({
routes: {
"!/": "defaultRoute",
"*actions": "defaultRoute"
},
defaultRoute: function (actions) {
var homeView = function () {
new Homepage();
}
}
})
$(document).ready(function () {
var Golden_age = function () {
new Homepage();
}
})
the question is essentially what all is wrong with this?
You're wrapping your instantiations in an anonymous function but not invoking them:
var Golden_age = new Homepage(); // Invoked.
var Golden_age = function(){ new Homepage(); } // Stored function, not invoked.

Categories

Resources