Skip to content
Browse files

first commit

  • Loading branch information...
0 parents commit 42a1c75cbd666cb11ac04d6db5e9110c0e37c3f3 @HenrikJoreteg committed
Showing with 380 additions and 0 deletions.
  1. +293 −0 capsule.models.js
  2. +87 −0 capsule.views.js
  3. 0 license
  4. 0 readme
293 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 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();
+ }
+ });
+})();
0 license
No changes.
0 readme
No changes.

0 comments on commit 42a1c75

Please sign in to comment.
Something went wrong with that request. Please try again.