Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added extensible computes

  • Loading branch information...
commit 34cdbfddc0411a98d1b6395bf3a3f8b78b2f307a 1 parent 6271a87
@hunterloftis authored
View
7 backbone.viewmodel.coffee
@@ -14,6 +14,7 @@ do (Backbone) ->
@_virtuals = {}
@_bindings = []
super
+ @compute(attr, fn) for attr, fn of @computes
set: (key, value, options) ->
unless options && options.dependency
@@ -79,19 +80,19 @@ do (Backbone) ->
Backbone.Virtual.track(this, 'change:' + attr)
return @attributes[attr]
- compute: ->
+ compute: =>
args = _.toArray(arguments)
get = args.pop()
args.push({ get: get })
@virtual.apply(this, args)
- pass: ->
+ pass: =>
args = _.toArray(arguments)
reference = args.pop()
args.push({ reference: reference })
@virtual.apply(this, args)
- virtual: ->
+ virtual: =>
attrs = _.toArray(arguments)
options = attrs.pop()
options.model = this
View
13 dist/backbone.viewmodel-0.2.0.js
@@ -22,12 +22,25 @@
this.createVirtual = __bind(this.createVirtual, this);
+ this.virtual = __bind(this.virtual, this);
+
+ this.pass = __bind(this.pass, this);
+
+ this.compute = __bind(this.compute, this);
+
this.parseBinding = __bind(this.parseBinding, this);
this.bindToNode = __bind(this.bindToNode, this);
+
+ var attr, fn, _ref;
this._virtuals = {};
this._bindings = [];
ViewModel.__super__.constructor.apply(this, arguments);
+ _ref = this.computes;
+ for (attr in _ref) {
+ fn = _ref[attr];
+ this.compute(attr, fn);
+ }
}
ViewModel.prototype.set = function(key, value, options) {
View
27 dist/backbone.viewmodel-0.2.0.min.js
@@ -1,23 +1,24 @@
-(function(){var h=function(b,c){return function(){return b.apply(c,arguments)}},f={}.hasOwnProperty,d=function(b,c){function a(){this.constructor=b}for(var e in c)f.call(c,e)&&(b[e]=c[e]);a.prototype=c.prototype;b.prototype=new a;b.__super__=c.prototype;return b};(function(b){var c,a;a=b.Model.prototype;c={undefined:void 0,"null":null,"true":!0,"false":!1};b.ViewModel=function(e){function g(b,a){this.onVirtual=h(this.onVirtual,this);this.createVirtual=h(this.createVirtual,this);this.parseBinding=
-h(this.parseBinding,this);this.bindToNode=h(this.bindToNode,this);this._virtuals={};this._bindings=[];g.__super__.constructor.apply(this,arguments)}d(g,e);g.prototype.set=function(b,c,e){var d,g;if(!e||!e.dependency)if(d=(null!=(g=this._virtuals)?g.hasOwnProperty(b):void 0)&&this._virtuals[b])return d.set.call(this,b,c,e,d);return a.set.apply(this,arguments)};g.prototype.bindView=function(b,a){var e,c,d,g;null==a&&(a="body");e="*["+b+"]";c=$(a).find(e);$(a).is(e)&&(c=$(a).add(c));d=0;for(g=c.length;d<
-g;d++)e=c[d],this.bindToNode(b,e);return c};g.prototype.unbindView=function(){var b,a,e,c;c=this._bindings;a=0;for(e=c.length;a<e;a++)b=c[a],b.stop();return this._bindings=[]};g.prototype.isBoundTo=function(b){var a,c,e,d;d=this._bindings;c=0;for(e=d.length;c<e;c++)if(a=d[c],a.node===b)return!0;return!1};g.prototype.bindToNode=function(a,b){var c,e,d,g,f;if(!this.isBoundTo(b)){e=$(b).attr(a);c=e.split(";");e=[];g=0;for(f=c.length;g<f;g++)d=c[g],e.push(this.parseBinding(b,a,d));f=[];d=0;for(g=e.length;d<
-g;d++)c=e[d],f.push(this.createBinding(c));return f}};g.prototype.parseBinding=function(b,a,c){var e;e=c.split("(");var c=e[0].trim(),d,g,f,h;f=e[1].trim().slice(0,-1).split(",");h=[];d=0;for(g=f.length;d<g;d++)e=f[d],h.push(this.parseArgument(e));return{node:b,viewModel:this,type:c,bindingAttr:a,args:h}};g.prototype.parseArgument=function(b){b=b.trim();c.hasOwnProperty(b)?b=c[b]:isNaN(b)||(b=Number(b));return b};g.prototype.createBinding=function(a){var e;e=b.Binding[a.type];if(null!=e)return a=
-new e(a),a.start(),this._bindings.push(a),a;throw Error('Trying to create a binding of unknown type "'+a.type+'"');};g.prototype.get=function(a){b.Virtual.track(this,"change:"+a);return this.attributes[a]};g.prototype.compute=function(){var a,b;a=_.toArray(arguments);b=a.pop();a.push({get:b});return this.virtual.apply(this,a)};g.prototype.pass=function(){var a,b;a=_.toArray(arguments);b=a.pop();a.push({reference:b});return this.virtual.apply(this,a)};g.prototype.virtual=function(){var a,b,e;b=_.toArray(arguments);
-e=b.pop();e.model=this;var c,d,g;g=[];c=0;for(d=b.length;c<d;c++)a=b[c],g.push(this.createVirtual(a,e));return g};g.prototype.createVirtual=function(a,e){var c;c=_.extend({},e,{attr:a});c=new b.Virtual(c);this._virtuals[a]=c;c.on("change",this.onVirtual);return c.run()};g.prototype.onVirtual=function(a){return this.set(a.attr,a.result,{dependency:!0})};return g}(b.Model);return b.Model=b.ViewModel})(Backbone)}).call(this);
-(function(){var h={}.hasOwnProperty,f=function(d,b){function c(){this.constructor=d}for(var a in b)h.call(b,a)&&(d[a]=b[a]);c.prototype=b.prototype;d.prototype=new c;d.__super__=b.prototype;return d};(function(d){var b,c,a,e,g,h;a=d.Collection.prototype;d.ViewCollection=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}f(b,a);b.prototype.list=function(){d.Virtual.track(this,"add remove reset change create sort");return this.models};return b}(d.Collection);d.Collection.prototype.model=
-d.Model;b=function(b){return d.ViewCollection.prototype[b]=function(){d.Virtual.track(this,"add remove reset change create sort");return a[b].apply(this,arguments)}};h="get getByCid where pluck clone at toJSON".split(" ").concat("forEach each map reduce reduceRight find detect filter select reject every all some any include contains invoke max min sortBy sortedIndex toArray size first initial rest last without indexOf shuffle lastIndexOf isEmpty groupBy".split(" "));e=0;for(g=h.length;e<g;e++)c=h[e],
+(function(){var g=function(b,c){return function(){return b.apply(c,arguments)}},f={}.hasOwnProperty,d=function(b,c){function a(){this.constructor=b}for(var e in c)f.call(c,e)&&(b[e]=c[e]);a.prototype=c.prototype;b.prototype=new a;b.__super__=c.prototype;return b};(function(b){var c,a;a=b.Model.prototype;c={undefined:void 0,"null":null,"true":!0,"false":!1};b.ViewModel=function(e){function h(b,a){this.onVirtual=g(this.onVirtual,this);this.createVirtual=g(this.createVirtual,this);this.virtual=g(this.virtual,
+this);this.pass=g(this.pass,this);this.compute=g(this.compute,this);this.parseBinding=g(this.parseBinding,this);this.bindToNode=g(this.bindToNode,this);var i,c,e;this._virtuals={};this._bindings=[];h.__super__.constructor.apply(this,arguments);e=this.computes;for(i in e)c=e[i],this.compute(i,c)}d(h,e);h.prototype.set=function(b,e,c){var d,h;if(!c||!c.dependency)if(d=(null!=(h=this._virtuals)?h.hasOwnProperty(b):void 0)&&this._virtuals[b])return d.set.call(this,b,e,c,d);return a.set.apply(this,arguments)};
+h.prototype.bindView=function(b,a){var c,e,d,h;null==a&&(a="body");c="*["+b+"]";e=$(a).find(c);$(a).is(c)&&(e=$(a).add(e));d=0;for(h=e.length;d<h;d++)c=e[d],this.bindToNode(b,c);return e};h.prototype.unbindView=function(){var b,a,c,e;e=this._bindings;a=0;for(c=e.length;a<c;a++)b=e[a],b.stop();return this._bindings=[]};h.prototype.isBoundTo=function(b){var a,e,c,d;d=this._bindings;e=0;for(c=d.length;e<c;e++)if(a=d[e],a.node===b)return!0;return!1};h.prototype.bindToNode=function(a,b){var e,c,d,h,f;
+if(!this.isBoundTo(b)){c=$(b).attr(a);e=c.split(";");c=[];h=0;for(f=e.length;h<f;h++)d=e[h],c.push(this.parseBinding(b,a,d));f=[];d=0;for(h=c.length;d<h;d++)e=c[d],f.push(this.createBinding(e));return f}};h.prototype.parseBinding=function(b,a,e){var c;c=e.split("(");var e=c[0].trim(),d,h,f,g;f=c[1].trim().slice(0,-1).split(",");g=[];d=0;for(h=f.length;d<h;d++)c=f[d],g.push(this.parseArgument(c));return{node:b,viewModel:this,type:e,bindingAttr:a,args:g}};h.prototype.parseArgument=function(b){b=b.trim();
+c.hasOwnProperty(b)?b=c[b]:isNaN(b)||(b=Number(b));return b};h.prototype.createBinding=function(a){var c;c=b.Binding[a.type];if(null!=c)return a=new c(a),a.start(),this._bindings.push(a),a;throw Error('Trying to create a binding of unknown type "'+a.type+'"');};h.prototype.get=function(a){b.Virtual.track(this,"change:"+a);return this.attributes[a]};h.prototype.compute=function(){var a,b;a=_.toArray(arguments);b=a.pop();a.push({get:b});return this.virtual.apply(this,a)};h.prototype.pass=function(){var a,
+b;a=_.toArray(arguments);b=a.pop();a.push({reference:b});return this.virtual.apply(this,a)};h.prototype.virtual=function(){var a,b,c;b=_.toArray(arguments);c=b.pop();c.model=this;var e,d,h;h=[];e=0;for(d=b.length;e<d;e++)a=b[e],h.push(this.createVirtual(a,c));return h};h.prototype.createVirtual=function(a,c){var e;e=_.extend({},c,{attr:a});e=new b.Virtual(e);this._virtuals[a]=e;e.on("change",this.onVirtual);return e.run()};h.prototype.onVirtual=function(a){return this.set(a.attr,a.result,{dependency:!0})};
+return h}(b.Model);return b.Model=b.ViewModel})(Backbone)}).call(this);
+(function(){var g={}.hasOwnProperty,f=function(d,b){function c(){this.constructor=d}for(var a in b)g.call(b,a)&&(d[a]=b[a]);c.prototype=b.prototype;d.prototype=new c;d.__super__=b.prototype;return d};(function(d){var b,c,a,e,h,g;a=d.Collection.prototype;d.ViewCollection=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}f(b,a);b.prototype.list=function(){d.Virtual.track(this,"add remove reset change create sort");return this.models};return b}(d.Collection);d.Collection.prototype.model=
+d.Model;b=function(b){return d.ViewCollection.prototype[b]=function(){d.Virtual.track(this,"add remove reset change create sort");return a[b].apply(this,arguments)}};g="get getByCid where pluck clone at toJSON".split(" ").concat("forEach each map reduce reduceRight find detect filter select reject every all some any include contains invoke max min sortBy sortedIndex toArray size first initial rest last without indexOf shuffle lastIndexOf isEmpty groupBy".split(" "));e=0;for(h=g.length;e<h;e++)c=g[e],
b(c);return d.Collection=d.ViewCollection})(Backbone)}).call(this);
-(function(){var h=function(f,d){return function(){return f.apply(d,arguments)}};(function(f){f.Virtual=function(){function d(b){this.remove=h(this.remove,this);this.add=h(this.add,this);this.update=h(this.update,this);this.onChange=h(this.onChange,this);this.run=h(this.run,this);this.runSafe=h(this.runSafe,this);_.extend(this,b);this.dependencies=[];this.result=void 0}d._computations=[];d._dependencies=void 0;d.startTracking=function(){f.Virtual._dependencies=[];return f.Virtual._computations.push(f.Virtual._dependencies)};
+(function(){var g=function(f,d){return function(){return f.apply(d,arguments)}};(function(f){f.Virtual=function(){function d(b){this.remove=g(this.remove,this);this.add=g(this.add,this);this.update=g(this.update,this);this.onChange=g(this.onChange,this);this.run=g(this.run,this);this.runSafe=g(this.runSafe,this);_.extend(this,b);this.dependencies=[];this.result=void 0}d._computations=[];d._dependencies=void 0;d.startTracking=function(){f.Virtual._dependencies=[];return f.Virtual._computations.push(f.Virtual._dependencies)};
d.stopTracking=function(){var b,c;b=f.Virtual._computations;c=b.pop();f.Virtual._dependencies=b.length?b[b.length-1]:void 0;return c};d.track=function(b,c){var a;return null!=(a=f.Virtual._dependencies)?a.push({model:b,event:c}):void 0};d.prototype.runSafe=function(){try{return this.get.call(this.model,this.attr,this)}catch(b){return this.fail}};d.prototype.run=function(){f.Virtual.startTracking();this.result=this.hasOwnProperty("fail")?this.runSafe():this.get.call(this.model,this.attr,this);this.update(f.Virtual.stopTracking());
this.trigger("change",this);return this.result};d.prototype.onChange=function(){return this.run()};d.prototype.update=function(b){var c,a,e,d;d=this.dependencies;a=0;for(e=d.length;a<e;a++)c=d[a],this.remove(c);a=0;for(e=b.length;a<e;a++)c=b[a],this.add(c);return this.dependencies=b};d.prototype.add=function(b){return b.model.on(b.event,this.onChange)};d.prototype.remove=function(b){return b.model.off(b.event,this.onChange)};d.prototype.get=function(b,c){return("function"===typeof c.reference?c.reference.call(this):
c.reference).get(b)};d.prototype.set=function(b,c,a,e){return("function"===typeof e.reference?e.reference.call(this):e.reference).set(b,c)};return d}();return _.extend(f.Virtual.prototype,f.Events)})(Backbone)}).call(this);
-(function(){var h=function(f,d){return function(){return f.apply(d,arguments)}};(function(f){f.Binding=function(){function d(b){this.stop=h(this.stop,this);this.start=h(this.start,this);this.onViewChange=h(this.onViewChange,this);this.onCollectionChange=h(this.onCollectionChange,this);this.onModelChange=h(this.onModelChange,this);this.initialize=h(this.initialize,this);_.extend(this,b);this.initialize.apply(this,b.args)}d.prototype.initialize=function(){};d.prototype.onModelChange=function(){};d.prototype.onCollectionChange=
+(function(){var g=function(f,d){return function(){return f.apply(d,arguments)}};(function(f){f.Binding=function(){function d(b){this.stop=g(this.stop,this);this.start=g(this.start,this);this.onViewChange=g(this.onViewChange,this);this.onCollectionChange=g(this.onCollectionChange,this);this.onModelChange=g(this.onModelChange,this);this.initialize=g(this.initialize,this);_.extend(this,b);this.initialize.apply(this,b.args)}d.prototype.initialize=function(){};d.prototype.onModelChange=function(){};d.prototype.onCollectionChange=
function(){};d.prototype.onViewChange=function(){};d.prototype.start=function(){this.viewModel.on("change:"+this.attribute,this.onModelChange);return this.onModelChange()};d.prototype.stop=function(){return this.viewModel.off("change:"+this.attribute,this.onModelChange)};return d}();return f.Binding.extend=f.Model.extend})(Backbone)}).call(this);
-(function(){var h={}.hasOwnProperty,f=function(b,c){function a(){this.constructor=b}for(var e in c)h.call(c,e)&&(b[e]=c[e]);a.prototype=c.prototype;b.prototype=new a;b.__super__=c.prototype;return b},d=function(b,c){return function(){return b.apply(c,arguments)}};(function(b){b.Binding.visible=function(b){function a(){return a.__super__.constructor.apply(this,arguments)}f(a,b);a.prototype.initialize=function(a){this.attribute=a};a.prototype.onModelChange=function(){return this.viewModel.get(this.attribute)?
+(function(){var g={}.hasOwnProperty,f=function(b,c){function a(){this.constructor=b}for(var e in c)g.call(c,e)&&(b[e]=c[e]);a.prototype=c.prototype;b.prototype=new a;b.__super__=c.prototype;return b},d=function(b,c){return function(){return b.apply(c,arguments)}};(function(b){b.Binding.visible=function(b){function a(){return a.__super__.constructor.apply(this,arguments)}f(a,b);a.prototype.initialize=function(a){this.attribute=a};a.prototype.onModelChange=function(){return this.viewModel.get(this.attribute)?
$(this.node).show():$(this.node).hide()};return a}(b.Binding);b.Binding.text=function(b){function a(){return a.__super__.constructor.apply(this,arguments)}f(a,b);a.prototype.initialize=function(a){this.attribute=a};a.prototype.onModelChange=function(){var a;a=this.viewModel.get(this.attribute);return $(this.node).text(a)};return a}(b.Binding);b.Binding.val=function(b){function a(){return a.__super__.constructor.apply(this,arguments)}f(a,b);a.prototype.initialize=function(a){this.attribute=a};a.prototype.start=
function(){a.__super__.start.apply(this,arguments);return $(this.node).on("keyup change",this.onViewChange)};a.prototype.onModelChange=function(){var a;a=this.viewModel.get(this.attribute);return $(this.node).val(a)};a.prototype.onViewChange=function(){return this.viewModel.set(this.attribute,$(this.node).val())};a.prototype.stop=function(){a.__super__.stop.apply(this,arguments);return $(this.node).off("keyup change",this.onViewChange)};return a}(b.Binding);b.Binding.css=function(b){function a(){return a.__super__.constructor.apply(this,
arguments)}f(a,b);a.prototype.initialize=function(a,b,c){this.className=a;this.attribute=b;this.truth=null!=c?c:!0};a.prototype.onModelChange=function(){var a;a=this.viewModel.get(this.attribute);return Boolean(this.truth)===Boolean(a)?$(this.node).addClass(this.className):$(this.node).removeClass(this.className)};return a}(b.Binding);b.Binding.click=function(b){function a(){return a.__super__.constructor.apply(this,arguments)}f(a,b);a.prototype.initialize=function(){var a;a=_.toArray(arguments);
this.callback=a.shift();return this.args=a};a.prototype.start=function(){return $(this.node).on("click",this.onViewChange)};a.prototype.onViewChange=function(a){var b;a.preventDefault();return(null!=(b=this.viewModel[this.callback])?b:this.viewModel.get(this.callback)).apply(this.viewModel,this.args)};a.prototype.stop=function(){return $(this.node).off("click",this.onViewChange)};return a}(b.Binding);return b.Binding.each=function(c){function a(){this.renderItem=d(this.renderItem,this);return a.__super__.constructor.apply(this,
-arguments)}f(a,c);a.prototype.initialize=function(a){this.attr=a;this.container=$(this.node);this.itemTemplate=this.container.html();return this.container.html("")};a.prototype.start=function(){this.viewModel.on("change:"+this.attr,this.onCollectionChange);return this.onCollectionChange()};a.prototype.onCollectionChange=function(){var a,c,d,f,h;this.container.html("");this.collection=this.viewModel.get(this.attr);if(this.collection instanceof b.Collection)return this.collection.off("add remove reset change create sort",
-this.onCollectionChange),this.collection.each(this.renderItem),this.collection.on("add remove reset change create sort",this.onCollectionChange);f=this.collection;h=[];c=0;for(d=f.length;c<d;c++)a=f[c],h.push(this.renderItem(a));return h};a.prototype.renderItem=function(a){var b,c,d,f,h;f=$(this.itemTemplate);h=[];c=0;for(d=f.length;c<d;c++)b=f[c],this.container.append(b),h.push(a.bindView(this.bindingAttr,b));return h};a.prototype.stop=function(){return this.viewModel.off("change:"+this.attr,this.onCollectionChange)};
+arguments)}f(a,c);a.prototype.initialize=function(a){this.attr=a;this.container=$(this.node);this.itemTemplate=this.container.html();return this.container.html("")};a.prototype.start=function(){this.viewModel.on("change:"+this.attr,this.onCollectionChange);return this.onCollectionChange()};a.prototype.onCollectionChange=function(){var a,c,d,f,g;this.container.html("");this.collection=this.viewModel.get(this.attr);if(this.collection instanceof b.Collection)return this.collection.off("add remove reset change create sort",
+this.onCollectionChange),this.collection.each(this.renderItem),this.collection.on("add remove reset change create sort",this.onCollectionChange);f=this.collection;g=[];c=0;for(d=f.length;c<d;c++)a=f[c],g.push(this.renderItem(a));return g};a.prototype.renderItem=function(a){var b,c,d,f,g;f=$(this.itemTemplate);g=[];c=0;for(d=f.length;c<d;c++)b=f[c],this.container.append(b),g.push(a.bindView(this.bindingAttr,b));return g};a.prototype.stop=function(){return this.viewModel.off("change:"+this.attr,this.onCollectionChange)};
return a}(b.Binding)})(Backbone)}).call(this);
View
13 lib/backbone.viewmodel.js
@@ -22,12 +22,25 @@
this.createVirtual = __bind(this.createVirtual, this);
+ this.virtual = __bind(this.virtual, this);
+
+ this.pass = __bind(this.pass, this);
+
+ this.compute = __bind(this.compute, this);
+
this.parseBinding = __bind(this.parseBinding, this);
this.bindToNode = __bind(this.bindToNode, this);
+
+ var attr, fn, _ref;
this._virtuals = {};
this._bindings = [];
ViewModel.__super__.constructor.apply(this, arguments);
+ _ref = this.computes;
+ for (attr in _ref) {
+ fn = _ref[attr];
+ this.compute(attr, fn);
+ }
}
ViewModel.prototype.set = function(key, value, options) {
View
4 test/test.html
@@ -7,7 +7,9 @@
<link rel="stylesheet" href="../vendor/qunit.css" type="text/css" media="screen">
<script src="../vendor/qunit.js"></script>
<script src="../vendor/jslitmus.js"></script>
- <script>QUnit.config.reorder = false;</script>
+ <script>
+ QUnit.config.reorder = false;
+ </script>
<!-- Platform dependencies -->
<script src='../vendor/zepto-1.0rc1.js'></script>
View
24 test/viewcollections.qunit.js
@@ -1,24 +0,0 @@
-$(document).ready(function() {
-
-module("Backbone.ViewCollection");
-
-test("tracking collection dependency through VMs and VCs", function() {
-
- var items = new Backbone.Collection();
-
- var vm = new Backbone.ViewModel({
- collection1: items
- });
-
- vm.compute('collection2', function() {
- var items = this.get('collection1');
- return _.filter(items, function(item) {
- return item % 2 === 0;
- });
- });
-
- strictEqual(vm.get('collection2').length, 0, 'list should start out empty');
-
-});
-
-});
View
24 test/virtual.qunit.js
@@ -246,4 +246,28 @@ test("passing with a Model", function() {
strictEqual(Backbone.Virtual._computations.length, 0, 'computation stack should be clear');
});
+test("adding virtuals with ViewModel.extend", function() {
+
+ var Extended = Backbone.ViewModel.extend({
+ defaults: {
+ x: 2
+ },
+ computes: {
+ square: function() {
+ return this.get('x') * this.get('x');
+ }
+ }
+ });
+
+ var vm = new Extended();
+
+ strictEqual(vm.get('x'), 2, 'x should be 2');
+ strictEqual(vm.get('square'), 4, 'square should be 4');
+
+ vm.set('x', 3);
+ strictEqual(vm.get('x'), 3, 'x should be 3');
+ strictEqual(vm.get('square'), 9, 'square should be 9');
+
+});
+
});
Please sign in to comment.
Something went wrong with that request. Please try again.