Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial documentation and versioning

  • Loading branch information...
commit cb17d0ba8b9e3ebccdc03379e311858dabcf8b3f 1 parent b310e1a
@rhysbrettbowen authored
View
58 README.md
@@ -1,31 +1,67 @@
# goog.mvc #
-a backbone.js inspired MVC library using the google closure library
+An MVC library which uses the Google Closure library for use with the Closure Compiler
-mapping:
+The folder should be put in your project directory and the path passed to the closure compiler
+
+to use a module, use
+
+```javascript
+goog.require('packageName');
+```
## mvc.Model ##
-The mvc.Model behaves much the same way as the Backbone.Model.
+The model is the main component. It allows you to store data and sends out change events when it changes (it extends goog.events.EventTarget). It also communicates with the data store through mvc.Sync
+
+You can instantiate a new model directly, or you may wish to create a new type of model that inherits from mvc.Model like so:
-One major difference is that for validation the mvc.Model takes in an mvc.model.Schema that provides functions for validation. The validation can either be a string stating type ("string", "number", etc), a regex, or a function that takes the value and the model to test and returns true or false.
+```javascript
+goog.require('mvc.Model');
+/**
+ * @constructor
+ * @inheritDoc
+ */
+var complexModel = function(attr, schema) {
+ goog.base(this, attr, schema);
+};
+goog.inherits(complexModel, mvc.Model);
+```
+Any setup would go in the constructor function and you can override methods and add new methods of your own.
-## mvc.Control || goog.ui.Compnent ##
+When creating a new model instance, the constructor takes two optional arguments. The first is a map or object with the initial keys and values of the model. The second is a schema which will be described in the next section
-The mvc.Control is basically a goog.ui.Component.
+You should always use the get() and set() functions when dealing with the model's data. These functions take care of saving old data and publishing change events
-There is a little syntactic sugar to make it more similar to Backbone.js, but the only extra useful method is delegateEvents which takes in an object like {"#{eventType} .#{className}" : function(Event)}. This binds events in the component to functions. If you're using a different goog.ui that inherits from goog.ui.Component then you can just bring over the function like so: yourObject.delegateEvents = mvc.Control.prototype.delegateEvents
+## mvc.model.Schema ##
+
+A schema can be set for a model. The schema takes in an object or map of keys and functions. The functions take in a value and return true or false. When a schema is passed in to a model, the model will use this to validate any values trying to be set, and won't add in data if a function returns false. You can also pass in the following strings to check for the type of input: "number", "string", "array"
## mvc.Collection ##
-a Collection in goog.mvc is also a model which means that it can have it's own attributes and schema. It can take in a comparator function to keep the models in order
+A mvc.Collection extends mvc.Model and so has all of it's properties. Also a collection can contain an array of models that belong to it. A collection can keep these models in an order if given a comparator function and will also listen to changes and emit a change if any model it contains fires a change event.
-## mvc.Router ##
+## mvc.Control ##
+
+the closure library already provides goog.ui.Component which is a great controller. If you use Backbone.js you'll probably recognise it as the view. mvc.Control adds in two methods, delegateEvents and getEls. These are convenience functions. The getEls allows you to use simple string selectors to get a handle for the elements under the component and delegateEvents gives an easier interface for listening to events in the component. If you want to use a different class in the library that already extends goog.ui.Component you can stil use these functions by adding them to your classes prototype like so:
-works the same as Backbone.Router, but uses goog.History instead of Backbone.History
+```javascript
+goog.require('mvc.Control');
+
+myClass.prototype.delegateEvents = mvc.Control.prototype.delegateEvents;
+myClass.prototype.getEls = mvc.Control.prototype.getEls;
+```
## mvc.Sync ##
-This is an interface and should deal with the models talking to the data store. Simple implementations have been provided for ajax and localstorage
+This is an interface that should have a custom implementation. Two simple implementations have been given called mvc.sync.Ajax and mvc.sync.Local. The purpose of sync is to be the glue between the model and the dataStore.
+
+## mvc.Router ##
+
+mvc.Router uses goog.History and hash tokens to hold and manage the state of the application. You can define a route with a regular expression that will fire custom events when a certain route comes on the URL.
+
+### changelog ###
+
+v0.1 - initial documentation and versioning
View
4 collection.js
@@ -1,5 +1,7 @@
+// v0.1
goog.provide('mvc.Collection');
+goog.require('mvc.Model');
goog.require('goog.events.EventTarget');
/**
@@ -27,7 +29,7 @@ mvc.Collection = function(models) {
}, this);
};
-goog.inherits(mvc.Collection, goog.events.EventTarget);
+goog.inherits(mvc.Collection, mvc.Model);
/**
* @return {Array}
View
6 collection_test.js
@@ -34,3 +34,9 @@ var testSortedCollection = function() {
assertEquals('second object should be mock 3', test.at(1), model3);
assertEquals('third object should be mock 1', test.at(2), model1);
};
+
+var testAsModel = function() {
+ var test = new mvc.Collection();
+ test.set('a', 1);
+ assertEquals('should have attribute a as 1', test.get('a'), 1);
+}
View
1  control.js
@@ -1,3 +1,4 @@
+// v0.1
goog.provide('mvc.Control');
goog.require('goog.dom');
View
12 control_test.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html>
+<head>
+ <title>Test for mvc.Model</title>
+</head>
+<body>
+ <div id="control"><div id="test1" class="class1"><div id="test2" class="class2"><span id="test3" class="class1"></span></div></div></div>
+ <script src="closure-library/closure/goog/base.js"></script>
+ <script src="test_deps.js"></script>
+ <script src="control_test.js"></script>
+</body>
+</html>
View
17 control_test.js
@@ -0,0 +1,17 @@
+goog.require('mvc.Control');
+
+goog.require('goog.dom');
+goog.require('goog.testing.jsunit');
+
+var simpleControl;
+
+var setUp = function() {
+ simpleControl = new mvc.Control();
+}
+
+var testSimpleControl = function() {
+ simpleControl.init = goog.nullFunction;
+ simpleControl.render(goog.dom.getElement("control"));
+ assertEquals("should come back with one element", simpleControl.getEls(".class2").length, 1);
+ assertEquals("should come back with 2 elements", simpleControl.getEls(".class1").length, 2);
+};
View
25 model.js
@@ -1,3 +1,4 @@
+// v0.1
goog.provide('mvc.Model');
goog.provide('mvc.Model.Schema');
@@ -84,15 +85,18 @@ mvc.Model.prototype.has = function(key) {
* @return {mvc.Model}
*/
mvc.Model.prototype.set = function(key, val, silent) {
- this.prev_ = goog.object.clone(this.attr_);
if(goog.isString(key)) {
var temp = {};
temp[key] = val;
key = temp;
}
+ if(!silent) {
+ this.prev_ = goog.object.clone(this.attr_);
+ }
goog.object.forEach(key, function(val, key) {
- if(!this.schema_ || this.schema_.validate(key, val))
+ if(!this.schema_ || this.schema_.validate(key, val)) {
this.attr_[key] = val;
+ }
}, this);
if(!silent) {
this.dispatchEvent(goog.events.EventType.CHANGE);
@@ -185,21 +189,32 @@ mvc.Model.prototype.save = function() {
};
// binds a change event
+/**
+ * @param {string} name
+ * @param {Element|Node|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(name in changes) {
+ if(name in changes || !goog.isDefAndNotNull(name)) {
+ if(goog.isFunction(el)) {
+ goog.bind(el, fn)(changes[name], this);
+ return;
+ }
if(!goog.isArrayLike(el))
el = [el];
goog.array.forEach(el, function(elem) {
if(goog.isFunction(fn)) {
fn(elem, changes[name]);
- } else {
+ } else if (el.nodeType){
goog.dom.setTextContent(elem, changes[name]);
+ } else {
+ el = changes[name];
}
});
}
- });
+ }, this);
};
/**
View
1  router.js
@@ -1,3 +1,4 @@
+// v0.1
goog.provide('mvc.Router');
goog.require('goog.events');
View
1  sync/ajax.js
@@ -1,3 +1,4 @@
+// v0.1
goog.provide('mvc.sync.Ajax');
goog.require('mvc.sync');
View
1  sync/local.js
@@ -1,3 +1,4 @@
+// v0.1
goog.provide('mvc.sync.local');
View
1  sync/sync.js
@@ -1,3 +1,4 @@
+// v0.1
goog.provide('mvc.sync');
/**
View
7 test_deps.js
@@ -1,12 +1,13 @@
// This file was autogenerated by calcdeps.py
-goog.addDependency("../../../collection.js", ['mvc.Collection'], ['goog.events.EventTarget']);
+goog.addDependency("../../../collection.js", ['mvc.Collection'], ['mvc.Model', 'goog.events.EventTarget']);
goog.addDependency("../../../collection_test.js", [], ['mvc.Collection', 'mvc.Model', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);
goog.addDependency("../../../control.js", ['mvc.Control'], ['goog.dom', 'goog.object', 'goog.ui.Component']);
-goog.addDependency("../../../control_test.js", [], []);
-goog.addDependency("../../../model.js", ['mvc.Model'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.object']);
+goog.addDependency("../../../control_test.js", [], ['mvc.Control', 'goog.dom', 'goog.testing.jsunit']);
+goog.addDependency("../../../model.js", ['mvc.Model', 'mvc.Model.Schema'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.object']);
goog.addDependency("../../../model_test.js", [], ['mvc.Model', 'goog.testing.jsunit']);
goog.addDependency("../../../router.js", ['mvc.Router'], ['goog.events', 'goog.history']);
goog.addDependency("../../../test_deps.js", [], []);
goog.addDependency("../../../sync/ajax.js", ['mvc.sync.Ajax'], ['mvc.sync', 'goog.net.XhrIo']);
+goog.addDependency("../../../sync/local.js", ['mvc.sync.local'], []);
goog.addDependency("../../../sync/sync.js", ['mvc.sync'], []);
goog.addDependency("../../../testApp/testApp.js", [], []);
Please sign in to comment.
Something went wrong with that request. Please try again.