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

Side by Side Diff: client/html/src/DocumentFragmentWrappingImplementation.dart

Issue 8355019: Make DocumentFragment implement Element. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 years, 2 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
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class FilteredElementList implements ElementList {
6 final Node _node;
7 final NodeList _childNodes;
8
9 FilteredElementList(Node node): _childNodes = node.nodes, _node = node;
10
11 // We can't memoize this, since it's possible that children will be messed
12 // with externally to this class.
13 //
14 // TODO(nweiz): Do we really need to copy the list to make the types work out?
15 List<Element> get _filtered() =>
16 new List.from(_childNodes.filter((n) => n is Element));
17
18 // Don't use _filtered.first so we can short-circuit once we find an element.
19 Element get first() {
20 for (var node in _childNodes) {
21 if (node is Element) {
22 return node;
23 }
24 }
25 }
Jacob 2011/10/19 23:36:03 return null explicitly
nweiz 2011/10/19 23:42:09 Done.
26
27 void forEach(void f(Element element)) {
28 _filtered.forEach(f);
29 }
30
31 void operator []=(int index, Element value) {
32 this[index].replaceWith(value);
33 }
34
35 void set length(int newLength) {
36 if (newLength >= length) {
Jacob 2011/10/19 23:36:03 length is somewhat costly to compute so cache it a
nweiz 2011/10/19 23:42:09 Done.
37 return;
38 } else if (newLength < 0) {
39 throw const IllegalArgumentException("Invalid list length");
40 }
41
42 removeRange(newLength - 1, length - newLength);
43 }
44
45 void add(Element value) {
46 _childNodes.add(value);
47 }
48
49 void addAll(Collection<Element> collection) {
50 collection.forEach(add);
51 }
52
53 void addLast(Element value) {
54 add(value);
55 }
56
57 void sort(int compare(Element a, Element b)) {
58 throw const UnsupportedOperationException('TODO(jacobr): should we impl?');
59 }
60
61 void copyFrom(List<Object> src, int srcStart, int dstStart, int count) {
62 throw const NotImplementedException();
63 }
64
65 void setRange(int start, int length, List from, [int startFrom = 0]) {
66 throw const NotImplementedException();
67 }
68
69 void removeRange(int start, int length) {
70 _filtered.getRange(start, length).forEach((el) => el.remove());
71 }
72
73 void insertRange(int start, int length, [initialValue = null]) {
74 throw const NotImplementedException();
75 }
76
77 void clear() {
78 // Currently, ElementList#clear clears even non-element nodes, so we follow
79 // that behavior.
80 _childNodes.clear();
81 }
82
83 Element removeLast() {
84 var last = this.last();
85 if (last != null) {
86 last.remove();
87 }
88 return last;
89 }
90
91 Collection<Element> filter(bool f(Element element)) => _filtered.filter(f);
92 bool every(bool f(Element element)) => _filtered.every(f);
93 bool some(bool f(Element element)) => _filtered.some(f);
94 bool isEmpty() => _filtered.isEmpty();
95 int get length() => _filtered.length;
96 Element operator [](int index) => _filtered[index];
97 Iterator<Element> iterator() => _filtered.iterator();
98 List<Element> getRange(int start, int length) =>
99 _filtered.getRange(start, length);
100 int indexOf(Element element, int startIndex) =>
101 _filtered.indexOf(element, startIndex);
102 int lastIndexOf(Element element, int startIndex) =>
103 _filtered.lastIndexOf(element, startIndex);
104 Element last() => _filtered.last();
105 }
106
107 class EmptyStyleDeclaration implements CSSStyleDeclaration {
108 String get cssText() => "";
109 int get length() => 0;
110 CSSRule get parentRule() => null;
111 CSSValue getPropertyCSSValue(String propertyName) => null;
112 String getPropertyPriority(String propertyName) => "";
113 String getPropertyShorthand(String propertyName) => null;
114 String getPropertyValue(String propertyName) => null;
115 bool isPropertyImplicit(String propertyName) => false;
116 String item(int index) => "";
117
118 void set cssText(String value) {
119 throw new UnsupportedOperationException(
120 "Can't modify a frozen style declaration.");
121 }
122
123 String removeProperty(String propertyName) {
124 throw new UnsupportedOperationException(
125 "Can't modify a frozen style declaration.");
126 }
127
128 void setProperty(String propertyName, String value, [String priority]) {
129 throw new UnsupportedOperationException(
130 "Can't modify a frozen style declaration.");
131 }
132 }
133
134 class EmptyClientRect implements ClientRect {
135 num get bottom() => 0;
136 num get top() => 0;
137 num get left() => 0;
138 num get right() => 0;
139 num get height() => 0;
140 num get width() => 0;
141 }
142
5 class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation implements DocumentFragment { 143 class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation implements DocumentFragment {
144 ElementList _elements;
145 ElementEvents _on;
Jacob 2011/10/19 23:36:03 there's already an _on property declared by the No
nweiz 2011/10/19 23:42:09 Done.
146
6 DocumentFragmentWrappingImplementation._wrap(ptr) : super._wrap(ptr) {} 147 DocumentFragmentWrappingImplementation._wrap(ptr) : super._wrap(ptr) {}
7 148
149 factory DocumentFragmentWrappingImplementation.html(String html) {
150 var fragment = new DocumentFragment();
151 fragment.innerHTML = html;
152 return fragment;
153 }
154
8 factory DocumentFragmentWrappingImplementation() { 155 factory DocumentFragmentWrappingImplementation() {
Jacob 2011/10/19 23:36:03 nit: move this factory before the .html factory in
nweiz 2011/10/19 23:42:09 Done.
9 return new DocumentFragmentWrappingImplementation._wrap( 156 return new DocumentFragmentWrappingImplementation._wrap(
10 dom.document.createDocumentFragment()); 157 dom.document.createDocumentFragment());
11 } 158 }
12 159
13 Element query(String selectors) { 160 ElementList get elements() {
14 return LevelDom.wrapElement(_ptr.querySelector(selectors)); 161 if (_elements == null) {
15 } 162 _elements = new FilteredElementList(this);
16 163 }
17 ElementList queryAll(String selectors) { 164 return _elements;
18 return LevelDom.wrapElementList(_ptr.querySelectorAll(selectors)); 165 }
19 } 166
20 } 167 // TODO: The type of value should be Collection<Element>. See http://b/5392897
168 void set elements(value) {
169 // Copy list first since we don't want liveness during iteration.
170 List copy = new List.from(value);
171 final elements = this.elements;
172 elements.clear();
173 elements.addAll(copy);
174 }
175
176 String get innerHTML() {
177 var e = new Element.tag("div");
178 e.nodes.add(this.clone(true));
179 return e.innerHTML;
180 }
181
182 String get outerHTML() => innerHTML;
183
184 void set innerHTML(String value) {
185 this.nodes.clear();
186
187 var e = new Element.tag("div");
188 e.innerHTML = value;
189
190 // Copy list first since we don't want liveness during iteration.
191 List nodes = new List.from(e.nodes);
192 this.nodes.addAll(nodes);
193 }
194
195 Node _insertAdjacentNode(String where, Node node) {
196 switch (where.toLowerCase()) {
197 case "beforebegin": return null;
198 case "afterend": return null;
199 case "afterbegin":
200 this.insertBefore(node, nodes.first);
201 return node;
202 case "beforeend":
203 this.nodes.add(node);
204 return node;
205 default:
206 throw new IllegalArgumentException("Invalid position ${where}");
207 }
208 }
209
210 Element insertAdjacentElement([String where = null, Element element = null])
211 => this._insertAdjacentNode(where, element);
212
213 void insertAdjacentText([String where = null, String text = null]) {
214 this._insertAdjacentNode(where, new Text(text));
215 }
216
217 void insertAdjacentHTML(
218 [String position_OR_where = null, String text = null]) {
219 this._insertAdjacentNode(
220 position_OR_where, new DocumentFragment.html(text));
221 }
222
223 ElementEvents get on() {
224 if (_on === null) {
225 _on = new ElementEventsImplementation._wrap(_ptr);
226 }
227 return _on;
228 }
229
230 Element query(String selectors) =>
231 LevelDom.wrapElement(_ptr.querySelector(selectors));
232
233 ElementList queryAll(String selectors) =>
234 LevelDom.wrapElementList(_ptr.querySelectorAll(selectors));
235
236 // If we can come up with a semi-reasonable default value for an Element
237 // getter, we'll use it. In general, these return the same values as an
238 // element that has no parent.
239 int get clientHeight() => 0;
240 int get clientWidth() => 0;
241 int get offsetHeight() => 0;
242 int get offsetWidth() => 0;
243 int get scrollHeight() => 0;
244 int get scrollWidth() => 0;
245 int get clientLeft() => 0;
246 int get clientTop() => 0;
247 int get offsetLeft() => 0;
248 int get offsetTop() => 0;
249 int get scrollLeft() => 0;
250 int get scrollTop() => 0;
251 String get contentEditable() => "false";
252 bool get isContentEditable() => false;
253 bool get draggable() => false;
254 bool get hidden() => false;
255 bool get spellcheck() => false;
256 int get tabIndex() => -1;
257 String get id() => "";
258 String get title() => "";
259 String get tagName() => "";
260 String get webkitdropzone() => "";
261 Element get firstElementChild() => elements.first();
262 Element get lastElementChild() => elements.last;
263 Element get nextElementSibling() => null;
264 Element get previousElementSibling() => null;
265 Element get offsetParent() => null;
266 Element get parent() => null;
267 Map<String, String> get attributes() => const {};
268 // Issue 174: this should be a const set.
269 Set<String> get classes() => new Set<String>();
270 Map<String, String> get dataAttributes() => const {};
271 CSSStyleDeclaration get style() => new EmptyStyleDeclaration();
272 ClientRect getBoundingClientRect() => new EmptyClientRect();
273 List<ClientRect> getClientRects() => const [];
274 bool matchesSelector([String selectors]) => false;
275
276 // Imperative Element methods are made into no-ops, as they are on parentless
277 // elements.
278 void blur() {}
279 void focus() {}
280 void scrollByLines([int lines]) {}
281 void scrollByPages([int pages]) {}
282 void scrollIntoView([bool centerIfNeeded]) {}
283
284 // Setters throw errors rather than being no-ops because we aren't going to
285 // retain the values that were set, and erroring out seems clearer.
286 void set attributes(Map<String, String> value) {
287 throw new UnsupportedOperationException(
288 "Attributes can't be set for document fragments.");
289 }
290
291 void set classes(Collection<String> value) {
292 throw new UnsupportedOperationException(
293 "Classes can't be set for document fragments.");
294 }
295
296 void set dataAttributes(Map<String, String> value) {
297 throw new UnsupportedOperationException(
298 "Data attributes can't be set for document fragments.");
299 }
300
301 void set contentEditable(String value) {
302 throw new UnsupportedOperationException(
303 "Content editable can't be set for document fragments.");
304 }
305
306 String get dir() {
307 throw new UnsupportedOperationException(
308 "Document fragments don't support text direction.");
309 }
310
311 void set dir(String value) {
312 throw new UnsupportedOperationException(
313 "Document fragments don't support text direction.");
314 }
315
316 void set draggable(bool value) {
317 throw new UnsupportedOperationException(
318 "Draggable can't be set for document fragments.");
319 }
320
321 void set hidden(bool value) {
322 throw new UnsupportedOperationException(
323 "Hidden can't be set for document fragments.");
324 }
325
326 void set id(String value) {
327 throw new UnsupportedOperationException(
328 "ID can't be set for document fragments.");
329 }
330
331 String get lang() {
332 throw new UnsupportedOperationException(
333 "Document fragments don't support language.");
334 }
335
336 void set lang(String value) {
337 throw new UnsupportedOperationException(
338 "Document fragments don't support language.");
339 }
340
341 void set scrollLeft(int value) {
342 throw new UnsupportedOperationException(
343 "Document fragments don't support scrolling.");
344 }
345
346 void set scrollTop(int value) {
347 throw new UnsupportedOperationException(
348 "Document fragments don't support scrolling.");
349 }
350
351 void set spellcheck(bool value) {
352 throw new UnsupportedOperationException(
353 "Spellcheck can't be set for document fragments.");
354 }
355
356 void set tabIndex(int value) {
357 throw new UnsupportedOperationException(
358 "Tab index can't be set for document fragments.");
359 }
360
361 void set title(String value) {
362 throw new UnsupportedOperationException(
363 "Title can't be set for document fragments.");
364 }
365
366 void set webkitdropzone(String value) {
367 throw new UnsupportedOperationException(
368 "WebKit drop zone can't be set for document fragments.");
369 }
370 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698