Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(582)

Side by Side Diff: pkg/polymer_expressions/lib/polymer_expressions.dart

Issue 132403010: big update to observe, template_binding, polymer (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/polymer_expressions/lib/eval.dart ('k') | pkg/polymer_expressions/test/bindings_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * A binding delegate used with Polymer elements that 6 * A binding delegate used with Polymer elements that
7 * allows for complex binding expressions, including 7 * allows for complex binding expressions, including
8 * property access, function invocation, 8 * property access, function invocation,
9 * list/map indexing, and two-way filtering. 9 * list/map indexing, and two-way filtering.
10 * 10 *
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 // For template bind/repeat to an empty path, just pass through the model. 74 // For template bind/repeat to an empty path, just pass through the model.
75 // We don't want to unwrap the Scope. 75 // We don't want to unwrap the Scope.
76 // TODO(jmesserly): a custom element extending <template> could notice this 76 // TODO(jmesserly): a custom element extending <template> could notice this
77 // behavior. An alternative is to associate the Scope with the node via an 77 // behavior. An alternative is to associate the Scope with the node via an
78 // Expando, which is what the JavaScript PolymerExpressions does. 78 // Expando, which is what the JavaScript PolymerExpressions does.
79 if (isSemanticTemplate(node) && (name == 'bind' || name == 'repeat') && 79 if (isSemanticTemplate(node) && (name == 'bind' || name == 'repeat') &&
80 expr is EmptyExpression) { 80 expr is EmptyExpression) {
81 return null; 81 return null;
82 } 82 }
83 83
84 return (model, node) { 84 return (model, node, oneTime) {
85 if (model is! Scope) { 85 if (model is! Scope) {
86 model = new Scope(model: model, variables: globals); 86 model = new Scope(model: model, variables: globals);
87 } 87 }
88 var converter = null;
88 if (node is Element && name == "class") { 89 if (node is Element && name == "class") {
89 return new _Binding(expr, model, _classAttributeConverter); 90 converter = _classAttributeConverter;
90 } 91 }
91 if (node is Element && name == "style") { 92 if (node is Element && name == "style") {
92 return new _Binding(expr, model, _styleAttributeConverter); 93 converter = _styleAttributeConverter;
93 } 94 }
94 return new _Binding(expr, model); 95
96 if (oneTime) {
97 return _Binding._oneTime(expr, model, converter);
98 }
99
100 return new _Binding(expr, model, converter);
95 }; 101 };
96 } 102 }
97 103
98 prepareInstanceModel(Element template) => (model) => 104 prepareInstanceModel(Element template) => (model) =>
99 model is Scope ? model : new Scope(model: model, variables: globals); 105 model is Scope ? model : new Scope(model: model, variables: globals);
100 } 106 }
101 107
102 class _Binding extends ChangeNotifier { 108 class _Binding extends Bindable {
103 final Scope _scope; 109 final Scope _scope;
104 final ExpressionObserver _expr;
105 final _converter; 110 final _converter;
111 Expression _expr;
112 Function _callback;
113 StreamSubscription _sub;
106 var _value; 114 var _value;
107 115
108 _Binding(Expression expr, Scope scope, [this._converter]) 116 _Binding(this._expr, this._scope, [this._converter]);
109 : _expr = observe(expr, scope), 117
110 _scope = scope { 118 static _oneTime(Expression expr, Scope scope, [converter]) {
111 _expr.onUpdate.listen(_setValue).onError((e) {
112 _logger.warning("Error evaluating expression '$_expr': ${e.message}");
113 });
114 try { 119 try {
115 update(_expr, _scope); 120 return _convertValue(eval(expr, scope), scope, converter);
116 _setValue(_expr.currentValue);
117 } on EvalException catch (e) { 121 } on EvalException catch (e) {
118 _logger.warning("Error evaluating expression '$_expr': ${e.message}"); 122 _logger.warning("Error evaluating expression '$expr': ${e.message}");
123 return null;
119 } 124 }
120 } 125 }
121 126
122 _setValue(v) { 127 _setValue(v) {
123 var oldValue = _value; 128 _value = _convertValue(v, _scope, _converter);
129 if (_callback != null) _callback(_value);
130 }
131
132 static _convertValue(v, scope, converter) {
124 if (v is Comprehension) { 133 if (v is Comprehension) {
125 // convert the Comprehension into a list of scopes with the loop 134 // convert the Comprehension into a list of scopes with the loop
126 // variable added to the scope 135 // variable added to the scope
127 _value = v.iterable.map((i) { 136 return v.iterable.map((i) {
128 var vars = new Map(); 137 var vars = new Map();
129 vars[v.identifier] = i; 138 vars[v.identifier] = i;
130 Scope childScope = new Scope(parent: _scope, variables: vars); 139 Scope childScope = new Scope(parent: scope, variables: vars);
131 return childScope; 140 return childScope;
132 }).toList(growable: false); 141 }).toList(growable: false);
133 } else { 142 } else {
134 _value = (_converter == null) ? v : _converter(v); 143 return converter == null ? v : converter(v);
135 } 144 }
136 notifyPropertyChange(#value, oldValue, _value);
137 } 145 }
138 146
139 @reflectable get value => _value; 147 get value {
148 if (_callback != null) return _value;
149 return _oneTime(_expr, _scope, _converter);
150 }
140 151
141 @reflectable set value(v) { 152 set value(v) {
142 try { 153 try {
143 assign(_expr, v, _scope); 154 assign(_expr, v, _scope);
144 } on EvalException catch (e) { 155 } on EvalException catch (e) {
145 _logger.warning("Error evaluating expression '$_expr': ${e.message}"); 156 _logger.warning("Error evaluating expression '$_expr': ${e.message}");
146 } 157 }
147 } 158 }
159
160 open(callback(value)) {
161 if (_callback != null) throw new StateError('already open');
162
163 _callback = callback;
164 final expr = observe(_expr, _scope);
165 _expr = expr;
166 _sub = expr.onUpdate.listen(_setValue)..onError((e) {
167 _logger.warning("Error evaluating expression '$_expr': ${e.message}");
168 });
169 try {
170 update(expr, _scope);
171 _value = _convertValue(expr.currentValue, _scope, _converter);
172 } on EvalException catch (e) {
173 _logger.warning("Error evaluating expression '$_expr': ${e.message}");
174 }
175 return _value;
176 }
177
178 void close() {
179 if (_callback == null) return;
180
181 _sub.cancel();
182 _sub = null;
183 _expr = (_expr as ExpressionObserver).expression;
184 _callback = null;
185 }
148 } 186 }
OLDNEW
« no previous file with comments | « pkg/polymer_expressions/lib/eval.dart ('k') | pkg/polymer_expressions/test/bindings_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698