Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /// A simple tree API that results from parsing html. Intended to be compatible | 1 /// A simple tree API that results from parsing html. Intended to be compatible |
| 2 /// with dart:html, but right now it resembles the classic JS DOM. | 2 /// with dart:html, but right now it resembles the classic JS DOM. |
| 3 library dom; | 3 library dom; |
| 4 | 4 |
| 5 import 'dart:collection'; | 5 import 'dart:collection'; |
| 6 import 'package:source_maps/span.dart' show FileSpan; | 6 import 'package:source_maps/span.dart' show FileSpan; |
| 7 | 7 |
| 8 import 'src/constants.dart'; | 8 import 'src/constants.dart'; |
| 9 import 'src/list_proxy.dart'; | 9 import 'src/list_proxy.dart'; |
| 10 import 'src/token.dart'; | 10 import 'src/token.dart'; |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 644 | 644 |
| 645 Node _setParent(Node node) { | 645 Node _setParent(Node node) { |
| 646 // Note: we need to remove the node from its previous parent node, if any, | 646 // Note: we need to remove the node from its previous parent node, if any, |
| 647 // before updating its parent pointer to point at our parent. | 647 // before updating its parent pointer to point at our parent. |
| 648 node.remove(); | 648 node.remove(); |
| 649 node.parent = _parent; | 649 node.parent = _parent; |
| 650 return node; | 650 return node; |
| 651 } | 651 } |
| 652 | 652 |
| 653 void add(Node value) { | 653 void add(Node value) { |
| 654 super.add(_setParent(value)); | 654 if (value is DocumentFragment) { |
| 655 addAll(value.nodes); | |
| 656 } else { | |
| 657 super.add(_setParent(value)); | |
| 658 } | |
| 655 } | 659 } |
| 656 | 660 |
| 657 void addLast(Node value) => add(value); | 661 void addLast(Node value) => add(value); |
| 658 | 662 |
| 659 void addAll(Iterable<Node> collection) { | 663 void addAll(Iterable<Node> collection) { |
| 660 // Note: we need to be careful if collection is another NodeList. | 664 // Note: we need to be careful if collection is another NodeList. |
| 661 // In particular: | 665 // In particular: |
| 662 // 1. we need to copy the items before updating their parent pointers, | 666 // 1. we need to copy the items before updating their parent pointers, |
| 663 // 2. we should update parent pointers in reverse order. That way they | 667 // 2. we should update parent pointers in reverse order. That way they |
| 664 // are removed from the original NodeList (if any) from the end, which | 668 // are removed from the original NodeList (if any) from the end, which |
| 665 // is faster. | 669 // is faster. |
| 666 var list = (collection is NodeList || collection is! List) | 670 var list = (collection is NodeList || collection is! List) |
| 667 ? collection.toList() : collection as List; | 671 ? collection.toList() : collection as List; |
| 668 for (var node in list.reversed) _setParent(node); | 672 for (var node in list.reversed) _setParent(node); |
| 669 super.addAll(list); | 673 |
| 674 for (var node in list) { | |
| 675 if (node is DocumentFragment) { | |
| 676 addAll(node.nodes); | |
| 677 } else { | |
| 678 super.add(node); | |
| 679 } | |
| 680 } | |
| 670 } | 681 } |
| 671 | 682 |
| 672 void insert(int index, Node value) { | 683 void insert(int index, Node value) { |
| 673 super.insert(index, _setParent(value)); | 684 if (value is DocumentFragment) { |
| 685 insertAll(index, value.nodes); | |
| 686 } else { | |
| 687 super.insert(index, _setParent(value)); | |
| 688 } | |
| 674 } | 689 } |
| 675 | 690 |
| 676 Node removeLast() => super.removeLast()..parent = null; | 691 Node removeLast() => super.removeLast()..parent = null; |
| 677 | 692 |
| 678 Node removeAt(int i) => super.removeAt(i)..parent = null; | 693 Node removeAt(int i) => super.removeAt(i)..parent = null; |
| 679 | 694 |
| 680 void clear() { | 695 void clear() { |
| 681 for (var node in this) node.parent = null; | 696 for (var node in this) node.parent = null; |
| 682 super.clear(); | 697 super.clear(); |
| 683 } | 698 } |
| 684 | 699 |
| 685 void operator []=(int index, Node value) { | 700 void operator []=(int index, Node value) { |
| 686 this[index].parent = null; | 701 if (value is DocumentFragment) { |
| 687 super[index] = _setParent(value); | 702 removeAt(index); |
| 703 insertAll(index, value.nodes); | |
| 704 } else { | |
| 705 this[index].parent = null; | |
| 706 super[index] = _setParent(value); | |
| 707 } | |
| 688 } | 708 } |
| 689 | 709 |
| 690 // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see | 710 // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see |
| 691 // http://code.google.com/p/dart/issues/detail?id=5371 | 711 // http://code.google.com/p/dart/issues/detail?id=5371 |
| 692 void setRange(int start, int rangeLength, List<Node> from, | 712 void setRange(int start, int rangeLength, List<Node> from, |
| 693 [int startFrom = 0]) { | 713 [int startFrom = 0]) { |
| 694 if (from is NodeList) { | 714 if (from is NodeList) { |
| 695 // Note: this is presumed to make a copy | 715 // Note: this is presumed to make a copy |
| 696 from = from.sublist(startFrom, startFrom + rangeLength); | 716 from = from.sublist(startFrom, startFrom + rangeLength); |
| 697 } | 717 } |
| 698 // Note: see comment in [addAll]. We need to be careful about the order of | 718 // Note: see comment in [addAll]. We need to be careful about the order of |
| 699 // operations if [from] is also a NodeList. | 719 // operations if [from] is also a NodeList. |
| 700 for (int i = rangeLength - 1; i >= 0; i--) { | 720 for (int i = rangeLength - 1; i >= 0; i--) { |
| 701 this[start + i].parent = null; | 721 this[start + i] = from[startFrom + i]; |
| 702 super[start + i] = _setParent(from[startFrom + i]); | |
| 703 } | 722 } |
| 704 } | 723 } |
| 705 | 724 |
| 706 void replaceRange(int start, int end, Iterable<Node> newContents) { | 725 void replaceRange(int start, int end, Iterable<Node> newContents) { |
| 707 removeRange(start, end); | 726 removeRange(start, end); |
| 708 insertAll(start, newContents); | 727 insertAll(start, newContents); |
| 709 } | 728 } |
| 710 | 729 |
| 711 void removeRange(int start, int rangeLength) { | 730 void removeRange(int start, int rangeLength) { |
| 712 for (int i = start; i < rangeLength; i++) this[i].parent = null; | 731 for (int i = start; i < rangeLength; i++) this[i].parent = null; |
| 713 super.removeRange(start, rangeLength); | 732 super.removeRange(start, rangeLength); |
| 714 } | 733 } |
| 715 | 734 |
| 716 void removeWhere(bool test(Element e)) { | 735 void removeWhere(bool test(Element e)) { |
| 717 for (var node in where(test)) { | 736 for (var node in where(test)) { |
| 718 node.parent = null; | 737 node.parent = null; |
| 719 } | 738 } |
| 720 super.removeWhere(test); | 739 super.removeWhere(test); |
| 721 } | 740 } |
| 722 | 741 |
| 723 void retainWhere(bool test(Element e)) { | 742 void retainWhere(bool test(Element e)) { |
| 724 for (var node in where((n) => !test(n))) { | 743 for (var node in where((n) => !test(n))) { |
| 725 node.parent = null; | 744 node.parent = null; |
| 726 } | 745 } |
| 727 super.retainWhere(test); | 746 super.retainWhere(test); |
| 728 } | 747 } |
| 729 | 748 |
| 730 void insertAll(int index, List<Node> nodes) { | 749 void insertAll(int index, Iterable<Node> collection) { |
| 731 for (var node in nodes) _setParent(node); | 750 var list = (collection is NodeList || collection is! List) |
| 732 super.insertAll(index, nodes); | 751 ? collection.toList() : collection as List; |
| 752 for (var node in list) { | |
| 753 insert(index++, node); | |
|
Jennifer Messerly
2014/04/04 18:24:55
this is O(N^2) right? would something like this wo
Siggi Cherem (dart-lang)
2014/04/04 19:31:56
Good catch. Made the change, also updated addAll t
| |
| 754 } | |
| 733 } | 755 } |
| 734 } | 756 } |
| 735 | 757 |
| 736 | 758 |
| 737 /// An indexable collection of a node's descendants in the document tree, | 759 /// An indexable collection of a node's descendants in the document tree, |
| 738 /// filtered so that only elements are in the collection. | 760 /// filtered so that only elements are in the collection. |
| 739 // TODO(jmesserly): this was copied from dart:html | 761 // TODO(jmesserly): this was copied from dart:html |
| 740 // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. | 762 // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. |
| 741 class FilteredElementList extends IterableBase<Element> with ListMixin<Element> | 763 class FilteredElementList extends IterableBase<Element> with ListMixin<Element> |
| 742 implements List<Element> { | 764 implements List<Element> { |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 927 | 949 |
| 928 class _ConcatTextVisitor extends TreeVisitor { | 950 class _ConcatTextVisitor extends TreeVisitor { |
| 929 final _str = new StringBuffer(); | 951 final _str = new StringBuffer(); |
| 930 | 952 |
| 931 String toString() => _str.toString(); | 953 String toString() => _str.toString(); |
| 932 | 954 |
| 933 visitText(Text node) { | 955 visitText(Text node) { |
| 934 _str.write(node.data); | 956 _str.write(node.data); |
| 935 } | 957 } |
| 936 } | 958 } |
| OLD | NEW |