| Index: sdk/lib/html/templates/html/impl/impl_Element.darttemplate
|
| diff --git a/sdk/lib/html/templates/html/impl/impl_Element.darttemplate b/sdk/lib/html/templates/html/impl/impl_Element.darttemplate
|
| deleted file mode 100644
|
| index f05eb15fdd55cc6383adf13ee8d3536d9049509a..0000000000000000000000000000000000000000
|
| --- a/sdk/lib/html/templates/html/impl/impl_Element.darttemplate
|
| +++ /dev/null
|
| @@ -1,781 +0,0 @@
|
| -// Copyright (c) 2012, 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 html;
|
| -
|
| -// TODO(jacobr): use _Lists.dart to remove some of the duplicated
|
| -// functionality.
|
| -class _ChildrenElementList implements List {
|
| - // Raw Element.
|
| - final Element _element;
|
| - final HtmlCollection _childElements;
|
| -
|
| - _ChildrenElementList._wrap(Element element)
|
| - : _childElements = element.$dom_children,
|
| - _element = element;
|
| -
|
| - List<Element> _toList() {
|
| - final output = new List(_childElements.length);
|
| - for (int i = 0, len = _childElements.length; i < len; i++) {
|
| - output[i] = _childElements[i];
|
| - }
|
| - return output;
|
| - }
|
| -
|
| - bool contains(Element element) => _childElements.contains(element);
|
| -
|
| - void forEach(void f(Element element)) {
|
| - for (Element element in _childElements) {
|
| - f(element);
|
| - }
|
| - }
|
| -
|
| - List<Element> filter(bool f(Element element)) {
|
| - final output = [];
|
| - forEach((Element element) {
|
| - if (f(element)) {
|
| - output.add(element);
|
| - }
|
| - });
|
| - return new _FrozenElementList._wrap(output);
|
| - }
|
| -
|
| - bool every(bool f(Element element)) {
|
| - for (Element element in this) {
|
| - if (!f(element)) {
|
| - return false;
|
| - }
|
| - };
|
| - return true;
|
| - }
|
| -
|
| - bool some(bool f(Element element)) {
|
| - for (Element element in this) {
|
| - if (f(element)) {
|
| - return true;
|
| - }
|
| - };
|
| - return false;
|
| - }
|
| -
|
| - Collection map(f(Element element)) {
|
| - final out = [];
|
| - for (Element el in this) {
|
| - out.add(f(el));
|
| - }
|
| - return out;
|
| - }
|
| -
|
| - bool get isEmpty {
|
| - return _element.$dom_firstElementChild == null;
|
| - }
|
| -
|
| - int get length {
|
| - return _childElements.length;
|
| - }
|
| -
|
| - Element operator [](int index) {
|
| - return _childElements[index];
|
| - }
|
| -
|
| - void operator []=(int index, Element value) {
|
| - _element.$dom_replaceChild(value, _childElements[index]);
|
| - }
|
| -
|
| - void set length(int newLength) {
|
| - // TODO(jacobr): remove children when length is reduced.
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - Element add(Element value) {
|
| - _element.$dom_appendChild(value);
|
| - return value;
|
| - }
|
| -
|
| - Element addLast(Element value) => add(value);
|
| -
|
| - Iterator<Element> iterator() => _toList().iterator();
|
| -
|
| - void addAll(Collection<Element> collection) {
|
| - for (Element element in collection) {
|
| - _element.$dom_appendChild(element);
|
| - }
|
| - }
|
| -
|
| - void sort([int compare(Element a, Element b)]) {
|
| - throw new UnsupportedError('TODO(jacobr): should we impl?');
|
| - }
|
| -
|
| - dynamic reduce(dynamic initialValue,
|
| - dynamic combine(dynamic previousValue, Element element)) {
|
| - return Collections.reduce(this, initialValue, combine);
|
| - }
|
| -
|
| - void setRange(int start, int rangeLength, List from, [int startFrom = 0]) {
|
| - throw new UnimplementedError();
|
| - }
|
| -
|
| - void removeRange(int start, int rangeLength) {
|
| - throw new UnimplementedError();
|
| - }
|
| -
|
| - void insertRange(int start, int rangeLength, [initialValue = null]) {
|
| - throw new UnimplementedError();
|
| - }
|
| -
|
| - List getRange(int start, int rangeLength) =>
|
| - new _FrozenElementList._wrap(Lists.getRange(this, start, rangeLength,
|
| - []));
|
| -
|
| - int indexOf(Element element, [int start = 0]) {
|
| - return Lists.indexOf(this, element, start, this.length);
|
| - }
|
| -
|
| - int lastIndexOf(Element element, [int start = null]) {
|
| - if (start == null) start = length - 1;
|
| - return Lists.lastIndexOf(this, element, start);
|
| - }
|
| -
|
| - void clear() {
|
| - // It is unclear if we want to keep non element nodes?
|
| - _element.text = '';
|
| - }
|
| -
|
| - Element removeAt(int index) {
|
| - final result = this[index];
|
| - if (result != null) {
|
| - _element.$dom_removeChild(result);
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - Element removeLast() {
|
| - final result = this.last;
|
| - if (result != null) {
|
| - _element.$dom_removeChild(result);
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - Element get first {
|
| - return _element.$dom_firstElementChild;
|
| - }
|
| -
|
| -
|
| - Element get last {
|
| - return _element.$dom_lastElementChild;
|
| - }
|
| -}
|
| -
|
| -// TODO(jacobr): this is an inefficient implementation but it is hard to see
|
| -// a better option given that we cannot quite force NodeList to be an
|
| -// ElementList as there are valid cases where a NodeList JavaScript object
|
| -// contains Node objects that are not Elements.
|
| -class _FrozenElementList implements List {
|
| - final List<Node> _nodeList;
|
| -
|
| - _FrozenElementList._wrap(this._nodeList);
|
| -
|
| - bool contains(Element element) {
|
| - for (Element el in this) {
|
| - if (el == element) return true;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - void forEach(void f(Element element)) {
|
| - for (Element el in this) {
|
| - f(el);
|
| - }
|
| - }
|
| -
|
| - Collection map(f(Element element)) {
|
| - final out = [];
|
| - for (Element el in this) {
|
| - out.add(f(el));
|
| - }
|
| - return out;
|
| - }
|
| -
|
| - List<Element> filter(bool f(Element element)) {
|
| - final out = [];
|
| - for (Element el in this) {
|
| - if (f(el)) out.add(el);
|
| - }
|
| - return out;
|
| - }
|
| -
|
| - bool every(bool f(Element element)) {
|
| - for(Element element in this) {
|
| - if (!f(element)) {
|
| - return false;
|
| - }
|
| - };
|
| - return true;
|
| - }
|
| -
|
| - bool some(bool f(Element element)) {
|
| - for(Element element in this) {
|
| - if (f(element)) {
|
| - return true;
|
| - }
|
| - };
|
| - return false;
|
| - }
|
| -
|
| - bool get isEmpty => _nodeList.isEmpty;
|
| -
|
| - int get length => _nodeList.length;
|
| -
|
| - Element operator [](int index) => _nodeList[index];
|
| -
|
| - void operator []=(int index, Element value) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - void set length(int newLength) {
|
| - _nodeList.length = newLength;
|
| - }
|
| -
|
| - void add(Element value) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - void addLast(Element value) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - Iterator<Element> iterator() => new _FrozenElementListIterator(this);
|
| -
|
| - void addAll(Collection<Element> collection) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - void sort([int compare(Element a, Element b)]) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - dynamic reduce(dynamic initialValue,
|
| - dynamic combine(dynamic previousValue, Element element)) {
|
| - return Collections.reduce(this, initialValue, combine);
|
| - }
|
| -
|
| - void setRange(int start, int rangeLength, List from, [int startFrom = 0]) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - void removeRange(int start, int rangeLength) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - void insertRange(int start, int rangeLength, [initialValue = null]) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - List<Element> getRange(int start, int rangeLength) =>
|
| - new _FrozenElementList._wrap(_nodeList.getRange(start, rangeLength));
|
| -
|
| - int indexOf(Element element, [int start = 0]) =>
|
| - _nodeList.indexOf(element, start);
|
| -
|
| - int lastIndexOf(Element element, [int start = null]) =>
|
| - _nodeList.lastIndexOf(element, start);
|
| -
|
| - void clear() {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - Element removeAt(int index) {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - Element removeLast() {
|
| - throw new UnsupportedError('');
|
| - }
|
| -
|
| - Element get first => _nodeList.first;
|
| -
|
| - Element get last => _nodeList.last;
|
| -}
|
| -
|
| -class _FrozenElementListIterator implements Iterator<Element> {
|
| - final _FrozenElementList _list;
|
| - int _index = 0;
|
| -
|
| - _FrozenElementListIterator(this._list);
|
| -
|
| - /**
|
| - * Gets the next element in the iteration. Throws a
|
| - * [StateError("No more elements")] if no element is left.
|
| - */
|
| - Element next() {
|
| - if (!hasNext) {
|
| - throw new StateError("No more elements");
|
| - }
|
| -
|
| - return _list[_index++];
|
| - }
|
| -
|
| - /**
|
| - * Returns whether the [Iterator] has elements left.
|
| - */
|
| - bool get hasNext => _index < _list.length;
|
| -}
|
| -
|
| -class _ElementCssClassSet extends CssClassSet {
|
| -
|
| - final Element _element;
|
| -
|
| - _ElementCssClassSet(this._element);
|
| -
|
| - Set<String> readClasses() {
|
| - var s = new Set<String>();
|
| - var classname = _element.$dom_className;
|
| -
|
| - for (String name in classname.split(' ')) {
|
| - String trimmed = name.trim();
|
| - if (!trimmed.isEmpty) {
|
| - s.add(trimmed);
|
| - }
|
| - }
|
| - return s;
|
| - }
|
| -
|
| - void writeClasses(Set<String> s) {
|
| - List list = new List.from(s);
|
| - _element.$dom_className = Strings.join(list, ' ');
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * An abstract class, which all HTML elements extend.
|
| - */
|
| -abstract class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
|
| -
|
| - /**
|
| - * Creates an HTML element from a valid fragment of HTML.
|
| - *
|
| - * The [html] fragment must represent valid HTML with a single element root,
|
| - * which will be parsed and returned.
|
| - *
|
| - * Important: the contents of [html] should not contain any user-supplied
|
| - * data. Without strict data validation it is impossible to prevent script
|
| - * injection exploits.
|
| - *
|
| - * It is instead recommended that elements be constructed via [Element.tag]
|
| - * and text be added via [text].
|
| - *
|
| - * var element = new Element.html('<div class="foo">content</div>');
|
| - */
|
| - factory $CLASSNAME.html(String html) =>
|
| - _$(CLASSNAME)FactoryProvider.createElement_html(html);
|
| -
|
| - /**
|
| - * Creates the HTML element specified by the tag name.
|
| - *
|
| - * This is similar to [Document.createElement].
|
| - * [tag] should be a valid HTML tag name. If [tag] is an unknown tag then
|
| - * this will create an [UnknownElement].
|
| - *
|
| - * var divElement = new Element.tag('div');
|
| - * print(divElement is DivElement); // 'true'
|
| - * var myElement = new Element.tag('unknownTag');
|
| - * print(myElement is UnknownElement); // 'true'
|
| - *
|
| - * For standard elements it is more preferable to use the type constructors:
|
| - * var element = new DivElement();
|
| - */
|
| - factory $CLASSNAME.tag(String tag) =>
|
| - _$(CLASSNAME)FactoryProvider.createElement_tag(tag);
|
| -
|
| - /**
|
| - * All attributes on this element.
|
| - *
|
| - * Any modifications to the attribute map will automatically be applied to
|
| - * this element.
|
| - *
|
| - * This only includes attributes which are not in a namespace
|
| - * (such as 'xlink:href'), additional attributes can be accessed via
|
| - * [getNamespacedAttributes].
|
| - */
|
| - Map<String, String> get attributes => new _ElementAttributeMap(this);
|
| -
|
| - void set attributes(Map<String, String> value) {
|
| - Map<String, String> attributes = this.attributes;
|
| - attributes.clear();
|
| - for (String key in value.keys) {
|
| - attributes[key] = value[key];
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Deprecated, use innerHtml instead.
|
| - */
|
| - @deprecated
|
| - String get innerHTML => this.innerHtml;
|
| - @deprecated
|
| - void set innerHTML(String value) {
|
| - this.innerHtml = value;
|
| - }
|
| -
|
| - @deprecated
|
| - void set elements(Collection<Element> value) {
|
| - this.children = value;
|
| - }
|
| -
|
| - /**
|
| - * Deprecated, use [children] instead.
|
| - */
|
| - @deprecated
|
| - List<Element> get elements => this.children;
|
| -
|
| - /**
|
| - * List of the direct children of this element.
|
| - *
|
| - * This collection can be used to add and remove elements from the document.
|
| - *
|
| - * var item = new DivElement();
|
| - * item.text = 'Something';
|
| - * document.body.children.add(item) // Item is now displayed on the page.
|
| - * for (var element in document.body.children) {
|
| - * element.style.background = 'red'; // Turns every child of body red.
|
| - * }
|
| - */
|
| - List<Element> get children => new _ChildrenElementList._wrap(this);
|
| -
|
| - void set children(List<Element> value) {
|
| - // Copy list first since we don't want liveness during iteration.
|
| - List copy = new List.from(value);
|
| - var children = this.children;
|
| - children.clear();
|
| - children.addAll(copy);
|
| - }
|
| -
|
| - /**
|
| - * Finds the first descendant element of this element that matches the
|
| - * specified group of selectors.
|
| - *
|
| - * [selectors] should be a string using CSS selector syntax.
|
| - *
|
| - * // Gets the first descendant with the class 'classname'
|
| - * var element = element.query('.className');
|
| - * // Gets the element with id 'id'
|
| - * var element = element.query('#id');
|
| - * // Gets the first descendant [ImageElement]
|
| - * var img = element.query('img');
|
| - *
|
| - * See also:
|
| - *
|
| - * * [CSS Selectors](http://docs.webplatform.org/wiki/css/selectors)
|
| - */
|
| - Element query(String selectors) => $dom_querySelector(selectors);
|
| -
|
| - /**
|
| - * Finds all descendent elements of this element that match the specified
|
| - * group of selectors.
|
| - *
|
| - * [selectors] should be a string using CSS selector syntax.
|
| - *
|
| - * var items = element.query('.itemClassName');
|
| - */
|
| - List<Element> queryAll(String selectors) =>
|
| - new _FrozenElementList._wrap($dom_querySelectorAll(selectors));
|
| -
|
| - /**
|
| - * The set of CSS classes applied to this element.
|
| - *
|
| - * This set makes it easy to add, remove or toggle the classes applied to
|
| - * this element.
|
| - *
|
| - * element.classes.add('selected');
|
| - * element.classes.toggle('isOnline');
|
| - * element.classes.remove('selected');
|
| - */
|
| - CssClassSet get classes => new _ElementCssClassSet(this);
|
| -
|
| - void set classes(Collection<String> value) {
|
| - CssClassSet classSet = classes;
|
| - classSet.clear();
|
| - classSet.addAll(value);
|
| - }
|
| -
|
| - /**
|
| - * Allows access to all custom data attributes (data-*) set on this element.
|
| - *
|
| - * The keys for the map must follow these rules:
|
| - *
|
| - * * The name must not begin with 'xml'.
|
| - * * The name cannot contain a semi-colon (';').
|
| - * * The name cannot contain any capital letters.
|
| - *
|
| - * Any keys from markup will be converted to camel-cased keys in the map.
|
| - *
|
| - * For example, HTML specified as:
|
| - *
|
| - * <div data-my-random-value='value'></div>
|
| - *
|
| - * Would be accessed in Dart as:
|
| - *
|
| - * var value = element.dataAttributes['myRandomValue'];
|
| - *
|
| - * See also:
|
| - *
|
| - * * [Custom data attributes](http://www.w3.org/TR/html5/global-attributes.html#custom-data-attribute)
|
| - */
|
| - Map<String, String> get dataAttributes =>
|
| - new _DataAttributeMap(attributes);
|
| -
|
| - void set dataAttributes(Map<String, String> value) {
|
| - final dataAttributes = this.dataAttributes;
|
| - dataAttributes.clear();
|
| - for (String key in value.keys) {
|
| - dataAttributes[key] = value[key];
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Gets a map for manipulating the attributes of a particular namespace.
|
| - *
|
| - * This is primarily useful for SVG attributes such as xref:link.
|
| - */
|
| - Map<String, String> getNamespacedAttributes(String namespace) {
|
| - return new _NamespacedAttributeMap(this, namespace);
|
| - }
|
| -
|
| - /**
|
| - * The set of all CSS values applied to this element, including inherited
|
| - * and default values.
|
| - *
|
| - * The computedStyle contains values that are inherited from other
|
| - * sources, such as parent elements or stylesheets. This differs from the
|
| - * [style] property, which contains only the values specified directly on this
|
| - * element.
|
| - *
|
| - * See also:
|
| - *
|
| - * * [CSS Inheritance and Cascade](http://docs.webplatform.org/wiki/tutorials/inheritance_and_cascade)
|
| - */
|
| - Future<CssStyleDeclaration> get computedStyle {
|
| - // TODO(jacobr): last param should be null, see b/5045788
|
| - return getComputedStyle('');
|
| - }
|
| -
|
| - /**
|
| - * Returns the computed styles for pseudo-elements such as `::after`,
|
| - * `::before`, `::marker`, `::line-marker`.
|
| - *
|
| - * See also:
|
| - *
|
| - * * [Pseudo-elements](http://docs.webplatform.org/wiki/css/selectors/pseudo-elements)
|
| - */
|
| - Future<CssStyleDeclaration> getComputedStyle(String pseudoElement) {
|
| - return _createMeasurementFuture(
|
| - () => window.$dom_getComputedStyle(this, pseudoElement),
|
| - new Completer<CssStyleDeclaration>());
|
| - }
|
| -
|
| - /**
|
| - * Adds the specified element to after the last child of this element.
|
| - */
|
| - void append(Element e) {
|
| - this.children.add(e);
|
| - }
|
| -
|
| - /**
|
| - * Adds the specified text as a text node after the last child of this
|
| - * element.
|
| - */
|
| - void appendText(String text) {
|
| - this.insertAdjacentText('beforeend', text);
|
| - }
|
| -
|
| - /**
|
| - * Parses the specified text as HTML and adds the resulting node after the
|
| - * last child of this element.
|
| - */
|
| - void appendHtml(String text) {
|
| - this.insertAdjacentHtml('beforeend', text);
|
| - }
|
| -
|
| - // Hooks to support custom WebComponents.
|
| - /**
|
| - * Experimental support for [web components][wc]. This field stores a
|
| - * reference to the component implementation. It was inspired by Mozilla's
|
| - * [x-tags][] project. Please note: in the future it may be possible to
|
| - * `extend Element` from your class, in which case this field will be
|
| - * deprecated and will simply return this [Element] object.
|
| - *
|
| - * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
|
| - * [x-tags]: http://x-tags.org/
|
| - */
|
| -$if DART2JS
|
| - @Creates('Null') // Set from Dart code; does not instantiate a native type.
|
| -$endif
|
| - var xtag;
|
| -
|
| -$if DART2JS
|
| - /**
|
| - * Creates a text node and inserts it into the DOM at the specified location.
|
| - *
|
| - * To see the possible values for [where], read the doc for
|
| - * [insertAdjacentHtml].
|
| - *
|
| - * See also:
|
| - *
|
| - * * [insertAdjacentHtml]
|
| - */
|
| - void insertAdjacentText(String where, String text) {
|
| - if (JS('bool', '!!#.insertAdjacentText', this)) {
|
| - _insertAdjacentText(where, text);
|
| - } else {
|
| - _insertAdjacentNode(where, new Text(text));
|
| - }
|
| - }
|
| -
|
| - @JSName('insertAdjacentText')
|
| - void _insertAdjacentText(String where, String text) native;
|
| -
|
| - /**
|
| - * Parses text as an HTML fragment and inserts it into the DOM at the
|
| - * specified location.
|
| - *
|
| - * The [where] parameter indicates where to insert the HTML fragment:
|
| - *
|
| - * * 'beforeBegin': Immediately before this element.
|
| - * * 'afterBegin': As the first child of this element.
|
| - * * 'beforeEnd': As the last child of this element.
|
| - * * 'afterEnd': Immediately after this element.
|
| - *
|
| - * var html = '<div class="something">content</div>';
|
| - * // Inserts as the first child
|
| - * document.body.insertAdjacentHtml('afterBegin', html);
|
| - * var createdElement = document.body.children[0];
|
| - * print(createdElement.classes[0]); // Prints 'something'
|
| - *
|
| - * See also:
|
| - *
|
| - * * [insertAdjacentText]
|
| - * * [insertAdjacentElement]
|
| - */
|
| - void insertAdjacentHtml(String where, String text) {
|
| - if (JS('bool', '!!#.insertAdjacentHtml', this)) {
|
| - _insertAdjacentHtml(where, text);
|
| - } else {
|
| - _insertAdjacentNode(where, new DocumentFragment.html(text));
|
| - }
|
| - }
|
| -
|
| - @JSName('insertAdjacentHTML')
|
| - void _insertAdjacentHTML(String where, String text) native;
|
| -
|
| - /**
|
| - * Inserts [element] into the DOM at the specified location.
|
| - *
|
| - * To see the possible values for [where], read the doc for
|
| - * [insertAdjacentHtml].
|
| - *
|
| - * See also:
|
| - *
|
| - * * [insertAdjacentHtml]
|
| - */
|
| - Element insertAdjacentElement(String where, Element element) {
|
| - if (JS('bool', '!!#.insertAdjacentElement', this)) {
|
| - _insertAdjacentElement(where, element);
|
| - } else {
|
| - _insertAdjacentNode(where, element);
|
| - }
|
| - return element;
|
| - }
|
| -
|
| - @JSName('insertAdjacentElement')
|
| - void _insertAdjacentElement(String where, Element element) native;
|
| -
|
| - void _insertAdjacentNode(String where, Node node) {
|
| - switch (where.toLowerCase()) {
|
| - case 'beforebegin':
|
| - this.parentNode.insertBefore(node, this);
|
| - break;
|
| - case 'afterbegin':
|
| - var first = this.nodes.length > 0 ? this.nodes[0] : null;
|
| - this.insertBefore(node, first);
|
| - break;
|
| - case 'beforeend':
|
| - this.nodes.add(node);
|
| - break;
|
| - case 'afterend':
|
| - this.parentNode.insertBefore(node, this.nextNode);
|
| - break;
|
| - default:
|
| - throw new ArgumentError("Invalid position ${where}");
|
| - }
|
| - }
|
| -$else
|
| -$endif
|
| -
|
| -$!MEMBERS
|
| -}
|
| -
|
| -final _START_TAG_REGEXP = new RegExp('<(\\w+)');
|
| -class _ElementFactoryProvider {
|
| - static final _CUSTOM_PARENT_TAG_MAP = const {
|
| - 'body' : 'html',
|
| - 'head' : 'html',
|
| - 'caption' : 'table',
|
| - 'td': 'tr',
|
| - 'colgroup': 'table',
|
| - 'col' : 'colgroup',
|
| - 'tr' : 'tbody',
|
| - 'tbody' : 'table',
|
| - 'tfoot' : 'table',
|
| - 'thead' : 'table',
|
| - 'track' : 'audio',
|
| - };
|
| -
|
| - /** @domName Document.createElement */
|
| - static Element createElement_html(String html) {
|
| - // TODO(jacobr): this method can be made more robust and performant.
|
| - // 1) Cache the dummy parent elements required to use innerHTML rather than
|
| - // creating them every call.
|
| - // 2) Verify that the html does not contain leading or trailing text nodes.
|
| - // 3) Verify that the html does not contain both <head> and <body> tags.
|
| - // 4) Detatch the created element from its dummy parent.
|
| - String parentTag = 'div';
|
| - String tag;
|
| - final match = _START_TAG_REGEXP.firstMatch(html);
|
| - if (match != null) {
|
| - tag = match.group(1).toLowerCase();
|
| - if (_CUSTOM_PARENT_TAG_MAP.containsKey(tag)) {
|
| - parentTag = _CUSTOM_PARENT_TAG_MAP[tag];
|
| - }
|
| - }
|
| - final Element temp = new Element.tag(parentTag);
|
| - temp.innerHtml = html;
|
| -
|
| - Element element;
|
| - if (temp.children.length == 1) {
|
| - element = temp.children[0];
|
| - } else if (parentTag == 'html' && temp.children.length == 2) {
|
| - // Work around for edge case in WebKit and possibly other browsers where
|
| - // both body and head elements are created even though the inner html
|
| - // only contains a head or body element.
|
| - element = temp.children[tag == 'head' ? 0 : 1];
|
| - } else {
|
| - throw new ArgumentError('HTML had ${temp.children.length} '
|
| - 'top level elements but 1 expected');
|
| - }
|
| - element.remove();
|
| - return element;
|
| - }
|
| -
|
| - /** @domName Document.createElement */
|
| -$if DART2JS
|
| - // Optimization to improve performance until the dart2js compiler inlines this
|
| - // method.
|
| - static Element createElement_tag(String tag) =>
|
| - JS('Element', 'document.createElement(#)', tag);
|
| -$else
|
| - static Element createElement_tag(String tag) =>
|
| - document.$dom_createElement(tag);
|
| -$endif
|
| -}
|
|
|