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

Side by Side Diff: lib/dom/templates/html/impl/impl_Element.darttemplate

Issue 10913125: Remove lib/dom directory! (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 // TODO(jacobr): use _Lists.dart to remove some of the duplicated
6 // functionality.
7 class _ChildrenElementList implements ElementList {
8 // Raw Element.
9 final _ElementImpl _element;
10 final _HTMLCollectionImpl _childElements;
11
12 _ChildrenElementList._wrap(_ElementImpl element)
13 : _childElements = element.$dom_children,
14 _element = element;
15
16 List<Element> _toList() {
17 final output = new List(_childElements.length);
18 for (int i = 0, len = _childElements.length; i < len; i++) {
19 output[i] = _childElements[i];
20 }
21 return output;
22 }
23
24 _ElementImpl get first() {
25 return _element.$dom_firstElementChild;
26 }
27
28 void forEach(void f(Element element)) {
29 for (_ElementImpl element in _childElements) {
30 f(element);
31 }
32 }
33
34 ElementList filter(bool f(Element element)) {
35 final output = <Element>[];
36 forEach((Element element) {
37 if (f(element)) {
38 output.add(element);
39 }
40 });
41 return new _FrozenElementList._wrap(output);
42 }
43
44 bool every(bool f(Element element)) {
45 for(Element element in this) {
46 if (!f(element)) {
47 return false;
48 }
49 };
50 return true;
51 }
52
53 bool some(bool f(Element element)) {
54 for(Element element in this) {
55 if (f(element)) {
56 return true;
57 }
58 };
59 return false;
60 }
61
62 Collection map(f(Element element)) {
63 final out = [];
64 for (Element el in this) {
65 out.add(f(el));
66 }
67 return out;
68 }
69
70 bool isEmpty() {
71 return _element.$dom_firstElementChild == null;
72 }
73
74 int get length() {
75 return _childElements.length;
76 }
77
78 _ElementImpl operator [](int index) {
79 return _childElements[index];
80 }
81
82 void operator []=(int index, _ElementImpl value) {
83 _element.$dom_replaceChild(value, _childElements[index]);
84 }
85
86 void set length(int newLength) {
87 // TODO(jacobr): remove children when length is reduced.
88 throw const UnsupportedOperationException('');
89 }
90
91 Element add(_ElementImpl value) {
92 _element.$dom_appendChild(value);
93 return value;
94 }
95
96 Element addLast(_ElementImpl value) => add(value);
97
98 Iterator<Element> iterator() => _toList().iterator();
99
100 void addAll(Collection<Element> collection) {
101 for (_ElementImpl element in collection) {
102 _element.$dom_appendChild(element);
103 }
104 }
105
106 void sort(int compare(Element a, Element b)) {
107 throw const UnsupportedOperationException('TODO(jacobr): should we impl?');
108 }
109
110 void setRange(int start, int rangeLength, List from, [int startFrom = 0]) {
111 throw const NotImplementedException();
112 }
113
114 void removeRange(int start, int rangeLength) {
115 throw const NotImplementedException();
116 }
117
118 void insertRange(int start, int rangeLength, [initialValue = null]) {
119 throw const NotImplementedException();
120 }
121
122 List getRange(int start, int rangeLength) =>
123 new _FrozenElementList._wrap(_Lists.getRange(this, start, rangeLength,
124 <Element>[]));
125
126 int indexOf(Element element, [int start = 0]) {
127 return _Lists.indexOf(this, element, start, this.length);
128 }
129
130 int lastIndexOf(Element element, [int start = null]) {
131 if (start === null) start = length - 1;
132 return _Lists.lastIndexOf(this, element, start);
133 }
134
135 void clear() {
136 // It is unclear if we want to keep non element nodes?
137 _element.text = '';
138 }
139
140 Element removeLast() {
141 final result = this.last();
142 if (result != null) {
143 _element.$dom_removeChild(result);
144 }
145 return result;
146 }
147
148 Element last() {
149 return _element.$dom_lastElementChild;
150 }
151 }
152
153 // TODO(jacobr): this is an inefficient implementation but it is hard to see
154 // a better option given that we cannot quite force NodeList to be an
155 // ElementList as there are valid cases where a NodeList JavaScript object
156 // contains Node objects that are not Elements.
157 class _FrozenElementList implements ElementList {
158 final List<Node> _nodeList;
159
160 _FrozenElementList._wrap(this._nodeList);
161
162 Element get first() {
163 return _nodeList[0];
164 }
165
166 void forEach(void f(Element element)) {
167 for (Element el in this) {
168 f(el);
169 }
170 }
171
172 Collection map(f(Element element)) {
173 final out = [];
174 for (Element el in this) {
175 out.add(f(el));
176 }
177 return out;
178 }
179
180 ElementList filter(bool f(Element element)) {
181 final out = new _ElementList([]);
182 for (Element el in this) {
183 if (f(el)) out.add(el);
184 }
185 return out;
186 }
187
188 bool every(bool f(Element element)) {
189 for(Element element in this) {
190 if (!f(element)) {
191 return false;
192 }
193 };
194 return true;
195 }
196
197 bool some(bool f(Element element)) {
198 for(Element element in this) {
199 if (f(element)) {
200 return true;
201 }
202 };
203 return false;
204 }
205
206 bool isEmpty() => _nodeList.isEmpty();
207
208 int get length() => _nodeList.length;
209
210 Element operator [](int index) => _nodeList[index];
211
212 void operator []=(int index, Element value) {
213 throw const UnsupportedOperationException('');
214 }
215
216 void set length(int newLength) {
217 _nodeList.length = newLength;
218 }
219
220 void add(Element value) {
221 throw const UnsupportedOperationException('');
222 }
223
224 void addLast(Element value) {
225 throw const UnsupportedOperationException('');
226 }
227
228 Iterator<Element> iterator() => new _FrozenElementListIterator(this);
229
230 void addAll(Collection<Element> collection) {
231 throw const UnsupportedOperationException('');
232 }
233
234 void sort(int compare(Element a, Element b)) {
235 throw const UnsupportedOperationException('');
236 }
237
238 void setRange(int start, int rangeLength, List from, [int startFrom = 0]) {
239 throw const UnsupportedOperationException('');
240 }
241
242 void removeRange(int start, int rangeLength) {
243 throw const UnsupportedOperationException('');
244 }
245
246 void insertRange(int start, int rangeLength, [initialValue = null]) {
247 throw const UnsupportedOperationException('');
248 }
249
250 ElementList getRange(int start, int rangeLength) =>
251 new _FrozenElementList._wrap(_nodeList.getRange(start, rangeLength));
252
253 int indexOf(Element element, [int start = 0]) =>
254 _nodeList.indexOf(element, start);
255
256 int lastIndexOf(Element element, [int start = null]) =>
257 _nodeList.lastIndexOf(element, start);
258
259 void clear() {
260 throw const UnsupportedOperationException('');
261 }
262
263 Element removeLast() {
264 throw const UnsupportedOperationException('');
265 }
266
267 Element last() => _nodeList.last();
268 }
269
270 class _FrozenElementListIterator implements Iterator<Element> {
271 final _FrozenElementList _list;
272 int _index = 0;
273
274 _FrozenElementListIterator(this._list);
275
276 /**
277 * Gets the next element in the iteration. Throws a
278 * [NoMoreElementsException] if no element is left.
279 */
280 Element next() {
281 if (!hasNext()) {
282 throw const NoMoreElementsException();
283 }
284
285 return _list[_index++];
286 }
287
288 /**
289 * Returns whether the [Iterator] has elements left.
290 */
291 bool hasNext() => _index < _list.length;
292 }
293
294 class _ElementList extends _ListWrapper<Element> implements ElementList {
295 _ElementList(List<Element> list) : super(list);
296
297 ElementList filter(bool f(Element element)) =>
298 new _ElementList(super.filter(f));
299
300 ElementList getRange(int start, int rangeLength) =>
301 new _ElementList(super.getRange(start, rangeLength));
302 }
303
304 class _ElementAttributeMap implements AttributeMap {
305
306 final _ElementImpl _element;
307
308 _ElementAttributeMap(this._element);
309
310 bool containsValue(String value) {
311 final attributes = _element.$dom_attributes;
312 for (int i = 0, len = attributes.length; i < len; i++) {
313 if(value == attributes[i].value) {
314 return true;
315 }
316 }
317 return false;
318 }
319
320 bool containsKey(String key) {
321 return _element.$dom_hasAttribute(key);
322 }
323
324 String operator [](String key) {
325 return _element.$dom_getAttribute(key);
326 }
327
328 void operator []=(String key, value) {
329 _element.$dom_setAttribute(key, '$value');
330 }
331
332 String putIfAbsent(String key, String ifAbsent()) {
333 if (!containsKey(key)) {
334 this[key] = ifAbsent();
335 }
336 return this[key];
337 }
338
339 String remove(String key) {
340 String value = _element.$dom_getAttribute(key);
341 _element.$dom_removeAttribute(key);
342 return value;
343 }
344
345 void clear() {
346 final attributes = _element.$dom_attributes;
347 for (int i = attributes.length - 1; i >= 0; i--) {
348 remove(attributes[i].name);
349 }
350 }
351
352 void forEach(void f(String key, String value)) {
353 final attributes = _element.$dom_attributes;
354 for (int i = 0, len = attributes.length; i < len; i++) {
355 final item = attributes[i];
356 f(item.name, item.value);
357 }
358 }
359
360 Collection<String> getKeys() {
361 // TODO(jacobr): generate a lazy collection instead.
362 final attributes = _element.$dom_attributes;
363 final keys = new List<String>(attributes.length);
364 for (int i = 0, len = attributes.length; i < len; i++) {
365 keys[i] = attributes[i].name;
366 }
367 return keys;
368 }
369
370 Collection<String> getValues() {
371 // TODO(jacobr): generate a lazy collection instead.
372 final attributes = _element.$dom_attributes;
373 final values = new List<String>(attributes.length);
374 for (int i = 0, len = attributes.length; i < len; i++) {
375 values[i] = attributes[i].value;
376 }
377 return values;
378 }
379
380 /**
381 * The number of {key, value} pairs in the map.
382 */
383 int get length() {
384 return _element.$dom_attributes.length;
385 }
386
387 /**
388 * Returns true if there is no {key, value} pair in the map.
389 */
390 bool isEmpty() {
391 return length == 0;
392 }
393 }
394
395 /**
396 * Provides a Map abstraction on top of data-* attributes, similar to the
397 * dataSet in the old DOM.
398 */
399 class _DataAttributeMap implements AttributeMap {
400
401 final Map<String, String> $dom_attributes;
402
403 _DataAttributeMap(this.$dom_attributes);
404
405 // interface Map
406
407 // TODO: Use lazy iterator when it is available on Map.
408 bool containsValue(String value) => getValues().some((v) => v == value);
409
410 bool containsKey(String key) => $dom_attributes.containsKey(_attr(key));
411
412 String operator [](String key) => $dom_attributes[_attr(key)];
413
414 void operator []=(String key, value) {
415 $dom_attributes[_attr(key)] = '$value';
416 }
417
418 String putIfAbsent(String key, String ifAbsent()) =>
419 $dom_attributes.putIfAbsent(_attr(key), ifAbsent);
420
421 String remove(String key) => $dom_attributes.remove(_attr(key));
422
423 void clear() {
424 // Needs to operate on a snapshot since we are mutating the collection.
425 for (String key in getKeys()) {
426 remove(key);
427 }
428 }
429
430 void forEach(void f(String key, String value)) {
431 $dom_attributes.forEach((String key, String value) {
432 if (_matches(key)) {
433 f(_strip(key), value);
434 }
435 });
436 }
437
438 Collection<String> getKeys() {
439 final keys = new List<String>();
440 $dom_attributes.forEach((String key, String value) {
441 if (_matches(key)) {
442 keys.add(_strip(key));
443 }
444 });
445 return keys;
446 }
447
448 Collection<String> getValues() {
449 final values = new List<String>();
450 $dom_attributes.forEach((String key, String value) {
451 if (_matches(key)) {
452 values.add(value);
453 }
454 });
455 return values;
456 }
457
458 int get length() => getKeys().length;
459
460 // TODO: Use lazy iterator when it is available on Map.
461 bool isEmpty() => length == 0;
462
463 // Helpers.
464 String _attr(String key) => 'data-$key';
465 bool _matches(String key) => key.startsWith('data-');
466 String _strip(String key) => key.substring(5);
467 }
468
469 class _CssClassSet implements CSSClassSet {
470
471 final _ElementImpl _element;
472
473 _CssClassSet(this._element);
474
475 String toString() => _formatSet(_read());
476
477 // interface Iterable - BEGIN
478 Iterator<String> iterator() => _read().iterator();
479 // interface Iterable - END
480
481 // interface Collection - BEGIN
482 void forEach(void f(String element)) {
483 _read().forEach(f);
484 }
485
486 Collection map(f(String element)) => _read().map(f);
487
488 Collection<String> filter(bool f(String element)) => _read().filter(f);
489
490 bool every(bool f(String element)) => _read().every(f);
491
492 bool some(bool f(String element)) => _read().some(f);
493
494 bool isEmpty() => _read().isEmpty();
495
496 bool get isFrozen() => false;
497
498 int get length() =>_read().length;
499
500 // interface Collection - END
501
502 // interface Set - BEGIN
503 bool contains(String value) => _read().contains(value);
504
505 void add(String value) {
506 // TODO - figure out if we need to do any validation here
507 // or if the browser natively does enough
508 _modify((s) => s.add(value));
509 }
510
511 bool remove(String value) {
512 Set<String> s = _read();
513 bool result = s.remove(value);
514 _write(s);
515 return result;
516 }
517
518 bool toggle(String value) {
519 Set<String> s = _read();
520 bool result = false;
521 if (s.contains(value)) {
522 s.remove(value);
523 } else {
524 s.add(value);
525 result = true;
526 }
527 _write(s);
528 return result;
529 }
530
531 void addAll(Collection<String> collection) {
532 // TODO - see comment above about validation
533 _modify((s) => s.addAll(collection));
534 }
535
536 void removeAll(Collection<String> collection) {
537 _modify((s) => s.removeAll(collection));
538 }
539
540 bool isSubsetOf(Collection<String> collection) =>
541 _read().isSubsetOf(collection);
542
543 bool containsAll(Collection<String> collection) =>
544 _read().containsAll(collection);
545
546 Set<String> intersection(Collection<String> other) =>
547 _read().intersection(other);
548
549 void clear() {
550 _modify((s) => s.clear());
551 }
552 // interface Set - END
553
554 /**
555 * Helper method used to modify the set of css classes on this element.
556 *
557 * f - callback with:
558 * s - a Set of all the css class name currently on this element.
559 *
560 * After f returns, the modified set is written to the
561 * className property of this element.
562 */
563 void _modify( f(Set<String> s)) {
564 Set<String> s = _read();
565 f(s);
566 _write(s);
567 }
568
569 /**
570 * Read the class names from the Element class property,
571 * and put them into a set (duplicates are discarded).
572 */
573 Set<String> _read() {
574 // TODO(mattsh) simplify this once split can take regex.
575 Set<String> s = new Set<String>();
576 for (String name in _classname().split(' ')) {
577 String trimmed = name.trim();
578 if (!trimmed.isEmpty()) {
579 s.add(trimmed);
580 }
581 }
582 return s;
583 }
584
585 /**
586 * Read the class names as a space-separated string. This is meant to be
587 * overridden by subclasses.
588 */
589 String _classname() => _element.$dom_className;
590
591 /**
592 * Join all the elements of a set into one string and write
593 * back to the element.
594 */
595 void _write(Set s) {
596 _element.$dom_className = _formatSet(s);
597 }
598
599 String _formatSet(Set<String> s) {
600 // TODO(mattsh) should be able to pass Set to String.joins http:/b/5398605
601 List list = new List.from(s);
602 return Strings.join(list, ' ');
603 }
604 }
605
606 class _SimpleClientRect implements ClientRect {
607 final num left;
608 final num top;
609 final num width;
610 final num height;
611 num get right() => left + width;
612 num get bottom() => top + height;
613
614 const _SimpleClientRect(this.left, this.top, this.width, this.height);
615
616 bool operator ==(ClientRect other) {
617 return other !== null && left == other.left && top == other.top
618 && width == other.width && height == other.height;
619 }
620
621 String toString() => "($left, $top, $width, $height)";
622 }
623
624 // TODO(jacobr): we cannot currently be lazy about calculating the client
625 // rects as we must perform all measurement queries at a safe point to avoid
626 // triggering unneeded layouts.
627 /**
628 * All your element measurement needs in one place
629 * @domName none
630 */
631 class _ElementRectImpl implements ElementRect {
632 final ClientRect client;
633 final ClientRect offset;
634 final ClientRect scroll;
635
636 // TODO(jacobr): should we move these outside of ElementRect to avoid the
637 // overhead of computing them every time even though they are rarely used.
638 final _ClientRectImpl _boundingClientRect;
639 final _ClientRectListImpl _clientRects;
640
641 _ElementRectImpl(_ElementImpl element) :
642 client = new _SimpleClientRect(element.$dom_clientLeft,
643 element.$dom_clientTop,
644 element.$dom_clientWidth,
645 element.$dom_clientHeight),
646 offset = new _SimpleClientRect(element.$dom_offsetLeft,
647 element.$dom_offsetTop,
648 element.$dom_offsetWidth,
649 element.$dom_offsetHeight),
650 scroll = new _SimpleClientRect(element.$dom_scrollLeft,
651 element.$dom_scrollTop,
652 element.$dom_scrollWidth,
653 element.$dom_scrollHeight),
654 _boundingClientRect = element.$dom_getBoundingClientRect(),
655 _clientRects = element.$dom_getClientRects();
656
657 _ClientRectImpl get bounding() => _boundingClientRect;
658
659 // TODO(jacobr): cleanup.
660 List<ClientRect> get clientRects() {
661 final out = new List(_clientRects.length);
662 for (num i = 0; i < _clientRects.length; i++) {
663 out[i] = _clientRects.item(i);
664 }
665 return out;
666 }
667 }
668
669 class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
670
671 /**
672 * @domName Element.hasAttribute, Element.getAttribute, Element.setAttribute,
673 * Element.removeAttribute
674 */
675 _ElementAttributeMap get attributes() => new _ElementAttributeMap(this);
676
677 void set attributes(Map<String, String> value) {
678 Map<String, String> attributes = this.attributes;
679 attributes.clear();
680 for (String key in value.getKeys()) {
681 attributes[key] = value[key];
682 }
683 }
684
685 void set elements(Collection<Element> value) {
686 final elements = this.elements;
687 elements.clear();
688 elements.addAll(value);
689 }
690
691 ElementList get elements() => new _ChildrenElementList._wrap(this);
692
693 _ElementImpl query(String selectors) => $dom_querySelector(selectors);
694
695 List<Element> queryAll(String selectors) =>
696 new _FrozenElementList._wrap($dom_querySelectorAll(selectors));
697
698 _CssClassSet get classes() => new _CssClassSet(this);
699
700 void set classes(Collection<String> value) {
701 _CssClassSet classSet = classes;
702 classSet.clear();
703 classSet.addAll(value);
704 }
705
706 Map<String, String> get dataAttributes() =>
707 new _DataAttributeMap(attributes);
708
709 void set dataAttributes(Map<String, String> value) {
710 final dataAttributes = this.dataAttributes;
711 dataAttributes.clear();
712 for (String key in value.getKeys()) {
713 dataAttributes[key] = value[key];
714 }
715 }
716
717 Future<ElementRect> get rect() {
718 return _createMeasurementFuture(
719 () => new _ElementRectImpl(this),
720 new Completer<ElementRect>());
721 }
722
723 Future<CSSStyleDeclaration> get computedStyle() {
724 // TODO(jacobr): last param should be null, see b/5045788
725 return getComputedStyle('');
726 }
727
728 Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) {
729 return _createMeasurementFuture(
730 () => _window.$dom_getComputedStyle(this, pseudoElement),
731 new Completer<CSSStyleDeclaration>());
732 }
733
734 void addText(String text) {
735 this.insertAdjacentText('beforeend', text);
736 }
737
738 void addHTML(String text) {
739 this.insertAdjacentHTML('beforeend', text);
740 }
741
742 // Hooks to support custom WebComponents.
743 var xtag;
744
745 $if DARTIUM
746 noSuchMethod(String name, List args) {
747 if (dynamicUnknownElementDispatcher == null) {
748 throw new NoSuchMethodException(this, name, args);
749 } else {
750 return dynamicUnknownElementDispatcher(this, name, args);
751 }
752 }
753 $else
754 // TODO(vsm): Implement noSuchMethod or similar for dart2js.
755 $endif
756
757 $if DART2JS
758 /** @domName Element.insertAdjacentText */
759 void insertAdjacentText(String where, String text) {
760 if (JS('bool', '!!this.insertAdjacentText')) {
761 _insertAdjacentText(where, text);
762 } else {
763 _insertAdjacentNode(where, new Text(text));
764 }
765 }
766
767 void _insertAdjacentText(String where, String text)
768 native 'insertAdjacentText';
769
770 /** @domName Element.insertAdjacentHTML */
771 void insertAdjacentHTML(String where, String text) {
772 if (JS('bool', '!!this.insertAdjacentHTML')) {
773 _insertAdjacentHTML(where, text);
774 } else {
775 _insertAdjacentNode(where, new DocumentFragment.html(text));
776 }
777 }
778
779 void _insertAdjacentHTML(String where, String text)
780 native 'insertAdjacentHTML';
781
782 /** @domName Element.insertAdjacentHTML */
783 Element insertAdjacentElement(String where, Element element) {
784 if (JS('bool', '!!this.insertAdjacentElement')) {
785 _insertAdjacentElement(where, element);
786 } else {
787 _insertAdjacentNode(where, element);
788 }
789 return element;
790 }
791
792 void _insertAdjacentElement(String where, Element element)
793 native 'insertAdjacentElement';
794
795 void _insertAdjacentNode(String where, Node node) {
796 switch (where.toLowerCase()) {
797 case 'beforebegin':
798 this.parent.insertBefore(node, this);
799 break;
800 case 'afterbegin':
801 this.insertBefore(node, this.nodes.first);
802 break;
803 case 'beforeend':
804 this.nodes.add(node);
805 break;
806 case 'afterend':
807 this.parent.insertBefore(node, this.nextNode);
808 break;
809 default:
810 throw new IllegalArgumentException("Invalid position ${where}");
811 }
812 }
813 $else
814 $endif
815
816 $!MEMBERS
817 }
818
819 // Temporary dispatch hook to support WebComponents.
820 Function dynamicUnknownElementDispatcher;
821
822 final _START_TAG_REGEXP = const RegExp('<(\\w+)');
823 class _ElementFactoryProvider {
824 static final _CUSTOM_PARENT_TAG_MAP = const {
825 'body' : 'html',
826 'head' : 'html',
827 'caption' : 'table',
828 'td': 'tr',
829 'colgroup': 'table',
830 'col' : 'colgroup',
831 'tr' : 'tbody',
832 'tbody' : 'table',
833 'tfoot' : 'table',
834 'thead' : 'table',
835 'track' : 'audio',
836 };
837
838 /** @domName Document.createElement */
839 factory Element.html(String html) {
840 // TODO(jacobr): this method can be made more robust and performant.
841 // 1) Cache the dummy parent elements required to use innerHTML rather than
842 // creating them every call.
843 // 2) Verify that the html does not contain leading or trailing text nodes.
844 // 3) Verify that the html does not contain both <head> and <body> tags.
845 // 4) Detatch the created element from its dummy parent.
846 String parentTag = 'div';
847 String tag;
848 final match = _START_TAG_REGEXP.firstMatch(html);
849 if (match !== null) {
850 tag = match.group(1).toLowerCase();
851 if (_CUSTOM_PARENT_TAG_MAP.containsKey(tag)) {
852 parentTag = _CUSTOM_PARENT_TAG_MAP[tag];
853 }
854 }
855 final _ElementImpl temp = new Element.tag(parentTag);
856 temp.innerHTML = html;
857
858 Element element;
859 if (temp.elements.length == 1) {
860 element = temp.elements.first;
861 } else if (parentTag == 'html' && temp.elements.length == 2) {
862 // Work around for edge case in WebKit and possibly other browsers where
863 // both body and head elements are created even though the inner html
864 // only contains a head or body element.
865 element = temp.elements[tag == 'head' ? 0 : 1];
866 } else {
867 throw new IllegalArgumentException('HTML had ${temp.elements.length} '
868 'top level elements but 1 expected');
869 }
870 element.remove();
871 return element;
872 }
873
874 /** @domName Document.createElement */
875 $if DART2JS
876 // Optimization to improve performance until the dart2js compiler inlines this
877 // method.
878 factory Element.tag(String tag) native "return document.createElement(tag)";
879 $else
880 factory Element.tag(String tag) => _document.$dom_createElement(tag);
881 $endif
882 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698