Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
HenrikJoreteg committed Feb 15, 2011
0 parents commit 42a1c75
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 0 deletions.
293 changes: 293 additions & 0 deletions capsule.models.js
@@ -0,0 +1,293 @@
/*global Backbone _ uuid */
(function(){
// Initial Setup
// -------------

// The top-level namespace. All public Backbone classes and modules will
// be attached to this. Exported for both CommonJS and the browser.
var Capsule,
server = false;

if (typeof exports !== 'undefined') {
var Backbone = require('./backbone'),
_ = require('underscore')._,
uuid = require('../packages/uuid');
Capsule = exports;
server = true;
} else {
var Backbone = this.Backbone,
_ = this._;

Capsule = this.Capsule = {};
}

Capsule.models = {};
//Capsule.collections = {};

Capsule.Model = Backbone.Model.extend({
register: function () {
var self = this;
if (server) {
var id = uuid();
this.id = id;
this.set({id: id});
}
if (this.id && !Capsule.models[this.id]) Capsule.models[this.id] = this;
this.bind('change:id', function (model) {
if (!Capsule.models[this.id]) Capsule.models[model.id] = self;
});
},

modelGetter: function (id) {
return Capsule.models[id];
},

toggle: function (attrName) {
var change = {};
change[attrName] = !(this.get(attrName));
this.setServer(change);
},

deleteServer: function () {
socket.send({
event: 'delete',
id: this.id
});
},

// this lets us export js functions and not just attributes to
// the template
toTemplate: function () {
var result = this.toJSON(),
that = this;

// by default we'll use the cid as the html ID
result.htmlId = this.cid;

if (this.templateHelpers) {
_.each(this.templateHelpers, function (val) {
result[val] = _.bind(that[val], that);
});
}

return result;
},

// builds and return a simple object ready to be JSON stringified
xport: function (opt) {
var result = {},
settings = _({
recurse: true
}).extend(opt || {});

function process(targetObj, source) {
targetObj.id = source.id || null;
targetObj.cid = source.cid || null;
targetObj.attrs = source.toJSON();
_.each(source, function (value, key) {
// since models store a reference to their collection
// we need to make sure we don't create a circular refrence
if (settings.recurse) {
if (key !== 'collection' && source[key] instanceof Backbone.Collection) {
targetObj.collections = targetObj.collections || {};
targetObj.collections[key] = {};
targetObj.collections[key].models = [];
targetObj.collections[key].id = source[key].id || null;
_.each(source[key].models, function (value, index) {
process(targetObj.collections[key].models[index] = {}, value);
});
} else if (source[key] instanceof Backbone.Model) {
targetObj.models = targetObj.models || {};
process(targetObj.models[key] = {}, value);
}
}
});
}

process(result, this);

return result;
},

// rebuild the nested objects/collections from data created by the xport method
mport: function (data, silent) {
function process(targetObj, data) {
targetObj.id = data.id || null;
targetObj.set(data.attrs, {silent: silent});
// loop through each collection
if (data.collections) {
_.each(data.collections, function (collection, name) {
targetObj[name].id = collection.id;
Capsule.models[collection.id] = targetObj[name];
_.each(collection.models, function (modelData, index) {
var newObj = targetObj[name]._add({}, {silent: silent});
process(newObj, modelData);
});
});
}

if (data.models) {
_.each(data.models, function (modelData, name) {
process(targetObj[name], modelData);
});
}
}

process(this, data);

return this;
},

publishProxy: function (data) {
this.trigger('publish', data);
},

publishChange: function (model, val, options, attr) {
var event = {};

if (model instanceof Backbone.Model) {
event = {
event: 'change',
id: model.id,
data: model.attributes
};
} else {
console.error('event was not a model', e);
}

this.trigger('publish', event);
},

publishAdd: function (model, collection) {
var event = {
event: 'add',
data: model.xport(),
collection: collection.id
};

this.trigger('publish', event);
},

publishRemove: function (model, collection) {
var event = {
event: 'remove',
id: model.id
};
this.trigger('publish', event);
},

ensureRequired: function () {
var that = this;
if (this.required) {
_.each(this.required, function (type, key) {
that.checkType(type, that.get(key), key);
});
}
},

validate: function (attr) {
var that = this;
_.each(attr, function (value, key) {
if (that.required && that.required.hasOwnProperty(key)) {
var type = that.required[key];
that.checkType(type, value, key);
}
});
},

checkType: function (type, value, key) {
var validator;

type = type.toLowerCase();

switch (type) {
case 'string': validator = _.isString; break;
case 'boolean': validator = _.isBoolean; break;
case 'date': validator = _.isDate; break;
case 'array': validator = _.isArray; break;
case 'number': validator = _.isNumber; break;
}

// run it
if (!validator(value)) {
throw "The '" + key + "' property of a '" + this.type + "' must be a '" + type + "'. You gave me '" + value + "'.";
}
},

setServer: function(attrs, options) {
socket.send({
event: 'set',
id: this.id,
change: attrs
});
}
});

Capsule.Collection = Backbone.Collection.extend({
register: function () {
var self = this;
if (server) {
var id = uuid();
this.id = id;
}
if (this.id && !Capsule.models[this.id]) Capsule.models[this.id] = this;
},

addServer: function (data) {
socket.send({
event: 'add',
id: this.id,
data: data
});
},

registerRadioProperties: function () {
var collection = this;

if (this.radioProperties) {
_.each(this.radioProperties, function (property) {
collection.bind('change:' + property, function (changedModel) {
if (changedModel.get(property)) {
collection.each(function (model) {
var tempObj = {};
if (model.get(property) && model.cid !== changedModel.cid) {
tempObj[property] = false;
model.set(tempObj);
}
});
}
});

collection.bind('add', function (addedModel) {
var tempObj = {};

// if we're adding stuff we need to make sure the added items don't violate the
// radio property rule if it's already set.
if (collection.select(function (model) {
return model.get(property);
}).length > 1) {
tempObj[property] = false;
addedModel.set(tempObj);
}
});
});
}
},

filterByProperty: function (prop, value) {
return this.filter(function (model) {
return model.get(prop) === value;
});
},

findByProperty: function (prop, value) {
return this.find(function (model) {
return model.get(prop) === value;
});
},

parse: function (resp) {
return resp.items;
}
});
})();
87 changes: 87 additions & 0 deletions capsule.views.js
@@ -0,0 +1,87 @@
(function(){
// Initial Setup
// -------------

// The top-level namespace. All public Backbone classes and modules will
// be attached to this. Exported for both CommonJS and the browser.
var Capsule,
$ = this.jQuery || this.Zepto || function(){};

if (typeof exports !== 'undefined') {
var Backbone = require('./backbone'),
_ = require('underscore')._;
Capsule = exports;
} else {
var Backbone = this.Backbone,
_ = this._;
Capsule = this.Capsule = {};
}


Capsule.View = Backbone.View.extend({
handleBindings: function () {
var self = this;

// content bindings
if (this.contentBindings) {
_.each(this.contentBindings, function (selector, key) {
self.model.bind('change:' + key, function () {
var el = (selector.length > 0) ? self.$(selector) : $(self.el);

el.html(self.model.get(key));
});
});
}

// class bindings
if (this.classBindings) {
_.each(this.classBindings, function (selector, key) {
self.model.bind('change:' + key, function () {
var newValue = self.model.get(key),
el = (selector.length > 0) ? self.$(selector) : $(self.el);

// if it's a boolean value, just add/remove 'active' class
if (_.isBoolean(newValue)) {
if (newValue) {
el.addClass(key);
} else {
el.removeClass(key);
}
// otherwise remove the previous value and add the new one as a class.
} else {
el.removeClass(self.model.previous(key)).addClass(newValue);
}
});
});
}
return this;
},

addReferences: function (hash) {
var item;
for (item in hash) {
this['$' + item] = $(hash[item], this.el);
}
},

autoSetInputs: function () {
this.$(':input').keyup(_(this.genericKeyUp).bind(this));
},

genericKeyUp: function (e) {
var res = {},
target = $(e.target);
if (e.which === 13 && e.target.tagName.toLowerCase() === 'input') target.blur();
res[type = target.data('type')] = target.val();
this.model.setServer(res);
return false;
},

basicRender: function (templateKey) {
var newEl = ich[this.template || templateKey](this.model.toTemplate());
$(this.el).replaceWith(newEl);
this.el = newEl;
this.delegateEvents();
}
});
})();
Empty file added license
Empty file.
Empty file added readme
Empty file.

0 comments on commit 42a1c75

Please sign in to comment.