Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

DVL'd up the projections

  • Loading branch information...
commit 3423bb7cacfbdc14789f74f49a100826f7f1e1aa 1 parent 2abc8bc
@vogievetsky authored
Showing with 108 additions and 19 deletions.
  1. +28 −9 dvl.js
  2. +21 −6 src/core.coffee
  3. +59 −4 tests/core/projections.js
View
37 dvl.js
@@ -432,8 +432,8 @@ function lift(fn) {
});
};
- DVLConst.prototype.project = function(fnDown, fnUp) {
- return dvl["const"](this.v != null ? fnDown.call(null, this.v) : null);
+ DVLConst.prototype.project = function(fns) {
+ return dvl["const"]((this.v != null) && (fns != null ? fns.down : void 0) ? fns.down.call(null, this.v) : null);
};
return DVLConst;
@@ -628,14 +628,33 @@ function lift(fn) {
});
};
- DVLVar.prototype.project = function(fnDown, fnUp) {
- var v;
+ DVLVar.prototype.project = function(fns) {
+ var me, v;
+ fns = dvl.wrap(fns);
v = dvl();
- v.proj = {
- parent: this,
- fnDown: fnDown,
- fnUp: fnUp
- };
+ me = this;
+ dvl.register({
+ listen: fns,
+ change: me,
+ fn: function() {
+ var _fns;
+ _fns = fns.value();
+ if (!_fns) {
+ _fns = {
+ down: function() {
+ return null;
+ },
+ up: function() {}
+ };
+ }
+ v.proj = {
+ parent: me,
+ fnDown: _fns.down,
+ fnUp: _fns.up
+ };
+ me.notify();
+ }
+ });
return v;
};
View
27 src/core.coffee
@@ -181,7 +181,7 @@ class DVLConst
applyAlways: (fn) -> dvl.applyAlways(this, fn)
pluck: (prop) -> dvl.apply(this, (d) -> d[prop])
pluckEx: (prop) -> dvl.apply(this, (d) -> d[prop]())
- project: (fnDown, fnUp) -> dvl.const(if @v? then fnDown.call(null, @v) else null)
+ project: (fns) -> dvl.const(if @v? and fns?.down then fns.down.call(null, @v) else null)
class DVLVar
constructor: (val) ->
@@ -292,12 +292,27 @@ class DVLVar
applyAlways: (fn) -> dvl.applyAlways(this, fn)
pluck: (prop) -> dvl.apply(this, (d) -> d[prop])
pluckEx: (prop) -> dvl.apply(this, (d) -> d[prop]())
- project: (fnDown, fnUp) ->
+ project: (fns) ->
+ fns = dvl.wrap(fns)
v = dvl()
- v.proj = {
- parent: this
- fnDown
- fnUp
+ me = this
+ dvl.register {
+ listen: fns
+ change: me
+ fn: ->
+ _fns = fns.value()
+ if not _fns
+ _fns = {
+ down: -> null
+ up: -> return
+ }
+ v.proj = {
+ parent: me
+ fnDown: _fns.down
+ fnUp: _fns.up
+ }
+ me.notify()
+ return
}
return v
View
63 tests/core/projections.js
@@ -12,10 +12,10 @@ suite.addBatch({
var t = {
color: dvl().compare(false),
}
- t.r = t.color.project(
- function(c) { return c.r },
- function(r) { this.r = r; return this }
- )
+ t.r = t.color.project({
+ down: function(c) { return c.r },
+ up: function(r) { this.r = r; return this }
+ })
t.avg = t.color.apply(function(a) { return (a.r + a.g + a.b) / 3; })
@@ -43,4 +43,59 @@ suite.addBatch({
},
});
+suite.addBatch({
+ "dynamic projection": {
+ topic: function() {
+ dvl.clearAll();
+ var t = {
+ key: dvl(),
+ color: dvl().compare(false),
+ }
+ var projFns = dvl.apply(t.key, function(_key) {
+ return {
+ down: function(c) { return c[_key] },
+ up: function(r) { this[_key] = r; return this }
+ }
+ })
+ t.r = t.color.project(projFns)
+
+ t.rCopy = t.r.apply(dvl.identity)
+
+ t.avg = t.color.apply(function(a) { return (a.r + a.g + a.b) / 3; })
+
+ return t;
+ },
+
+ "correct initial run": function(t) {
+ assert.strictEqual(t.r.value(), null);
+ },
+
+ "correct still null": function(t) {
+ t.color.value({ r: 1, g: 2, b: 3 });
+ assert.strictEqual(t.r.value(), null);
+ },
+
+ "correct to": function(t) {
+ t.key.value('r')
+ assert.strictEqual(t.r.value(), 1);
+ },
+
+ "correct from": function(t) {
+ t.r.value(10);
+ assert.strictEqual(t.color.value().r, 10);
+ },
+
+ "correct notify": function(t) {
+ t.r.value(10);
+ assert.strictEqual(t.rCopy.value(), 10);
+ assert.strictEqual(t.avg.value(), 5);
+ },
+
+ "correct on change": function(t) {
+ t.key.value('g')
+ assert.strictEqual(t.r.value(), 2);
+ }
+ },
+});
+
suite.export(module);
Please sign in to comment.
Something went wrong with that request. Please try again.