Index: template_binding/lib/src/node.dart |
diff --git a/template_binding/lib/src/node.dart b/template_binding/lib/src/node.dart |
deleted file mode 100644 |
index fbcf96a866dc8b4f0dffa92487e0c5d8db6c52c7..0000000000000000000000000000000000000000 |
--- a/template_binding/lib/src/node.dart |
+++ /dev/null |
@@ -1,200 +0,0 @@ |
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-part of template_binding; |
- |
-/** Extensions to the [Node] API. */ |
-class NodeBindExtension { |
- final Node _node; |
- final JsObject _js; |
- |
- NodeBindExtension._(node) |
- : _node = node, |
- _js = new JsObject.fromBrowserObject(node); |
- |
- /** |
- * Gets the data bindings that are associated with this node, if any. |
- * |
- * This starts out null, and if [enableBindingsReflection] is enabled, calls |
- * to [bind] will initialize this field and the binding. |
- */ |
- // Dart note: in JS this has a trailing underscore, meaning "private". |
- // But in dart if we made it _bindings, it wouldn't be accessible at all. |
- // It is unfortunately needed to implement Node.bind correctly. |
- Map<String, Bindable> get bindings { |
- var b = _js['bindings_']; |
- if (b == null) return null; |
- // TODO(jmesserly): should cache this for identity. |
- return new _NodeBindingsMap(_node, b); |
- } |
- |
- set bindings(Map<String, Bindable> value) { |
- if (value == null) { |
- _js.deleteProperty('bindings_'); |
- return; |
- } |
- var b = bindings; |
- if (b == null) { |
- _js['bindings_'] = new JsObject.jsify({}); |
- b = bindings; |
- } |
- b.addAll(value); |
- } |
- |
- /** |
- * Binds the attribute [name] to [value]. [value] can be a simple value when |
- * [oneTime] is true, or a [Bindable] like [PathObserver]. |
- * Returns the [Bindable] instance. |
- */ |
- Bindable bind(String name, value, {bool oneTime: false}) { |
- name = _dartToJsName(_node, name); |
- |
- if (!oneTime && value is Bindable) { |
- value = bindableToJsObject(value); |
- } |
- return jsObjectToBindable(_js.callMethod('bind', [name, value, oneTime])); |
- } |
- |
- /** |
- * Called when all [bind] calls are finished for a given template expansion. |
- */ |
- bindFinished() => _js.callMethod('bindFinished'); |
- |
- // Note: confusingly this is on NodeBindExtension because it can be on any |
- // Node. It's really an API added by TemplateBinding. Therefore it stays |
- // implemented in Dart because TemplateBinding still is. |
- TemplateInstance _templateInstance; |
- |
- /** Gets the template instance that instantiated this node, if any. */ |
- TemplateInstance get templateInstance => |
- _templateInstance != null ? _templateInstance : |
- (_node.parent != null ? nodeBind(_node.parent).templateInstance : null); |
-} |
- |
-class _NodeBindingsMap extends MapBase<String, Bindable> { |
- final Node _node; |
- final JsObject _bindings; |
- |
- _NodeBindingsMap(this._node, this._bindings); |
- |
- // TODO(jmesserly): this should be lazy |
- Iterable<String> get keys => |
- js.context['Object'].callMethod('keys', [_bindings]).map( |
- (name) => _jsToDartName(_node, name)); |
- |
- Bindable operator[](String name) => |
- jsObjectToBindable(_bindings[_dartToJsName(_node, name)]); |
- |
- operator[]=(String name, Bindable value) { |
- _bindings[_dartToJsName(_node, name)] = bindableToJsObject(value); |
- } |
- |
- @override Bindable remove(String name) { |
- name = _dartToJsName(_node, name); |
- var old = this[name]; |
- _bindings.deleteProperty(name); |
- return old; |
- } |
- |
- @override void clear() { |
- // Notes: this implementation only works because our "keys" returns a copy. |
- // We could also make it O(1) by assigning a new JS object to the bindings_ |
- // property, if performance is an issue. |
- keys.forEach(remove); |
- } |
-} |
- |
-// TODO(jmesserly): perhaps we should switch Dart's Node.bind API back to |
-// 'textContent' for consistency? This only affects the raw Node.bind API when |
-// called on Text nodes, which is unlikely to be used except by TemplateBinding. |
-// Seems like a lot of magic to support it. I don't think Node.bind promises any |
-// strong relationship between properties and [name], so textContent seems fine. |
-String _dartToJsName(Node node, String name) { |
- if (node is Text && name == 'text') name = 'textContent'; |
- return name; |
-} |
- |
- |
-String _jsToDartName(Node node, String name) { |
- if (node is Text && name == 'textContent') name = 'text'; |
- return name; |
-} |
- |
- |
-/// Given a bindable [JsObject], wraps it in a Dart [Bindable]. |
-/// See [bindableToJsObject] to go in the other direction. |
-Bindable jsObjectToBindable(JsObject obj) { |
- if (obj == null) return null; |
- var b = obj['__dartBindable']; |
- // For performance, unwrap the Dart bindable if we find one. |
- // Note: in the unlikely event some code messes with our __dartBindable |
- // property we can simply fallback to a _JsBindable wrapper. |
- return b is Bindable ? b : new _JsBindable(obj); |
-} |
- |
-class _JsBindable extends Bindable { |
- final JsObject _js; |
- _JsBindable(JsObject obj) : _js = obj; |
- |
- open(callback) => _js.callMethod('open', |
- [Zone.current.bindUnaryCallback(callback)]); |
- |
- close() => _js.callMethod('close'); |
- |
- get value => _js.callMethod('discardChanges'); |
- |
- set value(newValue) { |
- _js.callMethod('setValue', [newValue]); |
- } |
- |
- deliver() => _js.callMethod('deliver'); |
-} |
- |
-/// Given a [bindable], create a JS object proxy for it. |
-/// This is the inverse of [jsObjectToBindable]. |
-JsObject bindableToJsObject(Bindable bindable) { |
- if (bindable is _JsBindable) return bindable._js; |
- |
- var zone = Zone.current; |
- inZone(f) => zone.bindCallback(f, runGuarded: false); |
- inZoneUnary(f) => zone.bindUnaryCallback(f, runGuarded: false); |
- |
- return new JsObject.jsify({ |
- 'open': inZoneUnary( |
- (callback) => bindable.open((x) => callback.apply([x]))), |
- 'close': inZone(() => bindable.close()), |
- 'discardChanges': inZone(() => bindable.value), |
- 'setValue': inZoneUnary((x) => bindable.value = x), |
- // NOTE: this is not used by Node.bind, but it's used by Polymer: |
- // https://github.com/Polymer/polymer-dev/blob/ba2b68fe5a5721f60b5994135f3270e63588809a/src/declaration/properties.js#L130 |
- // Technically this works because 'deliver' is on PathObserver and |
- // CompoundObserver. But ideally Polymer-JS would not assume that. |
- 'deliver': inZone(() => bindable.deliver()), |
- // Save this so we can return it from [jsObjectToBindable] |
- '__dartBindable': bindable |
- }); |
-} |
- |
-/** Information about the instantiated template. */ |
-class TemplateInstance { |
- // TODO(rafaelw): firstNode & lastNode should be read-synchronous |
- // in cases where script has modified the template instance boundary. |
- |
- /** The first node of this template instantiation. */ |
- Node get firstNode => _firstNode; |
- |
- /** |
- * The last node of this template instantiation. |
- * This could be identical to [firstNode] if the template only expanded to a |
- * single node. |
- */ |
- Node get lastNode => _lastNode; |
- |
- /** The model used to instantiate the template. */ |
- final model; |
- |
- Node _firstNode, _lastNode; |
- |
- TemplateInstance(this.model); |
-} |