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

Side by Side Diff: tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate

Issue 17552019: Reorganize mdv and observe packages (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merged Created 7 years, 5 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 // WARNING: Do not edit - generated code. 5 // WARNING: Do not edit - generated code.
6 6
7 part of $LIBRARYNAME; 7 part of $LIBRARYNAME;
8 8
9
10 /**
11 * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
12 * but (by design) don't attempt to implement a wide array of specialized
13 * behaviors.
14 *
15 * Enabling these features in MDV is a matter of implementing and registering an
16 * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
17 * delegation functions which implement specialized behavior. This object is
18 * registered with MDV via [TemplateElement.syntax]:
19 *
20 *
21 * HTML:
22 * <template bind syntax="MySyntax">
23 * {{ What!Ever('crazy')->thing^^^I+Want(data) }}
24 * </template>
25 *
26 * Dart:
27 * class MySyntax extends CustomBindingSyntax {
28 * getBinding(model, path, name, node) {
29 * // The magic happens here!
30 * }
31 * }
32 *
33 * ...
34 *
35 * TemplateElement.syntax['MySyntax'] = new MySyntax();
36 *
37 * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
38 * more information about Custom Syntax.
39 */
40 // TODO(jmesserly): if this is just one method, a function type would make it
41 // more Dart-friendly.
42 @Experimental
43 abstract class CustomBindingSyntax {
44 /**
45 * This syntax method allows for a custom interpretation of the contents of
46 * mustaches (`{{` ... `}}`).
47 *
48 * When a template is inserting an instance, it will invoke this method for
49 * each mustache which is encountered. The function is invoked with four
50 * arguments:
51 *
52 * - [model]: The data context for which this instance is being created.
53 * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
54 * - [name]: The context in which the mustache occurs. Within element
55 * attributes, this will be the name of the attribute. Within text,
56 * this will be 'text'.
57 * - [node]: A reference to the node to which this binding will be created.
58 *
59 * If the method wishes to handle binding, it is required to return an object
60 * which has at least a `value` property that can be observed. If it does,
61 * then MDV will call [Node.bind on the node:
62 *
63 * node.bind(name, retval, 'value');
64 *
65 * If the 'getBinding' does not wish to override the binding, it should return
66 * null.
67 */
68 // TODO(jmesserly): I had to remove type annotations from "name" and "node"
69 // Normally they are String and Node respectively. But sometimes it will pass
70 // (int name, CompoundBinding node). That seems very confusing; we may want
71 // to change this API.
72 getBinding(model, String path, name, node) => null;
73
74 /**
75 * This syntax method allows a syntax to provide an alterate model than the
76 * one the template would otherwise use when producing an instance.
77 *
78 * When a template is about to create an instance, it will invoke this method
79 * The function is invoked with two arguments:
80 *
81 * - [template]: The template element which is about to create and insert an
82 * instance.
83 * - [model]: The data context for which this instance is being created.
84 *
85 * The template element will always use the return value of `getInstanceModel`
86 * as the model for the new instance. If the syntax does not wish to override
87 * the value, it should simply return the `model` value it was passed.
88 */
89 getInstanceModel(Element template, model) => model;
90
91 /**
92 * This syntax method allows a syntax to provide an alterate expansion of
93 * the [template] contents. When the template wants to create an instance,
94 * it will call this method with the template element.
95 *
96 * By default this will call `template.createInstance()`.
97 */
98 getInstanceFragment(Element template) => template.createInstance();
99 }
100
101
9 @Experimental 102 @Experimental
10 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { 103 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
11 $!MEMBERS 104 $!MEMBERS
12 105
13 // For real TemplateElement use the actual DOM .content field instead of 106 // For real TemplateElement use the actual DOM .content field instead of
14 // our polyfilled expando. 107 // our polyfilled expando.
15 @Experimental 108 @Experimental
16 DocumentFragment get content => $dom_content; 109 DocumentFragment get content => $dom_content;
17 110
18 static StreamController<DocumentFragment> _instanceCreated;
19 111
20 /** 112 /**
21 * *Warning*: This is an implementation helper for Model-Driven Views and 113 * The MDV package, if available.
22 * should not be used in your code.
23 * 114 *
24 * This event is fired whenever a template is instantiated via 115 * This can be used to initialize MDV support via:
25 * [createInstance]. 116 *
117 * import 'dart:html';
118 * import 'package:mdv/mdv.dart' as mdv;
119 * main() {
120 * mdv.initialize();
121 * }
26 */ 122 */
27 // TODO(rafaelw): This is a hack, and is neccesary for the polyfill 123 static Function mdvPackage = (node) {
28 // because custom elements are not upgraded during clone() 124 throw new UnsupportedError("The MDV package is not available. "
29 @Experimental 125 "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
30 static Stream<DocumentFragment> get instanceCreated { 126 "`mdv.initialize()`");
31 if (_instanceCreated == null) { 127 };
32 _instanceCreated = new StreamController<DocumentFragment>(sync: true);
33 }
34 return _instanceCreated.stream;
35 }
36 128
37 /** 129 /**
38 * Ensures proper API and content model for template elements. 130 * Ensures proper API and content model for template elements.
39 * 131 *
40 * [instanceRef] can be used to set the [Element.ref] property of [template], 132 * [instanceRef] can be used to set the [Element.ref] property of [template],
41 * and use the ref's content will be used as source when createInstance() is 133 * and use the ref's content will be used as source when createInstance() is
42 * invoked. 134 * invoked.
43 * 135 *
44 * Returns true if this template was just decorated, or false if it was 136 * Returns true if this template was just decorated, or false if it was
45 * already decorated. 137 * already decorated.
46 */ 138 */
47 @Experimental 139 @Experimental
48 static bool decorate(Element template, [Element instanceRef]) { 140 static bool decorate(Element template, [Element instanceRef]) {
49 // == true check because it starts as a null field. 141 // == true check because it starts as a null field.
50 if (template._templateIsDecorated == true) return false; 142 if (template._templateIsDecorated == true) return false;
51 143
52 template._templateIsDecorated = true; 144 template._templateIsDecorated = true;
53 145
54 _injectStylesheet(); 146 _injectStylesheet();
55 147
56 // Create content 148 // Create content
57 if (template is! TemplateElement) { 149 if (template is! TemplateElement) {
58 var doc = _Bindings._getTemplateContentsOwner(template.document); 150 var doc = _getTemplateContentsOwner(template.document);
59 template._templateContent = doc.createDocumentFragment(); 151 template._templateContent = doc.createDocumentFragment();
60 } 152 }
61 153
62 if (instanceRef != null) { 154 if (instanceRef != null) {
63 template._templateInstanceRef = instanceRef; 155 template._templateInstanceRef = instanceRef;
64 return true; // content is empty. 156 return true; // content is empty.
65 } 157 }
66 158
67 if (template is TemplateElement) { 159 if (template is TemplateElement) {
68 bootstrap(template.content); 160 bootstrap(template.content);
69 } else { 161 } else {
70 _Bindings._liftNonNativeChildrenIntoContent(template); 162 _liftNonNativeChildrenIntoContent(template);
71 } 163 }
72 164
73 return true; 165 return true;
74 } 166 }
75 167
168 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html# dfn-template-contents-owner
169 static Document _getTemplateContentsOwner(HtmlDocument doc) {
170 if (doc.window == null) {
171 return doc;
172 }
173 var d = doc._templateContentsOwner;
174 if (d == null) {
175 // TODO(arv): This should either be a Document or HTMLDocument depending
176 // on doc.
177 d = doc.implementation.createHtmlDocument('');
178 while (d.lastChild != null) {
179 d.lastChild.remove();
180 }
181 doc._templateContentsOwner = d;
182 }
183 return d;
184 }
185
186 static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
187 var clone = templateElement.clone(false);
188 var attributes = templateElement.attributes;
189 for (var name in attributes.keys.toList()) {
190 switch (name) {
191 case 'template':
192 case 'repeat':
193 case 'bind':
194 case 'ref':
195 clone.attributes.remove(name);
196 break;
197 default:
198 attributes.remove(name);
199 break;
200 }
201 }
202
203 return clone;
204 }
205
206 static void _liftNonNativeChildrenIntoContent(Element templateElement) {
207 var content = templateElement.content;
208
209 if (!templateElement._isAttributeTemplate) {
210 var child;
211 while ((child = templateElement.firstChild) != null) {
212 content.append(child);
213 }
214 return;
215 }
216
217 // For attribute templates we copy the whole thing into the content and
218 // we move the non template attributes into the content.
219 //
220 // <tr foo template>
221 //
222 // becomes
223 //
224 // <tr template>
225 // + #document-fragment
226 // + <tr foo>
227 //
228 var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
229 var child;
230 while ((child = templateElement.firstChild) != null) {
231 newRoot.append(child);
232 }
233 content.append(newRoot);
234 }
235
76 /** 236 /**
77 * This used to decorate recursively all templates from a given node. 237 * This used to decorate recursively all templates from a given node.
78 * 238 *
79 * By default [decorate] will be called on templates lazily when certain 239 * By default [decorate] will be called on templates lazily when certain
80 * properties such as [model] are accessed, but it can be run eagerly to 240 * properties such as [model] are accessed, but it can be run eagerly to
81 * decorate an entire tree recursively. 241 * decorate an entire tree recursively.
82 */ 242 */
83 // TODO(rafaelw): Review whether this is the right public API. 243 // TODO(rafaelw): Review whether this is the right public API.
84 @Experimental 244 @Experimental
85 static void bootstrap(Node content) { 245 static void bootstrap(Node content) {
86 _Bindings._bootstrapTemplatesRecursivelyFrom(content); 246 void _bootstrap(template) {
247 if (!TemplateElement.decorate(template)) {
248 bootstrap(template.content);
249 }
250 }
251
252 // Need to do this first as the contents may get lifted if |node| is
253 // template.
254 // TODO(jmesserly): content is DocumentFragment or Element
255 var descendents = (content as dynamic).queryAll(_allTemplatesSelectors);
256 if (content is Element && (content as Element).isTemplate) {
257 _bootstrap(content);
258 }
259
260 descendents.forEach(_bootstrap);
87 } 261 }
88 262
89 /** 263 static final String _allTemplatesSelectors = 'template, option[template], ' +
90 * Binds all mustaches recursively starting from the [root] node. 264 Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
91 *
92 * Note: this is not an official Model-Driven-Views API; it is intended to
93 * support binding the [ShadowRoot]'s content to a model.
94 */
95 // TODO(jmesserly): this is needed to avoid two <template> nodes when using
96 // bindings in a custom element's template. See also:
97 // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
98 // Called from:
99 // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
100 @Experimental
101 static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
102 _Bindings._addBindings(root, model, syntax);
103 }
104 265
105 static bool _initStyles; 266 static bool _initStyles;
106 267
107 static void _injectStylesheet() { 268 static void _injectStylesheet() {
108 if (_initStyles == true) return; 269 if (_initStyles == true) return;
109 _initStyles = true; 270 _initStyles = true;
110 271
111 var style = new StyleElement(); 272 var style = new StyleElement();
112 style.text = r''' 273 style.text = r'''
113 template, 274 template,
(...skipping 12 matching lines...) Expand all
126 document.head.append(style); 287 document.head.append(style);
127 } 288 }
128 289
129 /** 290 /**
130 * A mapping of names to Custom Syntax objects. See [CustomBindingSyntax] for 291 * A mapping of names to Custom Syntax objects. See [CustomBindingSyntax] for
131 * more information. 292 * more information.
132 */ 293 */
133 @Experimental 294 @Experimental
134 static Map<String, CustomBindingSyntax> syntax = {}; 295 static Map<String, CustomBindingSyntax> syntax = {};
135 } 296 }
OLDNEW
« no previous file with comments | « tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate ('k') | tools/dom/templates/html/impl/impl_Node.darttemplate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698