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

Side by Side Diff: pkg/mdv/lib/src/node.dart

Issue 34453003: Rename mdv -> template_binding, remove experiemntal apis from dart:html (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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/mdv/lib/src/list_diff.dart ('k') | pkg/mdv/lib/src/select_element.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of mdv;
6
7 /** Extensions to the [Node] API. */
8 class _NodeExtension {
9 final Node node;
10 Map<String, NodeBinding> _bindings;
11
12 _NodeExtension(this.node);
13
14 NodeBinding createBinding(String name, model, String path) => null;
15
16 /**
17 * Binds the attribute [name] to the [path] of the [model].
18 * Path is a String of accessors such as `foo.bar.baz`.
19 */
20 NodeBinding bind(String name, model, String path) {
21 var binding = bindings[name];
22 if (binding != null) binding.close();
23
24 // Note: dispatch through the xtag so a custom element can override it.
25 binding = (node is Element ? (node as Element).xtag : node)
26 .createBinding(name, model, path);
27
28 bindings[name] = binding;
29 if (binding == null) {
30 window.console.error('Unhandled binding to Node: '
31 '$this $name $model $path');
32 }
33 return binding;
34 }
35
36 /** Unbinds the attribute [name]. */
37 void unbind(String name) {
38 if (_bindings == null) return;
39 var binding = bindings.remove(name);
40 if (binding != null) binding.close();
41 }
42
43 /** Unbinds all bound attributes. */
44 void unbindAll() {
45 if (_bindings == null) return;
46 for (var binding in bindings.values) {
47 if (binding != null) binding.close();
48 }
49 _bindings = null;
50 }
51
52 // TODO(jmesserly): we should return a read-only wrapper here.
53 Map<String, NodeBinding> get bindings {
54 if (_bindings == null) _bindings = new LinkedHashMap<String, NodeBinding>();
55 return _bindings;
56 }
57
58 TemplateInstance _templateInstance;
59
60 /** Gets the template instance that instantiated this node, if any. */
61 TemplateInstance get templateInstance =>
62 _templateInstance != null ? _templateInstance :
63 (node.parent != null ? node.parent.templateInstance : null);
64 }
65
66 /** A data binding on a [Node]. See [Node.bindings] and [Node.bind]. */
67 abstract class NodeBinding {
68 Node _node;
69 var _model;
70 PathObserver _observer;
71 StreamSubscription _pathSub;
72
73 /** The property of [node] which will be data bound. */
74 final String property;
75
76 /** The property of [node] which will be data bound. */
77 final String path;
78
79 /** The node that has [property] which will be data bound. */
80 Node get node => _node;
81
82 /**
83 * The bound data model.
84 */
85 get model => _model;
86
87 /** True if this binding has been [closed]. */
88 bool get closed => _observer == null;
89
90 /** The value at the [path] on [model]. */
91 get value => _observer.value;
92
93 set value(newValue) {
94 _observer.value = newValue;
95 }
96
97 NodeBinding(this._node, this.property, this._model, this.path) {
98 // Create the path observer
99 _observer = new PathObserver(model, path);
100 _observePath();
101 }
102
103 void _observePath() {
104 _pathSub = _observer.bindSync(boundValueChanged);
105 }
106
107 /** Called when [value] changes to update the [node]. */
108 // TODO(jmesserly): the impl in MDV uses mirrors to set the property,
109 // but that isn't used except for specific known fields like "textContent",
110 // so I'm overridding this in the subclasses instead.
111 void boundValueChanged(newValue);
112
113 /** Called to sanitize the value before it is assigned into the property. */
114 sanitizeBoundValue(value) => value == null ? '' : '$value';
115
116 /**
117 * Called by [Node.unbind] to close this binding and unobserve the [path].
118 *
119 * This can be overridden in subclasses, but they must call `super.close()`
120 * to free associated resources. They must also check [closed] and return
121 * immediately if already closed.
122 */
123 void close() {
124 if (closed) return;
125
126 if (_pathSub != null) _pathSub.cancel();
127 _pathSub = null;
128 _observer = null;
129 _node = null;
130 _model = null;
131 }
132 }
OLDNEW
« no previous file with comments | « pkg/mdv/lib/src/list_diff.dart ('k') | pkg/mdv/lib/src/select_element.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698