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

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

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
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 // 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 * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
11 * but (by design) don't attempt to implement a wide array of specialized
12 * behaviors.
13 *
14 * Enabling these features in MDV is a matter of implementing and registering an
15 * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
16 * delegation functions which implement specialized behavior. This object is
17 * registered with MDV via [Element.bindingDelegate]:
18 *
19 *
20 * HTML:
21 * <template bind>
22 * {{ What!Ever('crazy')->thing^^^I+Want(data) }}
23 * </template>
24 *
25 * Dart:
26 * class MySyntax extends BindingDelegate {
27 * getBinding(model, path, name, node) {
28 * // The magic happens here!
29 * }
30 * }
31 * ...
32 * query('template').bindingDelegate = new MySyntax();
33 * query('template').model = new MyModel();
34 *
35 * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
36 * more information about Custom Syntax.
37 */
38 // TODO(jmesserly): move this type to the MDV package? Two issues: we'd lose
39 // type annotation on [Element.bindingDelegate], and "mdv" is normally imported
40 // with a prefix.
41 @Experimental()
42 abstract class BindingDelegate {
43 /**
44 * This syntax method allows for a custom interpretation of the contents of
45 * mustaches (`{{` ... `}}`).
46 *
47 * When a template is inserting an instance, it will invoke this method for
48 * each mustache which is encountered. The function is invoked with four
49 * arguments:
50 *
51 * - [model]: The data context for which this instance is being created.
52 * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
53 * - [name]: The context in which the mustache occurs. Within element
54 * attributes, this will be the name of the attribute. Within text,
55 * this will be 'text'.
56 * - [node]: A reference to the node to which this binding will be created.
57 *
58 * If the method wishes to handle binding, it is required to return an object
59 * which has at least a `value` property that can be observed. If it does,
60 * then MDV will call [Node.bind on the node:
61 *
62 * node.bind(name, retval, 'value');
63 *
64 * If the 'getBinding' does not wish to override the binding, it should return
65 * null.
66 */
67 // TODO(jmesserly): I had to remove type annotations from "name" and "node"
68 // Normally they are String and Node respectively. But sometimes it will pass
69 // (int name, CompoundBinding node). That seems very confusing; we may want
70 // to change this API.
71 getBinding(model, String path, name, node) => null;
72
73 /**
74 * This syntax method allows a syntax to provide an alterate model than the
75 * one the template would otherwise use when producing an instance.
76 *
77 * When a template is about to create an instance, it will invoke this method
78 * The function is invoked with two arguments:
79 *
80 * - [template]: The template element which is about to create and insert an
81 * instance.
82 * - [model]: The data context for which this instance is being created.
83 *
84 * The template element will always use the return value of `getInstanceModel`
85 * as the model for the new instance. If the syntax does not wish to override
86 * the value, it should simply return the `model` value it was passed.
87 */
88 getInstanceModel(Element template, model) => model;
89 }
90
91 @Experimental() 9 @Experimental()
92 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { 10 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
93 $!MEMBERS 11 $!MEMBERS
94 12
95 // For real TemplateElement use the actual DOM .content field instead of
96 // our polyfilled expando.
97 @Experimental()
98 DocumentFragment get content => _content;
99
100
101 /**
102 * The MDV package, if available.
103 *
104 * This can be used to initialize MDV support via:
105 *
106 * import 'dart:html';
107 * import 'package:mdv/mdv.dart' as mdv;
108 * main() {
109 * mdv.initialize();
110 * }
111 */
112 static Function mdvPackage = (node) {
113 throw new UnsupportedError("The MDV package is not available. "
114 "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
115 "`mdv.initialize()`");
116 };
117
118 /**
119 * Ensures proper API and content model for template elements.
120 *
121 * [instanceRef] can be used to set the [Element.ref] property of [template],
122 * and use the ref's content will be used as source when createInstance() is
123 * invoked.
124 *
125 * Returns true if this template was just decorated, or false if it was
126 * already decorated.
127 */
128 @Experimental()
129 static bool decorate(Element template, [Element instanceRef]) {
130 // == true check because it starts as a null field.
131 if (template._templateIsDecorated == true) return false;
132
133 _injectStylesheet();
134
135 var templateElement = template;
136 templateElement._templateIsDecorated = true;
137 var isNative = templateElement is TemplateElement;
138 var bootstrapContents = isNative;
139 var liftContents = !isNative;
140 var liftRoot = false;
141
142 if (!isNative && templateElement._isAttributeTemplate) {
143 if (instanceRef != null) {
144 // TODO(jmesserly): this is just an assert in MDV.
145 throw new ArgumentError('instanceRef should not be supplied for '
146 'attribute templates.');
147 }
148 templateElement = _extractTemplateFromAttributeTemplate(template);
149 templateElement._templateIsDecorated = true;
150 isNative = templateElement is TemplateElement;
151 liftRoot = true;
152 }
153
154 if (!isNative) {
155 var doc = _getTemplateContentsOwner(templateElement.ownerDocument);
156 templateElement._templateContent = doc.createDocumentFragment();
157 }
158
159 if (instanceRef != null) {
160 // template is contained within an instance, its direct content must be
161 // empty
162 templateElement._templateInstanceRef = instanceRef;
163 } else if (liftContents) {
164 _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
165 } else if (bootstrapContents) {
166 bootstrap(templateElement.content);
167 }
168
169 return true;
170 }
171
172 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html# dfn-template-contents-owner
173 static Document _getTemplateContentsOwner(HtmlDocument doc) {
174 if (doc.window == null) {
175 return doc;
176 }
177 var d = doc._templateContentsOwner;
178 if (d == null) {
179 // TODO(arv): This should either be a Document or HTMLDocument depending
180 // on doc.
181 d = doc.implementation.createHtmlDocument('');
182 while (d.lastChild != null) {
183 d.lastChild.remove();
184 }
185 doc._templateContentsOwner = d;
186 }
187 return d;
188 }
189
190 // For non-template browsers, the parser will disallow <template> in certain
191 // locations, so we allow "attribute templates" which combine the template
192 // element with the top-level container node of the content, e.g.
193 //
194 // <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
195 //
196 // becomes
197 //
198 // <template repeat="{{ foo }}">
199 // + #document-fragment
200 // + <tr class="bar">
201 // + <td>Bar</td>
202 //
203 static Element _extractTemplateFromAttributeTemplate(Element el) {
204 var template = el.ownerDocument.createElement('template');
205 el.parentNode.insertBefore(template, el);
206
207 for (var name in el.attributes.keys.toList()) {
208 switch (name) {
209 case 'template':
210 el.attributes.remove(name);
211 break;
212 case 'repeat':
213 case 'bind':
214 case 'ref':
215 template.attributes[name] = el.attributes.remove(name);
216 break;
217 }
218 }
219
220 return template;
221 }
222
223 static void _liftNonNativeChildrenIntoContent(Element template, Element el,
224 bool useRoot) {
225
226 var content = template.content;
227 if (useRoot) {
228 content.append(el);
229 return;
230 }
231
232 var child;
233 while ((child = el.firstChild) != null) {
234 content.append(child);
235 }
236 }
237
238 /**
239 * This used to decorate recursively all templates from a given node.
240 *
241 * By default [decorate] will be called on templates lazily when certain
242 * properties such as [model] are accessed, but it can be run eagerly to
243 * decorate an entire tree recursively.
244 */
245 // TODO(rafaelw): Review whether this is the right public API.
246 @Experimental()
247 static void bootstrap(Node content) {
248 void _bootstrap(template) {
249 if (!TemplateElement.decorate(template)) {
250 bootstrap(template.content);
251 }
252 }
253
254 // Need to do this first as the contents may get lifted if |node| is
255 // template.
256 // TODO(jmesserly): content is DocumentFragment or Element
257 var descendents =
258 (content as dynamic).querySelectorAll(_allTemplatesSelectors);
259 if (content is Element && (content as Element).isTemplate) {
260 _bootstrap(content);
261 }
262
263 descendents.forEach(_bootstrap);
264 }
265
266 static final String _allTemplatesSelectors =
267 'template, option[template], optgroup[template], ' +
268 Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
269
270 static bool _initStyles;
271
272 static void _injectStylesheet() {
273 if (_initStyles == true) return;
274 _initStyles = true;
275
276 var style = new StyleElement();
277 style.text = r'''
278 template,
279 thead[template],
280 tbody[template],
281 tfoot[template],
282 th[template],
283 tr[template],
284 td[template],
285 caption[template],
286 colgroup[template],
287 col[template],
288 option[template] {
289 display: none;
290 }''';
291 document.head.append(style);
292 }
293
294 /** 13 /**
295 * An override to place the contents into content rather than as child nodes. 14 * An override to place the contents into content rather than as child nodes.
296 * 15 *
297 * See also: 16 * See also:
298 * 17 *
299 * * <https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.h tml#innerhtml-on-templates> 18 * * <https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.h tml#innerhtml-on-templates>
300 */ 19 */
301 void setInnerHtml(String html, 20 void setInnerHtml(String html,
302 {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) { 21 {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
303 text = null; 22 text = null;
304 var fragment = createFragment( 23 var fragment = createFragment(
305 html, validator: validator, treeSanitizer: treeSanitizer); 24 html, validator: validator, treeSanitizer: treeSanitizer);
306 25
307 content.append(fragment); 26 content.append(fragment);
308 } 27 }
309 } 28 }
OLDNEW
« no previous file with comments | « tools/dom/templates/html/impl/impl_HTMLDocument.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