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 |