JS observer pattern - javascript

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

Related

Pass dynamic parameters to callback function in a loop

I wanted to set some jQuery animatios dynamically.
The code:
function anim(data) {
for (index in data) {
(function(){
var props = {};
props[data[index].property] = data[index].value;
data[index].elem.animate(
props,
500,
function() {
data[index].callback();
}
);
})();
}
}
var data =[
{
elem: elem1,
property: 'prop1',
value: 'val1',
callback: function() {
console.log('callback1');
}
},
{
elem: elem2,
property: 'prop2',
value: 'val2',
callback: function() {
console.log('callback2');
}
},
];
anim(data);
The problem is binding callbacks. When the callback is fired, data[index] is not available in current scope. Can somebody tell me how to set those callback propery?
Here you used a closure of Immediately-invoked function expression. You have to pass data[index] as parameter.
(function(dindex){
var props = {};
props[dindex.property] = dindex.value;
dindex.elem.animate(
props,
500,
function() {
dindex.callback();
}
);
})(data[index]);
You can try like this as an alternative,
function anim(data) {
$.each(data, function(x,y){
var props = {};
props[y.property] =y.value;
y.elem.animate(
props,
500,
function() {
y.callback();
}
);
});
}

Do something after all FB API calls finish

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?

Call functions from function inside an object in a javascript loop

I have a javascript object with some functions inside, I wish I could call them in a loop, something like this:
funcs: {
func1: function() {
return true;
},
func2: function() {
return false;
}
}
for(func in funcs) {
console.log(funcs[func]());
console.log(funcs[func].call());
}
Both work. But the declaration of your object is not correct. It is var object = { /*something*/};
var funcs = {
func1: function() {
return true;
},
func2: function() {
return false;
}
};
for(func in funcs) {
console.log(funcs[func]());
console.log(funcs[func].call());
}
Output
true
true
false
false

Javascript: Mixing constructor pattern and Revealing Module Pattern

Is there any way I can do have a Javascript class that extends an object that was created through the revealing module pattern? I tried the following code, but is there away to achieve the same thing?
sv.MergeQuestionViewModel = function () {
this = sv.QuestionDetailViewModal();
this.init($("#mergeQuestionModel"));
};
sv.QuestionDetailViewModal = function () {
var $el,
self = this,
_question = ko.observable(),
_status = new sv.Status();
var _init = function (el) {
$el = el;
$el.modal({
show: false,
backdrop: "static"
});
};
var _show = function () {
$el.modal('show');
};
var _render = function (item) {
_question(new sv.QuestionViewModel(item));
_show();
};
var _reset = function () {
_question(null);
_status.clear();
};
var _close = function () {
$el.modal('hide');
_reset();
};
return {
init: _init,
show: _show,
render: _render,
reset: _reset,
close: _close
};
};
You could use jQuery.extend to achive this behaviour.
sv.MergeQuestionViewModel = function () {
$.extend(this, sv.QuestionDetailViewModal);
this.init($("#mergeQuestionModel"));
};
sv.QuestionDetailViewModal = (function () {
var el,
_init = function($el) {
el = $el;
console.log('init', el);
},
_render = function() {
console.log('render', el);
};
return {
init : _init,
render : _render
};
}());
var view = new sv.MergeQuestionViewModel();
view.render();
Test it on http://jsfiddle.net/GEGNM/

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