(function($) { var Alpaca = $.alpaca; Alpaca.Observable = Base.extend( { constructor: function(scope, id) { var _this = this; this.base(); this.id = scope + "-" + id; this.value = null; this.subscribers = {}; // array that contains observable whose value is dependent on our value this.dependentOnUs = {}; // privileged functions this.notifySubscribers = function(prior) { var _this = this; $.each(this.subscribers, function(id, handler) { handler(_this.value, prior); }); }; this.notifyDependents = function(prior) { $.each(this.dependentOnUs, function(key, observer) { observer.onDependencyChange(); }); }; // assume null value function this.valueFunction = null; }, setValueFunction: function(valueFunction) { this.valueFunction = valueFunction; this.onDependencyChange(); }, /** * Registers a handler which acts as a subscriber. When this observable value changes, * the handler method is raised. * * @param f */ subscribe: function(id, handler) { if (!this.isSubscribed(id)) { this.subscribers[id] = handler; } }, unsubscribe: function(id) { delete this.subscribers[id]; }, isSubscribed: function(id) { return (this.subscribers[id] ? true: false); }, markDependentOnUs: function(observable) { this.dependentOnUs[observable.id] = observable; }, /** * Fired when one of our dependents has changed its value. */ onDependencyChange: function() { var prior = this.get(); // if we have a value calculation function, fire it if (this.valueFunction) { var current = this.valueFunction(); // if the value changed, notify if (prior != current) { this.set(current); } } }, set: function(value) { var prior = this.value; this.value = value; // notify all dependents (observers that depend on our value) this.notifyDependents(prior); // notify all subscribers of the updated value this.notifySubscribers(prior); }, get: function(_default) { var v = this.value; if (!v) { v = _default; } return v; }, clear: function() { var prior = this.value; delete this.value; // notify all dependents (observers that depend on our value) this.notifyDependents(prior); // notify all subscribers of the updated value this.notifySubscribers(prior); } }); })(jQuery);