| OLD | NEW |
| (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 part of html; | |
| 6 | |
| 7 /** | |
| 8 * Lazy implementation of the child nodes of an element that does not request | |
| 9 * the actual child nodes of an element until strictly necessary greatly | |
| 10 * improving performance for the typical cases where it is not required. | |
| 11 */ | |
| 12 class _ChildNodeListLazy implements List { | |
| 13 final Node _this; | |
| 14 | |
| 15 _ChildNodeListLazy(this._this); | |
| 16 | |
| 17 | |
| 18 $if DART2JS | |
| 19 Node get first => JS('Node', '#.firstChild', _this); | |
| 20 Node get last => JS('Node', '#.lastChild', _this); | |
| 21 $else | |
| 22 Node get first => _this.$dom_firstChild; | |
| 23 Node get last => _this.$dom_lastChild; | |
| 24 $endif | |
| 25 | |
| 26 void add(Node value) { | |
| 27 _this.$dom_appendChild(value); | |
| 28 } | |
| 29 | |
| 30 void addLast(Node value) { | |
| 31 _this.$dom_appendChild(value); | |
| 32 } | |
| 33 | |
| 34 | |
| 35 void addAll(Collection<Node> collection) { | |
| 36 for (Node node in collection) { | |
| 37 _this.$dom_appendChild(node); | |
| 38 } | |
| 39 } | |
| 40 | |
| 41 Node removeLast() { | |
| 42 final result = last; | |
| 43 if (result != null) { | |
| 44 _this.$dom_removeChild(result); | |
| 45 } | |
| 46 return result; | |
| 47 } | |
| 48 | |
| 49 Node removeAt(int index) { | |
| 50 var result = this[index]; | |
| 51 if (result != null) { | |
| 52 _this.$dom_removeChild(result); | |
| 53 } | |
| 54 return result; | |
| 55 } | |
| 56 | |
| 57 void clear() { | |
| 58 _this.text = ''; | |
| 59 } | |
| 60 | |
| 61 void operator []=(int index, Node value) { | |
| 62 _this.$dom_replaceChild(value, this[index]); | |
| 63 } | |
| 64 | |
| 65 Iterator<Node> iterator() => _this.$dom_childNodes.iterator(); | |
| 66 | |
| 67 // TODO(jacobr): We can implement these methods much more efficiently by | |
| 68 // looking up the nodeList only once instead of once per iteration. | |
| 69 bool contains(Node element) => Collections.contains(this, element); | |
| 70 | |
| 71 void forEach(void f(Node element)) => Collections.forEach(this, f); | |
| 72 | |
| 73 dynamic reduce(dynamic initialValue, | |
| 74 dynamic combine(dynamic previousValue, Node element)) { | |
| 75 return Collections.reduce(this, initialValue, combine); | |
| 76 } | |
| 77 | |
| 78 Collection map(f(Node element)) => Collections.map(this, [], f); | |
| 79 | |
| 80 Collection<Node> filter(bool f(Node element)) => | |
| 81 Collections.filter(this, <Node>[], f); | |
| 82 | |
| 83 bool every(bool f(Node element)) => Collections.every(this, f); | |
| 84 | |
| 85 bool some(bool f(Node element)) => Collections.some(this, f); | |
| 86 | |
| 87 bool get isEmpty => this.length == 0; | |
| 88 | |
| 89 // From List<Node>: | |
| 90 | |
| 91 // TODO(jacobr): this could be implemented for child node lists. | |
| 92 // The exception we throw here is misleading. | |
| 93 void sort([int compare(Node a, Node b)]) { | |
| 94 throw new UnsupportedError("Cannot sort immutable List."); | |
| 95 } | |
| 96 | |
| 97 int indexOf(Node element, [int start = 0]) => | |
| 98 Lists.indexOf(this, element, start, this.length); | |
| 99 | |
| 100 int lastIndexOf(Node element, [int start = 0]) => | |
| 101 Lists.lastIndexOf(this, element, start); | |
| 102 | |
| 103 // FIXME: implement these. | |
| 104 void setRange(int start, int rangeLength, List<Node> from, [int startFrom]) { | |
| 105 throw new UnsupportedError( | |
| 106 "Cannot setRange on immutable List."); | |
| 107 } | |
| 108 void removeRange(int start, int rangeLength) { | |
| 109 throw new UnsupportedError( | |
| 110 "Cannot removeRange on immutable List."); | |
| 111 } | |
| 112 void insertRange(int start, int rangeLength, [Node initialValue]) { | |
| 113 throw new UnsupportedError( | |
| 114 "Cannot insertRange on immutable List."); | |
| 115 } | |
| 116 List<Node> getRange(int start, int rangeLength) => | |
| 117 Lists.getRange(this, start, rangeLength, <Node>[]); | |
| 118 | |
| 119 // -- end List<Node> mixins. | |
| 120 | |
| 121 // TODO(jacobr): benchmark whether this is more efficient or whether caching | |
| 122 // a local copy of $dom_childNodes is more efficient. | |
| 123 int get length => _this.$dom_childNodes.length; | |
| 124 | |
| 125 void set length(int value) { | |
| 126 throw new UnsupportedError( | |
| 127 "Cannot set length on immutable List."); | |
| 128 } | |
| 129 | |
| 130 Node operator[](int index) => _this.$dom_childNodes[index]; | |
| 131 } | |
| 132 | |
| 133 /// @domName $DOMNAME | |
| 134 class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { | |
| 135 List<Node> get nodes { | |
| 136 return new _ChildNodeListLazy(this); | |
| 137 } | |
| 138 | |
| 139 void set nodes(Collection<Node> value) { | |
| 140 // Copy list first since we don't want liveness during iteration. | |
| 141 // TODO(jacobr): there is a better way to do this. | |
| 142 List copy = new List.from(value); | |
| 143 text = ''; | |
| 144 for (Node node in copy) { | |
| 145 $dom_appendChild(node); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 /** | |
| 150 * Removes this node from the DOM. | |
| 151 * @domName Node.removeChild | |
| 152 */ | |
| 153 void remove() { | |
| 154 // TODO(jacobr): should we throw an exception if parent is already null? | |
| 155 // TODO(vsm): Use the native remove when available. | |
| 156 if (this.parentNode != null) { | |
| 157 final Node parent = this.parentNode; | |
| 158 parentNode.$dom_removeChild(this); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 /** | |
| 163 * Replaces this node with another node. | |
| 164 * @domName Node.replaceChild | |
| 165 */ | |
| 166 Node replaceWith(Node otherNode) { | |
| 167 try { | |
| 168 final Node parent = this.parentNode; | |
| 169 parent.$dom_replaceChild(otherNode, this); | |
| 170 } catch (e) { | |
| 171 | |
| 172 }; | |
| 173 return this; | |
| 174 } | |
| 175 | |
| 176 $!MEMBERS | |
| 177 } | |
| OLD | NEW |