Skip to content

Instantly share code, notes, and snippets.

@bryanforbes
Created August 2, 2013 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bryanforbes/6140180 to your computer and use it in GitHub Desktop.
Save bryanforbes/6140180 to your computer and use it in GitHub Desktop.
define([
'dojo/declare',
'dojo/promise/when'
], function (declare, when) {
var slice = [].slice,
nop = function () {};
function createNotifier(object) {
var listenerMap = {},
objectListeners = [];
function notify(name, newValue, oldValue) {
var listeners = listenerMap[name];
if (listeners) {
listeners.forEach(function (listener) {
listener.handler.call(object, newValue, oldValue);
});
}
objectListeners.forEach(function (listener) {
listener.handler.call(object, name, newValue, oldValue);
});
}
notify.register = function (property, listener) {
var listeners = listenerMap[property];
if (!listener && typeof property === 'function') {
listener = property;
listeners = objectListeners;
}
else {
if (!listeners) {
listeners = listenerMap[property] = [];
}
}
listener = { handler: listener };
listeners.push(listener);
var handle = {
remove: function () {
var index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
handle.remove = nop;
}
};
return handle;
};
return notify;
}
return declare(null, {
postscript: function (params) {
if (params) {
this.set(params);
}
},
_get: function (property) {
return this[property];
},
get: function (property) {
var getter = this['_get_' + property];
if (typeof getter === 'function') {
return getter.apply(this, slice.call(arguments, 1));
}
else {
return this._get(property);
}
},
_set: function (property, value) {
var oldValue = this.get(property),
result = this[property] = value;
if (this.__notify && value !== oldValue) {
var self = this;
return when(result, function () {
self.__notify(property, value, oldValue);
});
}
return result;
},
set: function (property, value) {
if (typeof property === 'object') {
var results = {};
for (var key in property) {
results[key] = this.set(key, property[key]);
}
return results;
}
var setter = this['_set_' + property],
result;
if (typeof setter === 'function') {
result = setter.apply(this, slice.call(arguments, 1));
}
else {
result = this._set(property, value);
}
return result;
},
listen: function (property, listener) {
var notify = this.__notify;
if (!notify) {
Object.defineProperty(this, '__notify', {
configurable: false,
enumerable: false,
writable: false,
value: notify = createNotifier(this)
});
}
return notify.register(property, listener);
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment