aboutsummaryrefslogtreecommitdiffstats
path: root/src/Scope.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/Scope.js')
-rw-r--r--src/Scope.js65
1 files changed, 44 insertions, 21 deletions
diff --git a/src/Scope.js b/src/Scope.js
index 3633f960..daafabb0 100644
--- a/src/Scope.js
+++ b/src/Scope.js
@@ -1,18 +1,23 @@
function Scope(initialState, name) {
- this.widgets = [];
- this.evals = [];
- 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;
}
- this.set('$watch', bind(this, this.addWatchListener));
- this.set('$eval', bind(this, this.addEval));
};
Scope.expressionCache = {};
@@ -47,6 +52,7 @@ Scope.getter = function(instance, path) {
};
Scope.prototype = {
+ // TODO: rename to update? or eval?
updateView: function() {
var self = this;
this.fireWatchers();
@@ -64,7 +70,13 @@ Scope.prototype = {
addEval: function(fn, listener) {
// todo: this should take a function/string and a listener
- this.evals.push(fn);
+ // todo: this is a hack, which will need to be cleaned up.
+ var self = this,
+ listenFn = listener || noop,
+ expr = self.compile(fn);
+ this.evals.push(function(){
+ self.apply(listenFn, expr());
+ });
},
isProperty: function(exp) {
@@ -103,19 +115,26 @@ 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 bind(this.state, exp);
+ var expFn = Scope.expressionCache[exp], self = this;
+ if (!expFn) {
+ var parser = new Parser(exp);
+ expFn = parser.statements();
parser.assertAllConsumed();
- Scope.expressionCache[expressionText] = expression;
+ Scope.expressionCache[exp] = expFn;
}
- context = context || {};
- context.scope = this;
- context.self = this.state;
- return expression(context);
+ return function(context){
+ context = context || {};
+ context.self = self.state;
+ context.scope = self;
+ return expFn.call(self, context);
+ };
+ },
+
+ eval: function(expressionText, context) {
+// log('Scope.eval', expressionText);
+ return this.compile(expressionText)(context);
},
//TODO: Refactor. This function needs to be an execution closure for widgets
@@ -189,6 +208,10 @@ Scope.prototype = {
},
addWatchListener: function(watchExpression, listener) {
+ // TODO: clean me up!
+ if (!isFunction(listener)) {
+ listener = this.compile(listener);
+ }
var watcher = this.watchListeners[watchExpression];
if (!watcher) {
watcher = {listeners:[], expression:watchExpression};