Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- lots of fixes

- can reset models
- passes JSHint
- routes can have square brackets for optional components
- change function to fire change events on mvc.Model
- ajax sync now has urlifyString
  • Loading branch information...
commit 4ccc99fb58f205a6648b9f05a3af742a149d005c 1 parent 3dfbe56
@rhysbrettbowen authored
View
9 README.md
@@ -115,6 +115,15 @@ you can then register your object with the mediator and the messages that you ma
### changelog ###
+#### v0.8 ####
+
+- lots of fixes
+- can reset models
+- passes JSHint
+- routes can have square brackets for optional components
+- change function to fire change events on mvc.Model
+- ajax sync now has urlifyString
+
#### v0.7 ###
- add in mvc.Mediator
View
8 collection.js
@@ -112,7 +112,7 @@ mvc.Collection.prototype.getLength = function() {
mvc.Collection.prototype.sort = function(silent) {
var changeOrder = false;
if(this.comparator_) {
- var comp = this.comparator_
+ var comp = this.comparator_;
this.models_.sort(function(a, b) {
var ret = comp(a, b);
if(ret < 0)
@@ -143,7 +143,7 @@ mvc.Collection.prototype.add = function(model, ind, silent) {
goog.events.listen(model, goog.events.EventType.UNLOAD,
function(e){
goog.array.remove(this.models_, e.target);
- this.sort()
+ this.sort();
}, false, this);
this.sort(true);
if(!silent)
@@ -192,7 +192,7 @@ mvc.Collection.prototype.getById = function(id) {
return /** @type {mvc.Model} */(goog.array.find(this.models_, function(model) {
return model.get('id') == id;
}));
-}
+};
/**
* get all the models, optionally filter by function
@@ -218,4 +218,4 @@ mvc.Collection.prototype.at = function(index) {
mvc.Collection.prototype.clear = function() {
this.models_ = [];
-}
+};
View
11 control.js
@@ -19,8 +19,11 @@ goog.require('goog.ui.Component');
* @extends {goog.ui.Component}
*/
mvc.Control = function(model) {
+ goog.base(this);
this.setModel(model);
};
+goog.inherits(mvc.Control, goog.ui.Component);
+
/**
* Functions that can be passed to the mvc.Model.bind
@@ -33,7 +36,6 @@ mvc.Control.Fn = {
CLASS: goog.dom.classes.add
};
-goog.inherits(mvc.Control, goog.ui.Component);
// backbone.js views are just like goog.ui.component, this is more of an interface
@@ -45,7 +47,7 @@ mvc.Control.prototype.remove = function() {
this.dispose();
};
-mvc.Control.prototype.render = function(parent) {
+mvc.Control.prototype.show = function(parent) {
this.decorate(parent);
return this;
};
@@ -56,9 +58,6 @@ mvc.Control.prototype.createDom = function() {
this.setElementInternal(goog.dom.createDom("DIV"));
};
-mvc.Control.prototype.enterDocument = function() {
- this.init();
-};
/**
* pass an object where the key is "eventType .className" and the value is the
@@ -71,7 +70,7 @@ mvc.Control.prototype.enterDocument = function() {
*/
mvc.Control.prototype.delegateEvents = function(events) {
goog.object.forEach(events, function(val, key) {
- goog.events.listen(this.getElement(), key.replace(/\s.*/,''), function(e) {
+ this.getHandler().listen(this.getElement(), key.replace(/\s.*/,''), function(e) {
if(goog.dom.classes.has(e.target, key.replace(/.*\./,'')))
events[key](e);
}, false, this);
View
37 model.js
@@ -56,7 +56,7 @@ mvc.Model = function(options) {
this.cid_ = goog.getUid(this);
- goog.object.forEach((options.attr || []), function(val, name) {
+ goog.object.forEach(defaults.attr, function(val, name) {
this.attr_[name] = val;
}, this);
@@ -77,7 +77,14 @@ mvc.Model.prototype.toJson = function() {
mvc.Model.prototype.setSync = function(sync) {
this.sync_ = sync;
-}
+};
+
+mvc.Model.prototype.reset = function(silent) {
+ this.prev_ = this.attr_;
+ this.attr_ = {};
+ if(!silent)
+ this.change();
+};
/**
* @param {string} key
@@ -87,21 +94,21 @@ mvc.Model.prototype.get = function(key) {
if(this.formats_[key])
return this.formats_[key].fn();
return goog.object.get(this.attr_, key, null);
-}
+};
/**
* @return {boolean}
*/
mvc.Model.prototype.isNew = function() {
return !this.get('id');
-}
+};
/**
* @param {mvc.model.Schema} schema
*/
mvc.Model.prototype.setSchema = function(schema) {
this.schema_ = schema;
-}
+};
/**
* @param {string} key
@@ -115,7 +122,7 @@ mvc.Model.prototype.has = function(key) {
* set either a map of key values or a key value
*
* @param {Object|string} key object of key value pairs to set, or the key
- * @param {Object=} val to use if the key is a string
+ * @param {*=} val to use if the key is a string
* @param {boolean=} silent true if no change event should be fired
* @return {boolean}
*/
@@ -130,7 +137,7 @@ mvc.Model.prototype.set = function(key, val, silent) {
this.prev_ = goog.object.clone(this.attr_);
}
goog.object.forEach(key, function(val, key) {
- if(!this.schema_ || val == undefined) {
+ if(!this.schema_ || !goog.isDef(val)) {
this.attr_[key] = val;
} else {
var validate = this.schema_.validate(key, val);
@@ -196,7 +203,7 @@ mvc.Model.prototype.meta = function(attr, require, fn) {
return this.get(val);
}, this));
}, this)};
-}
+};
/**
* @param {string} key
@@ -224,6 +231,10 @@ mvc.Model.prototype.prev = function(key) {
return goog.object.get(this.prev_, key, null);
};
+mvc.Model.prototype.change = function() {
+ this.dispatchEvent(goog.events.EventType.CHANGE);
+};
+
/**
* returns object of changed attributes and their values
*/
@@ -263,7 +274,7 @@ mvc.Model.prototype.dispose = function() {
this.sync_.del(this);
this.dispatchEvent(goog.events.EventType.UNLOAD);
this.disposeInternal();
-}
+};
/**
* reads an object fomr an external source using sync
@@ -276,7 +287,7 @@ mvc.Model.prototype.fetch = function(callback, silent) {
if(status == 200) {
this.ext_ = goog.object.clone(data);
goog.array.forEach(goog.object.getKeys(this.attr_), function(key) {
- if(!key in data)
+ if(!(key in data))
this.unset(key, silent);
}, this);
goog.object.forEach(data, function(val, key) {
@@ -303,7 +314,7 @@ mvc.Model.prototype.save = function() {
mvc.Model.prototype.getBinder = function(key) {
return goog.bind(this.set, this, key);
-}
+};
/**
* Allows easy binding of a model's attributre to an element or a function.
@@ -315,15 +326,13 @@ mvc.Model.prototype.getBinder = function(key) {
* if no name is passed (null or undefined) then the operation will be run on
* any change to the model and pass in the model
*
- * @param {string|Array.<string>} name
+ * @param {?string} name
* @param {Function|*} el
* @param {Function|*=} fn
*/
mvc.Model.prototype.bind = function(name, el, fn) {
goog.events.listen(this, goog.events.EventType.CHANGE, function(e) {
var changes = e.target.getChanges();
- if(goog.isString(name))
- name = [name];
if(name in changes || !goog.isDefAndNotNull(name)) {
if(goog.isFunction(el)) {
goog.bind(el, /** @type {Function} */(fn))(changes[name], this);
View
6 model_test.js
@@ -9,15 +9,15 @@ var setUp = function() {
simpleModel = new mvc.Model({attr:
{'a':'exists'}});
emptyModel = new mvc.Model();
-}
+};
var testSimpleModel = function() {
assertNotNullNorUndefined("New model created", simpleModel);
assertEquals("Should be able to get 'a'", simpleModel.get('a'), 'exists');
assertNull("Should return null", simpleModel.get('b'));
- assertEquals("Should be able to change 'a'", simpleModel.set('a', 'changed').get('a'), 'changed')
+ assertEquals("Should be able to change 'a'", simpleModel.set('a', 'changed').get('a'), 'changed');
assertEquals("Should be able to add new attribute 'b'", simpleModel.set('b', 'new').get('b'), 'new');
- assertUndefined("Should be able to remove attribute 'b'", simpleModel.unset('b').get('b'))
+ assertUndefined("Should be able to remove attribute 'b'", simpleModel.unset('b').get('b'));
};
var testEmptyModel = function() {
View
6 router.js
@@ -40,9 +40,9 @@ mvc.Router.prototype.navigate = function(fragment) {
*/
mvc.Router.prototype.route = function(route, fn) {
if(goog.isString(route))
- route = new RegExp('^' + goog.string.regExpEscape(route).replace(/:\w+/g, '(\w+)').replace(/\*\w+/g, '(.*?)') + '$');
+ route = new RegExp('^' + goog.string.regExpEscape(route).replace(/\\:\w+/g, '(\\w+)').replace(/\\\*/g, '(.*)').replace(/\\\[/g,"(").replace(/\\\]/g,")?") + '$');
this.routes_.push({route: route, callback: fn});
-}
+};
/**
* @private
@@ -53,6 +53,6 @@ mvc.Router.prototype.onChange_ = function(e) {
var args = route.route.exec(fragment);
if(!args)
return;
- route.callback.call(this, args);
+ route.callback.apply(this, args);
}, this);
};
View
10 store.js
@@ -13,7 +13,7 @@ goog.require('goog.object');
/**
* @constructor
- * @param {function(new:mvc.Model,...*)} opt_defaultModel
+ * @param {function(new:mvc.Model)=} opt_defaultModel
*/
mvc.Store = function(opt_defaultModel) {
this.cache_ = {};
@@ -25,15 +25,16 @@ mvc.Store = function(opt_defaultModel) {
* and the type of model to create if none found in cache
*
* @param {string=} input the model's id
- * @param {function(new:mvc.Model,...*)=} the type of model to create
+ * @param {function(new:mvc.Model)=} opt_model type of model to create
+ * @return {mvc.Model}
*/
mvc.Store.prototype.get = function(input, opt_model) {
if(this.cache_[input])
return this.cache_[input];
var modelConstructor = opt_model || this.default_;
- var model = new mod();
+ var model = new modelConstructor();
if(input)
- ret.set('id', input);
+ model.set('id', input, true);
this.cache_[input || model.cid_] = model;
var list = goog.events.listen(model, goog.events.EventType.CHANGE,
function() {
@@ -44,6 +45,7 @@ mvc.Store.prototype.get = function(input, opt_model) {
goog.events.unlistenByKey(list);
}
}, false, this);
+ return model;
};
/**
View
38 sync/ajax.js
@@ -12,7 +12,7 @@ goog.require('goog.Uri.QueryData');
*/
mvc.AjaxSync = function(url) {
- var baseFunction = function(model){return ""};
+ var baseFunction = function(model){return "";};
this.baseUrls_ = {
create: baseFunction,
@@ -29,25 +29,40 @@ mvc.AjaxSync = function(url) {
del: url
};
}
- goog.object.extend(this.baseUrls_, goog.object.map(url, function(val) {
- if(goog.isString(val))
- return function(model) {
- return val.replace(/:(\w+)/g, function(id) {
- return model.get(id);
- });};
- return val;
- }));
+ goog.object.extend(this.baseUrls_, goog.object.map(url, this.urlifyString));
this.xhr_ = new goog.net.XhrManager();
this.sendCount_ = 0;
};
/**
+ * takes a string defining a url where :attribute will return that models
+ * attribute. e.g.
+ *
+ * var obj = new mvc.Model({attrs:{'id': 'fred'}});
+ * var urlGen = urlifyString("/object=:id/blah");
+ * urlGen(obj); // returns "/object=fred/blah"
+ *
+ *
+ * @param {string} val
+ * @return {function(mvc.Model):string}
+ */
+mvc.AjaxSync.prototype.urlifyString = function(val) {
+ if(goog.isString(val))
+ return function(model) {
+ return val.replace(/:(\w+)/g, function(id) {
+ return model.get(id.substring(1));
+ });};
+ return /** @type {function(mvc.Model):string} */(val);
+};
+
+/**
* @inheritDoc
*/
mvc.AjaxSync.prototype.create = function(model, callback) {
this.xhr_.send(""+(this.sendCount_++), this.baseUrls_.create(model),
- "POST", goog.Uri.QueryData.createFromMap(model.toJson()).toString(), undefined, undefined,
+ "POST", goog.Uri.QueryData.createFromMap(model.toJson()).toString(),
+ undefined, undefined,
goog.bind(this.onCreateComplete_, this, model, callback));
};
@@ -65,7 +80,8 @@ mvc.AjaxSync.prototype.read = function(model, callback) {
*/
mvc.AjaxSync.prototype.update = function(model, callback) {
this.xhr_.send(""+(this.sendCount_++), this.baseUrls_.update(model),
- "PUT", goog.Uri.QueryData.createFromMap(model.toJson()).toString(), undefined, undefined,
+ "PUT", goog.Uri.QueryData.createFromMap(model.toJson()).toString(),
+ undefined, undefined,
goog.bind(this.onUpdateComplete_, this, model, callback));
};
Please sign in to comment.
Something went wrong with that request. Please try again.