OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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 // TODO(jacobr): use _Lists.dart to remove some of the duplicated | 5 // TODO(jacobr): use _Lists.dart to remove some of the duplicated |
6 // functionality. | 6 // functionality. |
7 class _ChildrenElementList implements ElementList { | 7 class _ChildrenElementList implements ElementList { |
8 // Raw Element. | 8 // Raw Element. |
9 final _ElementImpl _element; | 9 final _ElementImpl _element; |
10 final _HTMLCollectionImpl _childElements; | 10 final _HTMLCollectionImpl _childElements; |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 class _ElementList extends _ListWrapper<Element> implements ElementList { | 298 class _ElementList extends _ListWrapper<Element> implements ElementList { |
299 _ElementList(List<Element> list) : super(list); | 299 _ElementList(List<Element> list) : super(list); |
300 | 300 |
301 ElementList filter(bool f(Element element)) => | 301 ElementList filter(bool f(Element element)) => |
302 new _ElementList(super.filter(f)); | 302 new _ElementList(super.filter(f)); |
303 | 303 |
304 ElementList getRange(int start, int length) => | 304 ElementList getRange(int start, int length) => |
305 new _ElementList(super.getRange(start, length)); | 305 new _ElementList(super.getRange(start, length)); |
306 } | 306 } |
307 | 307 |
308 class ElementAttributeMap implements Map<String, String> { | 308 class _ElementAttributeMap implements AttributeMap { |
309 | 309 |
310 final _ElementImpl _element; | 310 final _ElementImpl _element; |
311 | 311 |
312 ElementAttributeMap._wrap(this._element); | 312 _ElementAttributeMap(this._element); |
313 | 313 |
314 bool containsValue(String value) { | 314 bool containsValue(String value) { |
315 final attributes = _element.$dom_attributes; | 315 final attributes = _element.$dom_attributes; |
316 for (int i = 0, len = attributes.length; i < len; i++) { | 316 for (int i = 0, len = attributes.length; i < len; i++) { |
317 if(value == attributes[i].value) { | 317 if(value == attributes[i].value) { |
318 return true; | 318 return true; |
319 } | 319 } |
320 } | 320 } |
321 return false; | 321 return false; |
322 } | 322 } |
323 | 323 |
324 bool containsKey(String key) { | 324 bool containsKey(String key) { |
325 return _element.$dom_hasAttribute(key); | 325 return _element.$dom_hasAttribute(key); |
326 } | 326 } |
327 | 327 |
328 String operator [](String key) { | 328 String operator [](String key) { |
329 return _element.$dom_getAttribute(key); | 329 return _element.$dom_getAttribute(key); |
330 } | 330 } |
331 | 331 |
332 void operator []=(String key, String value) { | 332 void operator []=(String key, value) { |
333 _element.$dom_setAttribute(key, value); | 333 _element.$dom_setAttribute(key, '$value'); |
334 } | 334 } |
335 | 335 |
336 String putIfAbsent(String key, String ifAbsent()) { | 336 String putIfAbsent(String key, String ifAbsent()) { |
337 if (!containsKey(key)) { | 337 if (!containsKey(key)) { |
338 this[key] = ifAbsent(); | 338 this[key] = ifAbsent(); |
339 } | 339 } |
340 } | 340 } |
341 | 341 |
342 String remove(String key) { | 342 String remove(String key) { |
343 _element.$dom_removeAttribute(key); | 343 _element.$dom_removeAttribute(key); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 } | 386 } |
387 | 387 |
388 /** | 388 /** |
389 * Returns true if there is no {key, value} pair in the map. | 389 * Returns true if there is no {key, value} pair in the map. |
390 */ | 390 */ |
391 bool isEmpty() { | 391 bool isEmpty() { |
392 return length == 0; | 392 return length == 0; |
393 } | 393 } |
394 } | 394 } |
395 | 395 |
396 /** | |
397 * Provides a Map abstraction on top of data-* attributes, similar to the | |
398 * dataSet in the old DOM. | |
399 */ | |
400 class _DataAttributeMap implements AttributeMap { | |
401 | |
402 final Map<String, String> $dom_attributes; | |
403 | |
404 _DataAttributeMap(this.$dom_attributes); | |
405 | |
406 // interface Map | |
407 | |
408 // TODO: Use lazy iterator when it is available on Map. | |
409 bool containsValue(String value) => getValues().some((v) => v == value); | |
410 | |
411 bool containsKey(String key) => $dom_attributes.containsKey(_attr(key)); | |
412 | |
413 String operator [](String key) => $dom_attributes[_attr(key)]; | |
414 | |
415 void operator []=(String key, value) { | |
416 $dom_attributes[_attr(key)] = '$value'; | |
417 } | |
418 | |
419 String putIfAbsent(String key, String ifAbsent()) { | |
420 if (!containsKey(key)) { | |
nweiz
2012/03/30 00:06:23
Can't this just call $dom_attributes.putIfAbsent?
Jacob
2012/03/30 00:40:53
Yep. Done. FYI this code isn't new I just moved it
| |
421 return this[key] = ifAbsent(); | |
422 } | |
423 return this[key]; | |
424 } | |
425 | |
426 String remove(String key) => $dom_attributes.remove(_attr(key)); | |
427 | |
428 void clear() { | |
429 // Needs to operate on a snapshot since we are mutatiting the collection. | |
nweiz
2012/03/30 00:06:23
mutating
Jacob
2012/03/30 00:40:53
Done.
| |
430 for (String key in getKeys()) { | |
431 remove(key); | |
432 } | |
433 } | |
434 | |
435 void forEach(void f(String key, String value)) { | |
436 $dom_attributes.forEach((String key, String value) { | |
437 if (_matches(key)) { | |
438 f(_strip(key), value); | |
439 } | |
440 }); | |
441 } | |
442 | |
443 Collection<String> getKeys() { | |
444 final keys = new List<String>(); | |
445 $dom_attributes.forEach((String key, String value) { | |
nweiz
2012/03/30 00:06:23
This would be a little cleaner if you used this cl
Jacob
2012/03/30 00:40:53
Reasonable idea but I'd rather leave it unchanged.
| |
446 if (_matches(key)) { | |
447 keys.add(_strip(key)); | |
448 } | |
449 }); | |
450 return keys; | |
451 } | |
452 | |
453 Collection<String> getValues() { | |
454 final values = new List<String>(); | |
455 $dom_attributes.forEach((String key, String value) { | |
nweiz
2012/03/30 00:06:23
As above, a little cleaner to use this class's for
Jacob
2012/03/30 00:40:53
feel free to send an alternate CL.
| |
456 if (_matches(key)) { | |
457 values.add(value); | |
458 } | |
459 }); | |
460 return values; | |
461 } | |
462 | |
463 int get length() => getKeys().length; | |
464 | |
465 // TODO: Use lazy iterator when it is available on Map. | |
466 bool isEmpty() => length == 0; | |
467 | |
468 // Helpers. | |
469 String _attr(String key) => 'data-$key'; | |
470 bool _matches(String key) => key.startsWith('data-'); | |
471 String _strip(String key) => key.substring(5); | |
472 } | |
473 | |
474 class _CssClassSet implements Set<String> { | |
475 | |
476 final _ElementImpl _element; | |
477 | |
478 _CssClassSet(this._element); | |
479 | |
480 String toString() { | |
481 return _formatSet(_read()); | |
nweiz
2012/03/30 00:06:23
=>, here and below.
Jacob
2012/03/30 00:40:53
Done.
| |
482 } | |
483 | |
484 // interface Iterable - BEGIN | |
485 Iterator<String> iterator() { | |
486 return _read().iterator(); | |
487 } | |
488 // interface Iterable - END | |
489 | |
490 // interface Collection - BEGIN | |
491 void forEach(void f(String element)) { | |
492 _read().forEach(f); | |
493 } | |
494 | |
495 Collection map(f(String element)) { | |
496 return _read().map(f); | |
497 } | |
498 | |
499 Collection<String> filter(bool f(String element)) { | |
500 return _read().filter(f); | |
501 } | |
502 | |
503 bool every(bool f(String element)) { | |
504 return _read().every(f); | |
505 } | |
506 | |
507 bool some(bool f(String element)) { | |
508 return _read().some(f); | |
509 } | |
510 | |
511 bool isEmpty() { | |
512 return _read().isEmpty(); | |
513 } | |
514 | |
515 int get length() { | |
516 return _read().length; | |
517 } | |
518 // interface Collection - END | |
519 | |
520 // interface Set - BEGIN | |
521 bool contains(String value) { | |
522 return _read().contains(value); | |
523 } | |
524 | |
525 void add(String value) { | |
526 // TODO - figure out if we need to do any validation here | |
527 // or if the browser natively does enough | |
528 _modify((s) => s.add(value)); | |
529 } | |
530 | |
531 bool remove(String value) { | |
532 Set<String> s = _read(); | |
533 bool result = s.remove(value); | |
nweiz
2012/03/30 00:06:23
Couldn't you use _modify here if you changed it to
Jacob
2012/03/30 00:40:53
i don't follow. if you want to send a cleanup cl f
| |
534 _write(s); | |
535 return result; | |
536 } | |
537 | |
538 void addAll(Collection<String> collection) { | |
539 // TODO - see comment above about validation | |
540 _modify((s) => s.addAll(collection)); | |
541 } | |
542 | |
543 void removeAll(Collection<String> collection) { | |
544 _modify((s) => s.removeAll(collection)); | |
545 } | |
546 | |
547 bool isSubsetOf(Collection<String> collection) { | |
548 return _read().isSubsetOf(collection); | |
549 } | |
550 | |
551 bool containsAll(Collection<String> collection) { | |
552 return _read().containsAll(collection); | |
553 } | |
554 | |
555 Set<String> intersection(Collection<String> other) { | |
556 return _read().intersection(other); | |
557 } | |
558 | |
559 void clear() { | |
560 _modify((s) => s.clear()); | |
561 } | |
562 // interface Set - END | |
563 | |
564 /** | |
565 * Helper method used to modify the set of css classes on this element. | |
566 * | |
567 * f - callback with: | |
568 * s - a Set of all the css class name currently on this element. | |
569 * | |
570 * After f returns, the modified set is written to the | |
571 * className property of this element. | |
572 */ | |
573 void _modify( f(Set<String> s)) { | |
574 Set<String> s = _read(); | |
575 f(s); | |
576 _write(s); | |
577 } | |
578 | |
579 /** | |
580 * Read the class names from the Element class property, | |
581 * and put them into a set (duplicates are discarded). | |
582 */ | |
583 Set<String> _read() { | |
584 // TODO(mattsh) simplify this once split can take regex. | |
585 Set<String> s = new Set<String>(); | |
586 for (String name in $dom_className().split(' ')) { | |
587 String trimmed = name.trim(); | |
588 if (!trimmed.isEmpty()) { | |
589 s.add(trimmed); | |
590 } | |
591 } | |
592 return s; | |
593 } | |
594 | |
595 /** | |
596 * Read the class names as a space-separated string. This is meant to be | |
597 * overridden by subclasses. | |
598 */ | |
599 String $dom_className() => _element.$dom_className; | |
nweiz
2012/03/30 00:06:23
Why does this need to be implemented here?
Jacob
2012/03/30 00:40:53
Good catch... my regexp adding $dom to the names o
| |
600 | |
601 /** | |
602 * Join all the elements of a set into one string and write | |
603 * back to the element. | |
604 */ | |
605 void _write(Set s) { | |
606 _element.$dom_className = _formatSet(s); | |
607 } | |
608 | |
609 String _formatSet(Set<String> s) { | |
610 // TODO(mattsh) should be able to pass Set to String.joins http:/b/5398605 | |
611 List list = new List.from(s); | |
612 return Strings.join(list, ' '); | |
613 } | |
614 } | |
615 | |
396 class _SimpleClientRect implements ClientRect { | 616 class _SimpleClientRect implements ClientRect { |
397 final num left; | 617 final num left; |
398 final num top; | 618 final num top; |
399 final num width; | 619 final num width; |
400 final num height; | 620 final num height; |
401 num get right() => left + width; | 621 num get right() => left + width; |
402 num get bottom() => top + height; | 622 num get bottom() => top + height; |
403 | 623 |
404 const _SimpleClientRect(this.left, this.top, this.width, this.height); | 624 const _SimpleClientRect(this.left, this.top, this.width, this.height); |
405 | 625 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 final out = new List(_clientRects.length); | 671 final out = new List(_clientRects.length); |
452 for (num i = 0; i < _clientRects.length; i++) { | 672 for (num i = 0; i < _clientRects.length; i++) { |
453 out[i] = _clientRects.item(i); | 673 out[i] = _clientRects.item(i); |
454 } | 674 } |
455 return out; | 675 return out; |
456 } | 676 } |
457 } | 677 } |
458 | 678 |
459 class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { | 679 class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { |
460 | 680 |
461 // TODO(jacobr): caching these may hurt performance. | |
462 ElementAttributeMap _elementAttributeMap; | |
463 _CssClassSet _cssClassSet; | |
464 _DataAttributeMap _dataAttributes; | |
465 | |
466 /** | 681 /** |
467 * @domName Element.hasAttribute, Element.getAttribute, Element.setAttribute, | 682 * @domName Element.hasAttribute, Element.getAttribute, Element.setAttribute, |
468 * Element.removeAttribute | 683 * Element.removeAttribute |
469 */ | 684 */ |
470 Map<String, String> get attributes() { | 685 _ElementAttributeMap get attributes() => new _ElementAttributeMap(this); |
471 if (_elementAttributeMap === null) { | |
472 _elementAttributeMap = new ElementAttributeMap._wrap(this); | |
473 } | |
474 return _elementAttributeMap; | |
475 } | |
476 | 686 |
477 void set attributes(Map<String, String> value) { | 687 void set attributes(Map<String, String> value) { |
478 Map<String, String> attributes = this.attributes; | 688 Map<String, String> attributes = this.attributes; |
479 attributes.clear(); | 689 attributes.clear(); |
480 for (String key in value.getKeys()) { | 690 for (String key in value.getKeys()) { |
481 attributes[key] = value[key]; | 691 attributes[key] = value[key]; |
482 } | 692 } |
483 } | 693 } |
484 | 694 |
485 void set elements(Collection<Element> value) { | 695 void set elements(Collection<Element> value) { |
486 final elements = this.elements; | 696 final elements = this.elements; |
487 elements.clear(); | 697 elements.clear(); |
488 elements.addAll(value); | 698 elements.addAll(value); |
489 } | 699 } |
490 | 700 |
491 ElementList get elements() => new _ChildrenElementList._wrap(this); | 701 ElementList get elements() => new _ChildrenElementList._wrap(this); |
492 | 702 |
493 ElementList queryAll(String selectors) => | 703 ElementList queryAll(String selectors) => |
494 new _FrozenElementList._wrap($dom_querySelectorAll(selectors)); | 704 new _FrozenElementList._wrap($dom_querySelectorAll(selectors)); |
495 | 705 |
496 Set<String> get classes() { | 706 _CssClassSet get classes() => new _CssClassSet(this); |
497 if (_cssClassSet === null) { | |
498 _cssClassSet = new _CssClassSet(this); | |
499 } | |
500 return _cssClassSet; | |
501 } | |
502 | 707 |
503 void set classes(Collection<String> value) { | 708 void set classes(Collection<String> value) { |
504 _CssClassSet classSet = classes; | 709 _CssClassSet classSet = classes; |
505 classSet.clear(); | 710 classSet.clear(); |
506 classSet.addAll(value); | 711 classSet.addAll(value); |
507 } | 712 } |
508 | 713 |
509 Map<String, String> get dataAttributes() { | 714 Map<String, String> get dataAttributes() { |
510 if (_dataAttributes === null) { | 715 return new _DataAttributeMap(attributes); |
nweiz
2012/03/30 00:06:23
=>
Jacob
2012/03/30 00:40:53
Done.
| |
511 _dataAttributes = new _DataAttributeMap(attributes); | |
512 } | |
513 return _dataAttributes; | |
514 } | 716 } |
515 | 717 |
516 void set dataAttributes(Map<String, String> value) { | 718 void set dataAttributes(Map<String, String> value) { |
517 Map<String, String> dataAttributes = this.dataAttributes; | 719 final dataAttributes = this.dataAttributes; |
518 dataAttributes.clear(); | 720 dataAttributes.clear(); |
519 for (String key in value.getKeys()) { | 721 for (String key in value.getKeys()) { |
520 dataAttributes[key] = value[key]; | 722 dataAttributes[key] = value[key]; |
521 } | 723 } |
522 } | 724 } |
523 | 725 |
524 Future<ElementRect> get rect() { | 726 Future<ElementRect> get rect() { |
525 return _createMeasurementFuture( | 727 return _createMeasurementFuture( |
526 () => new _ElementRectImpl(this), | 728 () => new _ElementRectImpl(this), |
527 new Completer<ElementRect>()); | 729 new Completer<ElementRect>()); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
594 | 796 |
595 /** @domName Document.createElement */ | 797 /** @domName Document.createElement */ |
596 $if FROG | 798 $if FROG |
597 // Optimization to improve performance until the frog compiler inlines this | 799 // Optimization to improve performance until the frog compiler inlines this |
598 // method. | 800 // method. |
599 factory Element.tag(String tag) native "return document.createElement(tag)"; | 801 factory Element.tag(String tag) native "return document.createElement(tag)"; |
600 $else | 802 $else |
601 factory Element.tag(String tag) => _document.$dom_createElement(tag); | 803 factory Element.tag(String tag) => _document.$dom_createElement(tag); |
602 $endif | 804 $endif |
603 } | 805 } |
OLD | NEW |