aboutsummaryrefslogtreecommitdiffstats
path: root/src/Scope.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/Scope.js')
-rw-r--r--src/Scope.js62
1 files changed, 46 insertions, 16 deletions
diff --git a/src/Scope.js b/src/Scope.js
index daf4b36c..d22604fd 100644
--- a/src/Scope.js
+++ b/src/Scope.js
@@ -1,14 +1,22 @@
function Scope(initialState, name) {
- this.widgets = [];
- this.watchListeners = {};
- this.name = name;
+ var self = this;
+ self.widgets = [];
+ self.evals = [];
+ self.watchListeners = {};
+ self.name = name;
initialState = initialState || {};
var State = function(){};
State.prototype = initialState;
- this.state = new State();
- this.state['$parent'] = initialState;
+ self.state = new State();
+ extend(self.state, {
+ '$parent': initialState,
+ '$watch': bind(self, self.addWatchListener),
+ '$eval': bind(self, self.eval),
+ // change name to onEval?
+ '$addEval': bind(self, self.addEval)
+ });
if (name == "ROOT") {
- this.state['$root'] = this.state;
+ self.state['$root'] = self.state;
}
};
@@ -44,20 +52,33 @@ Scope.getter = function(instance, path) {
};
Scope.prototype = {
+ // TODO: rename to update? or eval?
updateView: function() {
var self = this;
this.fireWatchers();
- _.each(this.widgets, function(widget){
+ foreach(this.widgets, function(widget){
self.evalWidget(widget, "", {}, function(){
this.updateView(self);
});
});
+ foreach(this.evals, bind(this, this.apply));
},
addWidget: function(controller) {
if (controller) this.widgets.push(controller);
},
+ addEval: function(fn, listener) {
+ // todo: this should take a function/string and a listener
+ // todo: this is a hack, which will need to be cleaned up.
+ var self = this,
+ listenFn = listener || noop,
+ expr = bind(self, self.compile(fn), {scope: self, self: self.state});
+ this.evals.push(function(){
+ self.apply(listenFn, expr());
+ });
+ },
+
isProperty: function(exp) {
for ( var i = 0; i < exp.length; i++) {
var ch = exp.charAt(i);
@@ -94,15 +115,21 @@ Scope.prototype = {
this.eval(expressionText + "=" + toJson(value));
},
- eval: function(expressionText, context) {
-// log('Scope.eval', expressionText);
- var expression = Scope.expressionCache[expressionText];
- if (!expression) {
- var parser = new Parser(expressionText);
- expression = parser.statements();
+ compile: function(exp) {
+ if (isFunction(exp)) return exp;
+ var expFn = Scope.expressionCache[exp];
+ if (!expFn) {
+ var parser = new Parser(exp);
+ expFn = parser.statements();
parser.assertAllConsumed();
- Scope.expressionCache[expressionText] = expression;
+ Scope.expressionCache[exp] = expFn;
}
+ return expFn;
+ },
+
+ eval: function(expressionText, context) {
+// log('Scope.eval', expressionText);
+ var expression = this.compile(expressionText);
context = context || {};
context.scope = this;
context.self = this.state;
@@ -189,8 +216,7 @@ Scope.prototype = {
},
fireWatchers: function() {
- var self = this;
- var fired = false;
+ var self = this, fired = false;
foreach(this.watchListeners, function(watcher) {
var value = self.eval(watcher.expression);
if (value !== watcher.lastValue) {
@@ -202,5 +228,9 @@ Scope.prototype = {
}
});
return fired;
+ },
+
+ apply: function(fn) {
+ fn.apply(this.state, slice.call(arguments, 1, arguments.length));
}
};