Utilities: Datastruct |
|
Cool stuff. |
(function() {
"use strict"; |
CoffeeScript usage |
|
|
|
Creating getters/setters |
|
|
|
datastruct() |
|
Applies the mixin to the given class |
function datastruct(klass) { |
properties |
|
Key/value list of properties and their respective options. |
klass.properties = {}; |
property(name, options) |
|
Makes a property. Creates sets/gets if needed.
Also handles the case where you pass more than one property as |
klass.property = function(name, options) {
if ((arguments.length === 1) && (typeof name === 'object')) { /* [1] */
var props = name;
for (var key in props) {
if (props.hasOwnProperty(key)) {
var value = props[key];
klass.property(key, value);
}
}
return this;
}
options || (options = {});
klass.properties[name] = options;
if ((options.get) || (options.set)) {
Object.defineProperty(klass.prototype, name, {
get: options.get,
set: options.set
});
}
return this;
}; |
set() |
|
Yeah. |
klass.prototype.set = function(source) { |
|
if (arguments.length === 1) {
var source = arguments[0];
source || (source = {});
for (var prop in klass.properties) {
if (klass.properties.hasOwnProperty(prop)) {
var options = klass.properties[prop];
if (source.hasOwnProperty(prop)) {
this.set(prop, source[prop]);
} |
|
else if ((typeof options['default'] !== 'undefined') &&
(typeof this[prop] === 'undefined')) {
this.set(prop, clone(options['default']));
}
}
}
} |
|
else if (arguments.length === 2) {
var key = arguments[0];
var value = arguments[1];
var propOptions = klass.properties[key];
if (propOptions) { |
|
if ((propOptions.type) && (value.constructor !== propOptions.type)) {
value = new propOptions.type(value, this);
}
else if (propOptions.subtype) {
value = coerceObjectOrArray(value, propOptions.subtype, this);
}
this[key] = value;
}
}
return this;
}; |
toJSON() |
|
Implement this so that |
klass.prototype.toJSON = function() {
var object = {};
for (var prop in klass.properties) {
if (klass.properties.hasOwnProperty(prop)) {
var options = klass.properties[prop];
if (!options.hidden) {
object[prop] = this[prop];
}
}
}
return object;
};
return klass;
}; |
Private helpers |
|
coerceObjectOrArray() |
|
Casts the values of |
function coerceObjectOrArray(object, type, self) {
if (object.constructor === Array) {
var re = [];
for (var i=0, len=object.length; i<len; ++i) {
re[i] = new type(object[i], self);
}
return re;
}
else if (!object) {
return object; // Probably null
}
else if (typeof object === 'object') {
var re = {};
for (var key in object) {
if (object.hasOwnProperty(key)) {
var value = object[key];
re[key] = new type(value, self);
}
}
return re;
}
} |
clone() |
|
Creates a shallow clone of the object |
function clone(obj) {
if ((!obj) || (typeof obj !== 'object')) return obj;
return (obj.constructor === Array) ? obj.slice() : extend({}, obj);
} |
extend() |
|
Extenda given object |
function extend(obj, source) {
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
obj[prop] = source[prop];
}
}
return obj;
}
if (typeof module !== 'undefined') {
module.exports = datastruct;
}
})();
|