| OLD | NEW |
| 1 /// The Dart HTML library. | 1 /// The Dart HTML library. |
| 2 /// | 2 /// |
| 3 /// For examples, see | 3 /// For examples, see |
| 4 /// [Dart HTML5 Samples](https://github.com/dart-lang/dart-html5-samples) | 4 /// [Dart HTML5 Samples](https://github.com/dart-lang/dart-html5-samples) |
| 5 /// on Github. | 5 /// on Github. |
| 6 library dart.dom.html; | 6 library dart.dom.html; |
| 7 | 7 |
| 8 import 'dart:async'; | 8 import 'dart:async'; |
| 9 import 'dart:collection'; | 9 import 'dart:collection'; |
| 10 import 'dart:_collection-dev' hide Symbol; | 10 import 'dart:_collection-dev' hide Symbol; |
| (...skipping 20978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20989 * invoked. | 20989 * invoked. |
| 20990 * | 20990 * |
| 20991 * Returns true if this template was just decorated, or false if it was | 20991 * Returns true if this template was just decorated, or false if it was |
| 20992 * already decorated. | 20992 * already decorated. |
| 20993 */ | 20993 */ |
| 20994 @Experimental | 20994 @Experimental |
| 20995 static bool decorate(Element template, [Element instanceRef]) { | 20995 static bool decorate(Element template, [Element instanceRef]) { |
| 20996 // == true check because it starts as a null field. | 20996 // == true check because it starts as a null field. |
| 20997 if (template._templateIsDecorated == true) return false; | 20997 if (template._templateIsDecorated == true) return false; |
| 20998 | 20998 |
| 20999 template._templateIsDecorated = true; | |
| 21000 | |
| 21001 _injectStylesheet(); | 20999 _injectStylesheet(); |
| 21002 | 21000 |
| 21003 // Create content | 21001 var templateElement = template; |
| 21004 if (template is! TemplateElement) { | 21002 var isNative = templateElement is TemplateElement; |
| 21005 var doc = _getTemplateContentsOwner(template.document); | 21003 var bootstrapContents = isNative; |
| 21006 template._templateContent = doc.createDocumentFragment(); | 21004 var liftContents = !isNative; |
| 21005 var liftRoot = false; |
| 21006 |
| 21007 if (!isNative && templateElement._isAttributeTemplate) { |
| 21008 if (instanceRef != null) { |
| 21009 // TODO(jmesserly): this is just an assert in MDV. |
| 21010 throw new ArgumentError('instanceRef should not be supplied for ' |
| 21011 'attribute templates.'); |
| 21012 } |
| 21013 templateElement = _extractTemplateFromAttributeTemplate(template); |
| 21014 isNative = templateElement is TemplateElement; |
| 21015 liftRoot = true; |
| 21016 } |
| 21017 |
| 21018 templateElement._templateIsDecorated = true; |
| 21019 |
| 21020 if (!isNative) { |
| 21021 var doc = _getTemplateContentsOwner(templateElement.document); |
| 21022 templateElement._templateContent = doc.createDocumentFragment(); |
| 21007 } | 21023 } |
| 21008 | 21024 |
| 21009 if (instanceRef != null) { | 21025 if (instanceRef != null) { |
| 21010 template._templateInstanceRef = instanceRef; | 21026 // template is contained within an instance, its direct content must be |
| 21011 return true; // content is empty. | 21027 // empty |
| 21012 } | 21028 templateElement._templateInstanceRef = instanceRef; |
| 21013 | 21029 } else if (liftContents) { |
| 21014 if (template is TemplateElement) { | 21030 _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot); |
| 21015 bootstrap(template.content); | 21031 } else if (bootstrapContents) { |
| 21016 } else { | 21032 bootstrap(templateElement.content); |
| 21017 _liftNonNativeChildrenIntoContent(template); | |
| 21018 } | 21033 } |
| 21019 | 21034 |
| 21020 return true; | 21035 return true; |
| 21021 } | 21036 } |
| 21022 | 21037 |
| 21023 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#
dfn-template-contents-owner | 21038 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#
dfn-template-contents-owner |
| 21024 static Document _getTemplateContentsOwner(HtmlDocument doc) { | 21039 static Document _getTemplateContentsOwner(HtmlDocument doc) { |
| 21025 if (doc.window == null) { | 21040 if (doc.window == null) { |
| 21026 return doc; | 21041 return doc; |
| 21027 } | 21042 } |
| 21028 var d = doc._templateContentsOwner; | 21043 var d = doc._templateContentsOwner; |
| 21029 if (d == null) { | 21044 if (d == null) { |
| 21030 // TODO(arv): This should either be a Document or HTMLDocument depending | 21045 // TODO(arv): This should either be a Document or HTMLDocument depending |
| 21031 // on doc. | 21046 // on doc. |
| 21032 d = doc.implementation.createHtmlDocument(''); | 21047 d = doc.implementation.createHtmlDocument(''); |
| 21033 while (d.lastChild != null) { | 21048 while (d.lastChild != null) { |
| 21034 d.lastChild.remove(); | 21049 d.lastChild.remove(); |
| 21035 } | 21050 } |
| 21036 doc._templateContentsOwner = d; | 21051 doc._templateContentsOwner = d; |
| 21037 } | 21052 } |
| 21038 return d; | 21053 return d; |
| 21039 } | 21054 } |
| 21040 | 21055 |
| 21041 static Element _cloneAndSeperateAttributeTemplate(Element templateElement) { | 21056 // For non-template browsers, the parser will disallow <template> in certain |
| 21042 var clone = templateElement.clone(false); | 21057 // locations, so we allow "attribute templates" which combine the template |
| 21043 var attributes = templateElement.attributes; | 21058 // element with the top-level container node of the content, e.g. |
| 21044 for (var name in attributes.keys.toList()) { | 21059 // |
| 21060 // <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr> |
| 21061 // |
| 21062 // becomes |
| 21063 // |
| 21064 // <template repeat="{{ foo }}"> |
| 21065 // + #document-fragment |
| 21066 // + <tr class="bar"> |
| 21067 // + <td>Bar</td> |
| 21068 // |
| 21069 static Element _extractTemplateFromAttributeTemplate(Element el) { |
| 21070 var template = el.document.$dom_createElement('template'); |
| 21071 el.parentNode.insertBefore(template, el); |
| 21072 |
| 21073 for (var name in el.attributes.keys.toList()) { |
| 21045 switch (name) { | 21074 switch (name) { |
| 21046 case 'template': | 21075 case 'template': |
| 21076 el.attributes.remove(name); |
| 21077 break; |
| 21047 case 'repeat': | 21078 case 'repeat': |
| 21048 case 'bind': | 21079 case 'bind': |
| 21049 case 'ref': | 21080 case 'ref': |
| 21050 clone.attributes.remove(name); | 21081 template.attributes[name] = el.attributes.remove(name); |
| 21051 break; | |
| 21052 default: | |
| 21053 attributes.remove(name); | |
| 21054 break; | 21082 break; |
| 21055 } | 21083 } |
| 21056 } | 21084 } |
| 21057 | 21085 |
| 21058 return clone; | 21086 return template; |
| 21059 } | 21087 } |
| 21060 | 21088 |
| 21061 static void _liftNonNativeChildrenIntoContent(Element templateElement) { | 21089 static void _liftNonNativeChildrenIntoContent(Element template, Element el, |
| 21062 var content = templateElement.content; | 21090 bool useRoot) { |
| 21063 | 21091 |
| 21064 if (!templateElement._isAttributeTemplate) { | 21092 var content = template.content; |
| 21065 var child; | 21093 if (useRoot) { |
| 21066 while ((child = templateElement.firstChild) != null) { | 21094 content.append(el); |
| 21067 content.append(child); | |
| 21068 } | |
| 21069 return; | 21095 return; |
| 21070 } | 21096 } |
| 21071 | 21097 |
| 21072 // For attribute templates we copy the whole thing into the content and | |
| 21073 // we move the non template attributes into the content. | |
| 21074 // | |
| 21075 // <tr foo template> | |
| 21076 // | |
| 21077 // becomes | |
| 21078 // | |
| 21079 // <tr template> | |
| 21080 // + #document-fragment | |
| 21081 // + <tr foo> | |
| 21082 // | |
| 21083 var newRoot = _cloneAndSeperateAttributeTemplate(templateElement); | |
| 21084 var child; | 21098 var child; |
| 21085 while ((child = templateElement.firstChild) != null) { | 21099 while ((child = el.firstChild) != null) { |
| 21086 newRoot.append(child); | 21100 content.append(child); |
| 21087 } | 21101 } |
| 21088 content.append(newRoot); | |
| 21089 } | 21102 } |
| 21090 | 21103 |
| 21091 /** | 21104 /** |
| 21092 * This used to decorate recursively all templates from a given node. | 21105 * This used to decorate recursively all templates from a given node. |
| 21093 * | 21106 * |
| 21094 * By default [decorate] will be called on templates lazily when certain | 21107 * By default [decorate] will be called on templates lazily when certain |
| 21095 * properties such as [model] are accessed, but it can be run eagerly to | 21108 * properties such as [model] are accessed, but it can be run eagerly to |
| 21096 * decorate an entire tree recursively. | 21109 * decorate an entire tree recursively. |
| 21097 */ | 21110 */ |
| 21098 // TODO(rafaelw): Review whether this is the right public API. | 21111 // TODO(rafaelw): Review whether this is the right public API. |
| (...skipping 7664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 28763 _position = nextPosition; | 28776 _position = nextPosition; |
| 28764 return true; | 28777 return true; |
| 28765 } | 28778 } |
| 28766 _current = null; | 28779 _current = null; |
| 28767 _position = _array.length; | 28780 _position = _array.length; |
| 28768 return false; | 28781 return false; |
| 28769 } | 28782 } |
| 28770 | 28783 |
| 28771 T get current => _current; | 28784 T get current => _current; |
| 28772 } | 28785 } |
| OLD | NEW |