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 part of $LIBRARYNAME; | 5 part of $LIBRARYNAME; |
6 | 6 |
7 class _ChildrenElementList extends ListBase<Element> | 7 class _ChildrenElementList extends ListBase<Element> |
8 implements NodeListWrapper { | 8 implements NodeListWrapper { |
9 // Raw Element. | 9 // Raw Element. |
10 final Element _element; | 10 final Element _element; |
(...skipping 15 matching lines...) Expand all Loading... |
26 } | 26 } |
27 | 27 |
28 Element operator [](int index) { | 28 Element operator [](int index) { |
29 return _childElements[index]; | 29 return _childElements[index]; |
30 } | 30 } |
31 | 31 |
32 void operator []=(int index, Element value) { | 32 void operator []=(int index, Element value) { |
33 _element._replaceChild(value, _childElements[index]); | 33 _element._replaceChild(value, _childElements[index]); |
34 } | 34 } |
35 | 35 |
36 set length(int newLength) { | 36 void set length(int newLength) { |
37 // TODO(jacobr): remove children when length is reduced. | 37 // TODO(jacobr): remove children when length is reduced. |
38 throw new UnsupportedError('Cannot resize element lists'); | 38 throw new UnsupportedError('Cannot resize element lists'); |
39 } | 39 } |
40 | 40 |
41 Element add(Element value) { | 41 Element add(Element value) { |
42 _element.append(value); | 42 _element.append(value); |
43 return value; | 43 return value; |
44 } | 44 } |
45 | 45 |
46 Iterator<Element> get iterator => toList().iterator; | 46 Iterator<Element> get iterator => toList().iterator; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 throw new UnimplementedError(); | 90 throw new UnimplementedError(); |
91 } | 91 } |
92 | 92 |
93 void fillRange(int start, int end, [Element fillValue]) { | 93 void fillRange(int start, int end, [Element fillValue]) { |
94 throw new UnimplementedError(); | 94 throw new UnimplementedError(); |
95 } | 95 } |
96 | 96 |
97 bool remove(Object object) { | 97 bool remove(Object object) { |
98 if (object is Element) { | 98 if (object is Element) { |
99 Element element = object; | 99 Element element = object; |
100 $if JSINTEROP | |
101 // We aren't preserving identity of nodes in JSINTEROP mode | |
102 if (element.parentNode == _element) { | |
103 $else | |
104 if (identical(element.parentNode, _element)) { | 100 if (identical(element.parentNode, _element)) { |
105 $endif | |
106 _element._removeChild(element); | 101 _element._removeChild(element); |
107 return true; | 102 return true; |
108 } | 103 } |
109 } | 104 } |
110 return false; | 105 return false; |
111 } | 106 } |
112 | 107 |
113 void insert(int index, Element element) { | 108 void insert(int index, Element element) { |
114 if (index < 0 || index > length) { | 109 if (index < 0 || index > length) { |
115 throw new RangeError.range(index, 0, length); | 110 throw new RangeError.range(index, 0, length); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 $endif | 274 $endif |
280 | 275 |
281 int get length => _nodeList.length; | 276 int get length => _nodeList.length; |
282 | 277 |
283 Element operator [](int index) => _nodeList[index]; | 278 Element operator [](int index) => _nodeList[index]; |
284 | 279 |
285 void operator []=(int index, Element value) { | 280 void operator []=(int index, Element value) { |
286 throw new UnsupportedError('Cannot modify list'); | 281 throw new UnsupportedError('Cannot modify list'); |
287 } | 282 } |
288 | 283 |
289 set length(int newLength) { | 284 void set length(int newLength) { |
290 throw new UnsupportedError('Cannot modify list'); | 285 throw new UnsupportedError('Cannot modify list'); |
291 } | 286 } |
292 | 287 |
293 void sort([Comparator<Element> compare]) { | 288 void sort([Comparator<Element> compare]) { |
294 throw new UnsupportedError('Cannot sort list'); | 289 throw new UnsupportedError('Cannot sort list'); |
295 } | 290 } |
296 | 291 |
297 void shuffle([Random random]) { | 292 void shuffle([Random random]) { |
298 throw new UnsupportedError('Cannot shuffle list'); | 293 throw new UnsupportedError('Cannot shuffle list'); |
299 } | 294 } |
300 | 295 |
301 Element get first => _nodeList.first; | 296 Element get first => _nodeList.first; |
302 | 297 |
303 Element get last => _nodeList.last; | 298 Element get last => _nodeList.last; |
304 | 299 |
305 Element get single => _nodeList.single; | 300 Element get single => _nodeList.single; |
306 | 301 |
307 CssClassSet get classes => new _MultiElementCssClassSet(this); | 302 CssClassSet get classes => new _MultiElementCssClassSet(this); |
308 | 303 |
309 CssStyleDeclarationBase get style => | 304 CssStyleDeclarationBase get style => |
310 new _CssStyleDeclarationSet(this); | 305 new _CssStyleDeclarationSet(this); |
311 | 306 |
312 set classes(Iterable<String> value) { | 307 void set classes(Iterable<String> value) { |
313 // TODO(sra): This might be faster for Sets: | 308 // TODO(sra): This might be faster for Sets: |
314 // | 309 // |
315 // new _MultiElementCssClassSet(this).writeClasses(value) | 310 // new _MultiElementCssClassSet(this).writeClasses(value) |
316 // | 311 // |
317 // as the code below converts the Iterable[value] to a string multiple | 312 // as the code below converts the Iterable[value] to a string multiple |
318 // times. Maybe compute the string and set className here. | 313 // times. Maybe compute the string and set className here. |
319 _nodeList.forEach((e) => e.classes = value); | 314 _nodeList.forEach((e) => e.classes = value); |
320 } | 315 } |
321 | 316 |
322 CssRect get contentEdge => new _ContentCssListRect(this); | 317 CssRect get contentEdge => new _ContentCssListRect(this); |
323 | 318 |
324 CssRect get paddingEdge => this.first.paddingEdge; | 319 CssRect get paddingEdge => this.first.paddingEdge; |
325 | 320 |
326 CssRect get borderEdge => this.first.borderEdge; | 321 CssRect get borderEdge => this.first.borderEdge; |
327 | 322 |
328 CssRect get marginEdge => this.first.marginEdge; | 323 CssRect get marginEdge => this.first.marginEdge; |
329 | 324 |
330 List<Node> get rawList => _nodeList; | 325 List<Node> get rawList => _nodeList; |
331 | 326 |
332 $!ELEMENT_STREAM_GETTERS | 327 $!ELEMENT_STREAM_GETTERS |
333 } | 328 } |
334 | 329 |
335 @DocsEditable() | 330 @DocsEditable() |
336 $(ANNOTATIONS)$(NATIVESPEC)class $CLASSNAME$EXTENDS$IMPLEMENTS { | 331 $(ANNOTATIONS)$(NATIVESPEC)abstract class $CLASSNAME$EXTENDS$IMPLEMENTS { |
337 | 332 |
338 /** | 333 /** |
339 * Creates an HTML element from a valid fragment of HTML. | 334 * Creates an HTML element from a valid fragment of HTML. |
340 * | 335 * |
341 * var element = new Element.html('<div class="foo">content</div>'); | 336 * var element = new Element.html('<div class="foo">content</div>'); |
342 * | 337 * |
343 * The HTML fragment should contain only one single root element, any | 338 * The HTML fragment should contain only one single root element, any |
344 * leading or trailing text nodes will be removed. | 339 * leading or trailing text nodes will be removed. |
345 * | 340 * |
346 * The HTML fragment is parsed as if it occurred within the context of a | 341 * The HTML fragment is parsed as if it occurred within the context of a |
(...skipping 26 matching lines...) Expand all Loading... |
373 * | 368 * |
374 * class CustomElement extends Element { | 369 * class CustomElement extends Element { |
375 * factory CustomElement() => new Element.tag('x-custom'); | 370 * factory CustomElement() => new Element.tag('x-custom'); |
376 * | 371 * |
377 * CustomElement.created() : super.created() { | 372 * CustomElement.created() : super.created() { |
378 * // Perform any element initialization. | 373 * // Perform any element initialization. |
379 * } | 374 * } |
380 * } | 375 * } |
381 * document.registerElement('x-custom', CustomElement); | 376 * document.registerElement('x-custom', CustomElement); |
382 */ | 377 */ |
383 Element.created() : super._created(); | 378 Element.created() : super._created() { |
| 379 // Validate that this is a custom element & perform any additional |
| 380 // initialization. |
| 381 _initializeCustomElement(this); |
| 382 } |
384 | 383 |
385 /** | 384 /** |
386 * Creates the HTML element specified by the tag name. | 385 * Creates the HTML element specified by the tag name. |
387 * | 386 * |
388 * This is similar to [Document.createElement]. | 387 * This is similar to [Document.createElement]. |
389 * [tag] should be a valid HTML tag name. If [tag] is an unknown tag then | 388 * [tag] should be a valid HTML tag name. If [tag] is an unknown tag then |
390 * this will create an [UnknownElement]. | 389 * this will create an [UnknownElement]. |
391 * | 390 * |
392 * var divElement = new Element.tag('div'); | 391 * var divElement = new Element.tag('div'); |
393 * print(divElement is DivElement); // 'true' | 392 * print(divElement is DivElement); // 'true' |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 * | 553 * |
555 * Any modifications to the attribute map will automatically be applied to | 554 * Any modifications to the attribute map will automatically be applied to |
556 * this element. | 555 * this element. |
557 * | 556 * |
558 * This only includes attributes which are not in a namespace | 557 * This only includes attributes which are not in a namespace |
559 * (such as 'xlink:href'), additional attributes can be accessed via | 558 * (such as 'xlink:href'), additional attributes can be accessed via |
560 * [getNamespacedAttributes]. | 559 * [getNamespacedAttributes]. |
561 */ | 560 */ |
562 Map<String, String> get attributes => new _ElementAttributeMap(this); | 561 Map<String, String> get attributes => new _ElementAttributeMap(this); |
563 | 562 |
564 set attributes(Map<String, String> value) { | 563 void set attributes(Map<String, String> value) { |
565 Map<String, String> attributes = this.attributes; | 564 Map<String, String> attributes = this.attributes; |
566 attributes.clear(); | 565 attributes.clear(); |
567 for (String key in value.keys) { | 566 for (String key in value.keys) { |
568 attributes[key] = value[key]; | 567 attributes[key] = value[key]; |
569 } | 568 } |
570 } | 569 } |
571 | 570 |
572 /** | 571 /** |
573 * List of the direct children of this element. | 572 * List of the direct children of this element. |
574 * | 573 * |
575 * This collection can be used to add and remove elements from the document. | 574 * This collection can be used to add and remove elements from the document. |
576 * | 575 * |
577 * var item = new DivElement(); | 576 * var item = new DivElement(); |
578 * item.text = 'Something'; | 577 * item.text = 'Something'; |
579 * document.body.children.add(item) // Item is now displayed on the page. | 578 * document.body.children.add(item) // Item is now displayed on the page. |
580 * for (var element in document.body.children) { | 579 * for (var element in document.body.children) { |
581 * element.style.background = 'red'; // Turns every child of body red. | 580 * element.style.background = 'red'; // Turns every child of body red. |
582 * } | 581 * } |
583 */ | 582 */ |
| 583 $if DART2JS |
584 List<Element> get children => new _ChildrenElementList._wrap(this); | 584 List<Element> get children => new _ChildrenElementList._wrap(this); |
| 585 $else |
| 586 $if JSINTEROP |
| 587 List<Element> get children => new FilteredElementList(this); |
| 588 $else |
| 589 List<Element> get children => new _ChildrenElementList._wrap(this); |
| 590 $endif |
| 591 $endif |
585 | 592 |
586 set children(List<Element> value) { | 593 void set children(List<Element> value) { |
587 // Copy list first since we don't want liveness during iteration. | 594 // Copy list first since we don't want liveness during iteration. |
588 List copy = new List.from(value); | 595 List copy = new List.from(value); |
589 var children = this.children; | 596 var children = this.children; |
590 children.clear(); | 597 children.clear(); |
591 children.addAll(copy); | 598 children.addAll(copy); |
592 } | 599 } |
593 | 600 |
594 /** | 601 /** |
595 * Finds all descendent elements of this element that match the specified | 602 * Finds all descendent elements of this element that match the specified |
596 * group of selectors. | 603 * group of selectors. |
597 * | 604 * |
598 * [selectors] should be a string using CSS selector syntax. | 605 * [selectors] should be a string using CSS selector syntax. |
599 * | 606 * |
600 * var items = element.querySelectorAll('.itemClassName'); | 607 * var items = element.querySelectorAll('.itemClassName'); |
601 * | 608 * |
602 * For details about CSS selector syntax, see the | 609 * For details about CSS selector syntax, see the |
603 * [CSS selector specification](http://www.w3.org/TR/css3-selectors/). | 610 * [CSS selector specification](http://www.w3.org/TR/css3-selectors/). |
604 */ | 611 */ |
605 @DomName('Element.querySelectorAll') | 612 @DomName('Element.querySelectorAll') |
606 ElementList<Element> querySelectorAll(String selectors) => | 613 ElementList<Element> querySelectorAll(String selectors) => |
| 614 $if JSINTEROP |
| 615 _querySelectorAll(selectors); |
| 616 $else |
607 new _FrozenElementList._wrap(_querySelectorAll(selectors)); | 617 new _FrozenElementList._wrap(_querySelectorAll(selectors)); |
| 618 $endif |
608 | 619 |
609 /** | 620 /** |
610 * Alias for [querySelector]. Note this function is deprecated because its | 621 * Alias for [querySelector]. Note this function is deprecated because its |
611 * semantics will be changing in the future. | 622 * semantics will be changing in the future. |
612 */ | 623 */ |
613 @deprecated | 624 @deprecated |
614 @DomName('Element.querySelector') | 625 @DomName('Element.querySelector') |
615 @Experimental() | 626 @Experimental() |
616 Element query(String relativeSelectors) => querySelector(relativeSelectors); | 627 Element query(String relativeSelectors) => querySelector(relativeSelectors); |
617 | 628 |
(...skipping 12 matching lines...) Expand all Loading... |
630 * | 641 * |
631 * This set makes it easy to add, remove or toggle the classes applied to | 642 * This set makes it easy to add, remove or toggle the classes applied to |
632 * this element. | 643 * this element. |
633 * | 644 * |
634 * element.classes.add('selected'); | 645 * element.classes.add('selected'); |
635 * element.classes.toggle('isOnline'); | 646 * element.classes.toggle('isOnline'); |
636 * element.classes.remove('selected'); | 647 * element.classes.remove('selected'); |
637 */ | 648 */ |
638 CssClassSet get classes => new _ElementCssClassSet(this); | 649 CssClassSet get classes => new _ElementCssClassSet(this); |
639 | 650 |
640 set classes(Iterable<String> value) { | 651 void set classes(Iterable<String> value) { |
641 // TODO(sra): Do this without reading the classes in clear() and addAll(), | 652 // TODO(sra): Do this without reading the classes in clear() and addAll(), |
642 // or writing the classes in clear(). | 653 // or writing the classes in clear(). |
643 CssClassSet classSet = classes; | 654 CssClassSet classSet = classes; |
644 classSet.clear(); | 655 classSet.clear(); |
645 classSet.addAll(value); | 656 classSet.addAll(value); |
646 } | 657 } |
647 | 658 |
648 /** | 659 /** |
649 * Allows access to all custom data attributes (data-*) set on this element. | 660 * Allows access to all custom data attributes (data-*) set on this element. |
650 * | 661 * |
(...skipping 13 matching lines...) Expand all Loading... |
664 * | 675 * |
665 * var value = element.dataset['myRandomValue']; | 676 * var value = element.dataset['myRandomValue']; |
666 * | 677 * |
667 * See also: | 678 * See also: |
668 * | 679 * |
669 * * [Custom data attributes](http://www.w3.org/TR/html5/global-attributes.htm
l#custom-data-attribute) | 680 * * [Custom data attributes](http://www.w3.org/TR/html5/global-attributes.htm
l#custom-data-attribute) |
670 */ | 681 */ |
671 Map<String, String> get dataset => | 682 Map<String, String> get dataset => |
672 new _DataAttributeMap(attributes); | 683 new _DataAttributeMap(attributes); |
673 | 684 |
674 set dataset(Map<String, String> value) { | 685 void set dataset(Map<String, String> value) { |
675 final data = this.dataset; | 686 final data = this.dataset; |
676 data.clear(); | 687 data.clear(); |
677 for (String key in value.keys) { | 688 for (String key in value.keys) { |
678 data[key] = value[key]; | 689 data[key] = value[key]; |
679 } | 690 } |
680 } | 691 } |
681 | 692 |
682 /** | 693 /** |
683 * Gets a map for manipulating the attributes of a particular namespace. | 694 * Gets a map for manipulating the attributes of a particular namespace. |
684 * | 695 * |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 /** *Deprecated*: override [attached] instead. */ | 794 /** *Deprecated*: override [attached] instead. */ |
784 @Experimental() | 795 @Experimental() |
785 @deprecated | 796 @deprecated |
786 void enteredView() {} | 797 void enteredView() {} |
787 | 798 |
788 /** *Deprecated*: override [detached] instead. */ | 799 /** *Deprecated*: override [detached] instead. */ |
789 @Experimental() | 800 @Experimental() |
790 @deprecated | 801 @deprecated |
791 void leftView() {} | 802 void leftView() {} |
792 | 803 |
| 804 $if DART2JS |
793 /** | 805 /** |
794 * Creates a new AnimationEffect object whose target element is the object | 806 * Creates a new AnimationEffect object whose target element is the object |
795 * on which the method is called, and calls the play() method of the | 807 * on which the method is called, and calls the play() method of the |
796 * AnimationTimeline object of the document timeline of the node document | 808 * AnimationTimeline object of the document timeline of the node document |
797 * of the element, passing the newly created AnimationEffect as the argument | 809 * of the element, passing the newly created AnimationEffect as the argument |
798 * to the method. Returns an AnimationPlayer for the effect. | 810 * to the method. Returns an AnimationPlayer for the effect. |
799 * | 811 * |
800 * Examples | 812 * Examples |
801 * | 813 * |
802 * var animation = elem.animate([{"opacity": 75}, {"opacity": 0}], 200); | 814 * var animation = elem.animate([{"opacity": 75}, {"opacity": 0}], 200); |
803 * | 815 * |
804 * var animation = elem.animate([ | 816 * var animation = elem.animate([ |
805 * {"transform": "translate(100px, -100%)"}, | 817 * {"transform": "translate(100px, -100%)"}, |
806 * {"transform" : "translate(400px, 500px)"} | 818 * {"transform" : "translate(400px, 500px)"} |
807 * ], 1500); | 819 * ], 1500); |
808 * | 820 * |
809 * The [frames] parameter is an Iterable<Map>, where the | 821 * The [frames] parameter is an Iterable<Map>, where the |
810 * map entries specify CSS animation effects. The | 822 * map entries specify CSS animation effects. The |
811 * [timing] paramter can be a double, representing the number of milliseconds | 823 * [timing] paramter can be a double, representing the number of milliseconds |
812 * for the transition, or a Map with fields corresponding to those | 824 * for the transition, or a Map with fields corresponding to those |
813 * of the [Timing] object. | 825 * of the [Timing] object. |
| 826 * |
| 827 * This is not yet supported in Dartium. |
814 **/ | 828 **/ |
815 @Experimental() | 829 // TODO(alanknight): Correct above comment once it works in Dartium. |
| 830 @Experimental |
816 @SupportedBrowser(SupportedBrowser.CHROME, '36') | 831 @SupportedBrowser(SupportedBrowser.CHROME, '36') |
817 AnimationPlayer animate(Iterable<Map<String, dynamic>> frames, [timing]) { | 832 AnimationPlayer animate(Iterable<Map<String, dynamic>> frames, [timing]) { |
818 if (frames is! Iterable || !(frames.every((x) => x is Map))) { | 833 if (frames is! Iterable || !(frames.every((x) => x is Map))) { |
819 throw new ArgumentError("The frames parameter should be a List of Maps " | 834 throw new ArgumentError("The frames parameter should be a List of Maps " |
820 "with frame information"); | 835 "with frame information"); |
821 } | 836 } |
822 var convertedFrames = frames; | 837 var convertedFrames = frames; |
823 if (convertedFrames is Iterable) { | 838 if (convertedFrames is Iterable) { |
824 convertedFrames = convertDartToNative_List( | 839 convertedFrames = frames.map(convertDartToNative_Dictionary).toList(); |
825 frames.map(convertDartToNative_Dictionary).toList()); | |
826 } | 840 } |
827 var convertedTiming = timing; | 841 var convertedTiming = timing; |
828 if (convertedTiming is Map) { | 842 if (convertedTiming is Map) { |
829 convertedTiming = convertDartToNative_Dictionary(convertedTiming); | 843 convertedTiming = convertDartToNative_Dictionary(convertedTiming); |
830 } | 844 } |
831 return convertedTiming == null | 845 return convertedTiming == null |
832 ? _animate(convertedFrames) | 846 ? _animate(convertedFrames) |
833 : _animate(convertedFrames, convertedTiming); | 847 : _animate(convertedFrames, convertedTiming); |
834 } | 848 } |
835 | 849 |
836 $if DART2JS | |
837 @DomName('Element.animate') | 850 @DomName('Element.animate') |
838 @JSName('animate') | 851 @JSName('animate') |
839 @Experimental() // untriaged | 852 @Experimental() // untriaged |
840 AnimationPlayer _animate(Object effect, [timing]) native; | 853 AnimationPlayer _animate(Object effect, [timing]) native; |
841 $endif | 854 $endif |
842 /** | 855 /** |
843 * Called by the DOM whenever an attribute on this has been changed. | 856 * Called by the DOM whenever an attribute on this has been changed. |
844 */ | 857 */ |
845 void attributeChanged(String name, String oldValue, String newValue) {} | 858 void attributeChanged(String name, String oldValue, String newValue) {} |
846 | 859 |
(...skipping 13 matching lines...) Expand all Loading... |
860 * | 873 * |
861 * If xtag has not been set, it will simply return `this` [Element]. | 874 * If xtag has not been set, it will simply return `this` [Element]. |
862 * | 875 * |
863 * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html | 876 * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html |
864 * [x-tags]: http://x-tags.org/ | 877 * [x-tags]: http://x-tags.org/ |
865 */ | 878 */ |
866 // Note: return type is `dynamic` for convenience to suppress warnings when | 879 // Note: return type is `dynamic` for convenience to suppress warnings when |
867 // members of the component are used. The actual type is a subtype of Element. | 880 // members of the component are used. The actual type is a subtype of Element. |
868 get xtag => _xtag != null ? _xtag : this; | 881 get xtag => _xtag != null ? _xtag : this; |
869 | 882 |
870 set xtag(Element value) { | 883 void set xtag(Element value) { |
871 _xtag = value; | 884 _xtag = value; |
872 } | 885 } |
873 | 886 |
874 @DomName('Element.localName') | 887 @DomName('Element.localName') |
875 @DocsEditable() | 888 @DocsEditable() |
876 $if DART2JS | 889 $if DART2JS |
877 @Returns('String') | 890 @Returns('String') |
878 // Non-null for Elements. | 891 // Non-null for Elements. |
879 String get localName => JS('String', '#', _localName); | 892 String get localName => JS('String', '#', _localName); |
880 $else | 893 $else |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 void insertAdjacentText(String where, String text) { | 999 void insertAdjacentText(String where, String text) { |
987 if (JS('bool', '!!#.insertAdjacentText', this)) { | 1000 if (JS('bool', '!!#.insertAdjacentText', this)) { |
988 _insertAdjacentText(where, text); | 1001 _insertAdjacentText(where, text); |
989 } else { | 1002 } else { |
990 _insertAdjacentNode(where, new Text(text)); | 1003 _insertAdjacentNode(where, new Text(text)); |
991 } | 1004 } |
992 } | 1005 } |
993 | 1006 |
994 @JSName('insertAdjacentText') | 1007 @JSName('insertAdjacentText') |
995 void _insertAdjacentText(String where, String text) native; | 1008 void _insertAdjacentText(String where, String text) native; |
996 | 1009 |
997 $else | 1010 $else |
998 $endif | 1011 $endif |
999 | 1012 |
1000 /** | 1013 /** |
1001 * Parses text as an HTML fragment and inserts it into the DOM at the | 1014 * Parses text as an HTML fragment and inserts it into the DOM at the |
1002 * specified location. | 1015 * specified location. |
1003 * | 1016 * |
1004 * The [where] parameter indicates where to insert the HTML fragment: | 1017 * The [where] parameter indicates where to insert the HTML fragment: |
1005 * | 1018 * |
1006 * * 'beforeBegin': Immediately before this element. | 1019 * * 'beforeBegin': Immediately before this element. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 @Experimental() | 1262 @Experimental() |
1250 Point offsetTo(Element parent) { | 1263 Point offsetTo(Element parent) { |
1251 return Element._offsetToHelper(this, parent); | 1264 return Element._offsetToHelper(this, parent); |
1252 } | 1265 } |
1253 | 1266 |
1254 static Point _offsetToHelper(Element current, Element parent) { | 1267 static Point _offsetToHelper(Element current, Element parent) { |
1255 // We're hopping from _offsetParent_ to offsetParent (not just parent), so | 1268 // We're hopping from _offsetParent_ to offsetParent (not just parent), so |
1256 // offsetParent, "tops out" at BODY. But people could conceivably pass in | 1269 // offsetParent, "tops out" at BODY. But people could conceivably pass in |
1257 // the document.documentElement and I want it to return an absolute offset, | 1270 // the document.documentElement and I want it to return an absolute offset, |
1258 // so we have the special case checking for HTML. | 1271 // so we have the special case checking for HTML. |
1259 $if JSINTEROP | 1272 bool foundAsParent = identical(current, parent) || parent.tagName == 'HTML'; |
1260 bool sameAsParent = current == parent; | 1273 if (current == null || identical(current, parent)) { |
1261 $else | |
1262 bool sameAsParent = identical(current, parent); | |
1263 $endif | |
1264 bool foundAsParent = sameAsParent || parent.tagName == 'HTML'; | |
1265 if (current == null || sameAsParent) { | |
1266 if (foundAsParent) return new Point(0, 0); | 1274 if (foundAsParent) return new Point(0, 0); |
1267 throw new ArgumentError("Specified element is not a transitive offset " | 1275 throw new ArgumentError("Specified element is not a transitive offset " |
1268 "parent of this element."); | 1276 "parent of this element."); |
1269 } | 1277 } |
1270 Element parentOffset = current.offsetParent; | 1278 Element parentOffset = current.offsetParent; |
1271 Point p = Element._offsetToHelper(parentOffset, parent); | 1279 Point p = Element._offsetToHelper(parentOffset, parent); |
1272 return new Point(p.x + current.offsetLeft, p.y + current.offsetTop); | 1280 return new Point(p.x + current.offsetLeft, p.y + current.offsetTop); |
1273 } | 1281 } |
1274 | 1282 |
1275 static HtmlDocument _parseDocument; | 1283 static HtmlDocument _parseDocument; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1313 } | 1321 } |
1314 treeSanitizer = _defaultSanitizer; | 1322 treeSanitizer = _defaultSanitizer; |
1315 } else if (validator != null) { | 1323 } else if (validator != null) { |
1316 throw new ArgumentError( | 1324 throw new ArgumentError( |
1317 'validator can only be passed if treeSanitizer is null'); | 1325 'validator can only be passed if treeSanitizer is null'); |
1318 } | 1326 } |
1319 | 1327 |
1320 if (_parseDocument == null) { | 1328 if (_parseDocument == null) { |
1321 _parseDocument = document.implementation.createHtmlDocument(''); | 1329 _parseDocument = document.implementation.createHtmlDocument(''); |
1322 _parseRange = _parseDocument.createRange(); | 1330 _parseRange = _parseDocument.createRange(); |
1323 | 1331 » |
1324 // Workaround for Safari bug. Was also previously Chrome bug 229142 | 1332 // Workaround for Safari bug. Was also previously Chrome bug 229142 |
1325 // - URIs are not resolved in new doc. | 1333 // - URIs are not resolved in new doc.» |
1326 var base = _parseDocument.createElement('base'); | 1334 var base = _parseDocument.createElement('base');» |
1327 base.href = document.baseUri; | 1335 base.href = document.baseUri;» |
1328 _parseDocument.head.append(base); | 1336 _parseDocument.head.append(base); |
1329 } | 1337 } |
1330 var contextElement; | 1338 var contextElement; |
1331 if (this is BodyElement) { | 1339 if (this is BodyElement) { |
1332 contextElement = _parseDocument.body; | 1340 contextElement = _parseDocument.body; |
1333 } else { | 1341 } else { |
1334 contextElement = _parseDocument.createElement(tagName); | 1342 contextElement = _parseDocument.createElement(tagName); |
1335 _parseDocument.body.append(contextElement); | 1343 _parseDocument.body.append(contextElement); |
1336 } | 1344 } |
1337 var fragment; | 1345 var fragment; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1375 'BASE', 'BASEFONT', 'BR', 'COL', 'COLGROUP', 'EMBED', 'FRAME', 'FRAMESET', | 1383 'BASE', 'BASEFONT', 'BR', 'COL', 'COLGROUP', 'EMBED', 'FRAME', 'FRAMESET', |
1376 'HR', 'IMAGE', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM', | 1384 'HR', 'IMAGE', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM', |
1377 'SOURCE', 'STYLE', 'TITLE', 'WBR']; | 1385 'SOURCE', 'STYLE', 'TITLE', 'WBR']; |
1378 | 1386 |
1379 /** | 1387 /** |
1380 * Parses the HTML fragment and sets it as the contents of this element. | 1388 * Parses the HTML fragment and sets it as the contents of this element. |
1381 * | 1389 * |
1382 * This uses the default sanitization behavior to sanitize the HTML fragment, | 1390 * This uses the default sanitization behavior to sanitize the HTML fragment, |
1383 * use [setInnerHtml] to override the default behavior. | 1391 * use [setInnerHtml] to override the default behavior. |
1384 */ | 1392 */ |
1385 set innerHtml(String html) { | 1393 void set innerHtml(String html) { |
1386 this.setInnerHtml(html); | 1394 this.setInnerHtml(html); |
1387 } | 1395 } |
1388 | 1396 |
1389 /** | 1397 /** |
1390 * Parses the HTML fragment and sets it as the contents of this element. | 1398 * Parses the HTML fragment and sets it as the contents of this element. |
1391 * This ensures that the generated content follows the sanitization rules | 1399 * This ensures that the generated content follows the sanitization rules |
1392 * specified by the validator or treeSanitizer. | 1400 * specified by the validator or treeSanitizer. |
1393 * | 1401 * |
1394 * If the default validation behavior is too restrictive then a new | 1402 * If the default validation behavior is too restrictive then a new |
1395 * NodeValidator should be created, either extending or wrapping a default | 1403 * NodeValidator should be created, either extending or wrapping a default |
(...skipping 21 matching lines...) Expand all Loading... |
1417 html, validator: validator, treeSanitizer: treeSanitizer)); | 1425 html, validator: validator, treeSanitizer: treeSanitizer)); |
1418 } | 1426 } |
1419 } | 1427 } |
1420 String get innerHtml => _innerHtml; | 1428 String get innerHtml => _innerHtml; |
1421 | 1429 |
1422 /** | 1430 /** |
1423 * This is an ease-of-use accessor for event streams which should only be | 1431 * This is an ease-of-use accessor for event streams which should only be |
1424 * used when an explicit accessor is not available. | 1432 * used when an explicit accessor is not available. |
1425 */ | 1433 */ |
1426 ElementEvents get on => new ElementEvents(this); | 1434 ElementEvents get on => new ElementEvents(this); |
1427 | 1435 |
1428 /** | 1436 /** |
1429 * Verify if any of the attributes that we use in the sanitizer look unexpecte
d, | 1437 * Verify if any of the attributes that we use in the sanitizer look unexpecte
d, |
1430 * possibly indicating DOM clobbering attacks. | 1438 * possibly indicating DOM clobbering attacks. |
1431 * | 1439 * |
1432 * Those attributes are: attributes, lastChild, children, previousNode and tag
Name. | 1440 * Those attributes are: attributes, lastChild, children, previousNode and tag
Name. |
1433 */ | 1441 */ |
1434 $if DART2JS | 1442 $if DART2JS |
1435 static bool _hasCorruptedAttributes(Element element) { | 1443 static bool _hasCorruptedAttributes(Element element) { |
1436 return JS('bool', r''' | 1444 return JS('bool', r''' |
1437 (function(element) { | 1445 (function(element) { |
1438 if (!(element.attributes instanceof NamedNodeMap)) { | 1446 if (!(element.attributes instanceof NamedNodeMap)) { |
1439 return true; | 1447 return true; |
1440 } | 1448 } |
1441 var childNodes = element.childNodes; | 1449 var childNodes = element.childNodes; |
1442 if (element.lastChild && | 1450 if (element.lastChild && |
1443 element.lastChild !== childNodes[childNodes.length -1]) { | 1451 element.lastChild !== childNodes[childNodes.length -1]) { |
1444 return true; | 1452 return true; |
1445 } | 1453 } |
1446 if (element.children) { // On Safari, children can apparently be null. | 1454 if (element.children) { // On Safari, children can apparently be null. |
1447 if (!((element.children instanceof HTMLCollection) || | 1455 if (!((element.children instanceof HTMLCollection) || |
1448 (element.children instanceof NodeList))) { | 1456 (element.children instanceof NodeList))) { |
1449 return true; | 1457 return true; |
1450 } | 1458 } |
1451 } | 1459 } |
1452 return false; | 1460 return false; |
1453 })(#)''', element); | 1461 })(#)''', element); |
1454 } | 1462 } |
1455 $else | 1463 $else |
1456 | 1464 // Dartium isn't affected by these attacks, because it goes directly to the C+
+ API. |
1457 static var _namedNodeMap = js.context["NamedNodeMap"]; | 1465 static bool _hasCorruptedAttributes(Element element) => false; |
1458 static var _htmlCollection = js.context["HTMLCollection"]; | |
1459 static var _nodeList = js.context["NodeList"]; | |
1460 | |
1461 static bool _hasCorruptedAttributes(Element element) { | |
1462 var attributes = unwrap_jso(element)["attributes"]; | |
1463 if (!attributes.instanceof(_namedNodeMap)) { | |
1464 return true; | |
1465 } | |
1466 var childNodes = unwrap_jso(element.childNodes); | |
1467 var length = childNodes["length"]; | |
1468 var lastChild = unwrap_jso(element.lastChild); | |
1469 if (null != lastChild && | |
1470 lastChild != childNodes[length - 1]) { | |
1471 return true; | |
1472 } | |
1473 var children = unwrap_jso(element._children); | |
1474 if (null != children) { // On Safari, children can apparently be null. | |
1475 if (!children.instanceof(_htmlCollection) || | |
1476 children.instanceof(_nodeList)) { | |
1477 » return true; | |
1478 } | |
1479 } | |
1480 return false; | |
1481 } | |
1482 $endif | 1466 $endif |
1483 | 1467 |
1484 String get _safeTagName { | |
1485 String result = 'element tag unavailable'; | |
1486 try { | |
1487 if (tagName is String) { | |
1488 result = tagName; | |
1489 } | |
1490 } catch (e) {} | |
1491 return result; | |
1492 } | |
1493 | |
1494 $if DART2JS | 1468 $if DART2JS |
1495 @DomName('Element.offsetHeight') | 1469 @DomName('Element.offsetHeight') |
1496 @DocsEditable() | 1470 @DocsEditable() |
1497 int get offsetHeight => JS('num', '#.offsetHeight', this).round(); | 1471 int get offsetHeight => JS('num', '#.offsetHeight', this).round(); |
1498 | 1472 |
1499 @DomName('Element.offsetLeft') | 1473 @DomName('Element.offsetLeft') |
1500 @DocsEditable() | 1474 @DocsEditable() |
1501 int get offsetLeft => JS('num', '#.offsetLeft', this).round(); | 1475 int get offsetLeft => JS('num', '#.offsetLeft', this).round(); |
1502 | 1476 |
1503 @DomName('Element.offsetTop') | 1477 @DomName('Element.offsetTop') |
(...skipping 23 matching lines...) Expand all Loading... |
1527 @DomName('Element.scrollHeight') | 1501 @DomName('Element.scrollHeight') |
1528 @DocsEditable() | 1502 @DocsEditable() |
1529 int get scrollHeight => JS('num', '#.scrollHeight', this).round(); | 1503 int get scrollHeight => JS('num', '#.scrollHeight', this).round(); |
1530 | 1504 |
1531 @DomName('Element.scrollLeft') | 1505 @DomName('Element.scrollLeft') |
1532 @DocsEditable() | 1506 @DocsEditable() |
1533 int get scrollLeft => JS('num', '#.scrollLeft', this).round(); | 1507 int get scrollLeft => JS('num', '#.scrollLeft', this).round(); |
1534 | 1508 |
1535 @DomName('Element.scrollLeft') | 1509 @DomName('Element.scrollLeft') |
1536 @DocsEditable() | 1510 @DocsEditable() |
1537 set scrollLeft(int value) { | 1511 void set scrollLeft(int value) { |
1538 JS("void", "#.scrollLeft = #", this, value.round()); | 1512 JS("void", "#.scrollLeft = #", this, value.round()); |
1539 } | 1513 } |
1540 | 1514 |
1541 @DomName('Element.scrollTop') | 1515 @DomName('Element.scrollTop') |
1542 @DocsEditable() | 1516 @DocsEditable() |
1543 int get scrollTop => JS('num', '#.scrollTop', this).round(); | 1517 int get scrollTop => JS('num', '#.scrollTop', this).round(); |
1544 | 1518 |
1545 @DomName('Element.scrollTop') | 1519 @DomName('Element.scrollTop') |
1546 @DocsEditable() | 1520 @DocsEditable() |
1547 set scrollTop(int value) { | 1521 void set scrollTop(int value) { |
1548 JS("void", "#.scrollTop = #", this, value.round()); | 1522 JS("void", "#.scrollTop = #", this, value.round()); |
1549 } | 1523 } |
1550 | 1524 |
1551 @DomName('Element.scrollWidth') | 1525 @DomName('Element.scrollWidth') |
1552 @DocsEditable() | 1526 @DocsEditable() |
1553 int get scrollWidth => JS('num', '#.scrollWidth', this).round(); | 1527 int get scrollWidth => JS('num', '#.scrollWidth', this).round(); |
1554 | 1528 |
1555 $else | 1529 $else |
1556 $if JSINTEROP | 1530 $if JSINTEROP |
1557 // Need to explicitly delegate because Element is no longer abstract for Darti
um. | |
1558 bool get isContentEditable => _blink.BlinkHTMLElement.instance.isContentEditab
le_Getter_(unwrap_jso(this)); | |
1559 void click() => _blink.BlinkHTMLElement.instance.click_Callback_0_(unwrap_jso(
this)); | |
1560 | |
1561 @DomName('Element.offsetHeight') | 1531 @DomName('Element.offsetHeight') |
1562 @DocsEditable() | 1532 @DocsEditable() |
1563 int get offsetHeight => _blink.BlinkElement.instance.offsetHeight_Getter_(unwr
ap_jso(this)).round(); | 1533 int get offsetHeight => _blink.BlinkElement.instance.offsetHeight_Getter_(unwr
ap_jso(this)).round(); |
1564 | 1534 |
1565 @DomName('Element.offsetLeft') | 1535 @DomName('Element.offsetLeft') |
1566 @DocsEditable() | 1536 @DocsEditable() |
1567 int get offsetLeft => _blink.BlinkElement.instance.offsetLeft_Getter_(unwrap_j
so(this)).round(); | 1537 int get offsetLeft => _blink.BlinkElement.instance.offsetLeft_Getter_(unwrap_j
so(this)).round(); |
1568 | 1538 |
1569 @DomName('Element.offsetTop') | 1539 @DomName('Element.offsetTop') |
1570 @DocsEditable() | 1540 @DocsEditable() |
(...skipping 22 matching lines...) Expand all Loading... |
1593 @DomName('Element.scrollHeight') | 1563 @DomName('Element.scrollHeight') |
1594 @DocsEditable() | 1564 @DocsEditable() |
1595 int get scrollHeight => _blink.BlinkElement.instance.scrollHeight_Getter_(unwr
ap_jso(this)).round(); | 1565 int get scrollHeight => _blink.BlinkElement.instance.scrollHeight_Getter_(unwr
ap_jso(this)).round(); |
1596 | 1566 |
1597 @DomName('Element.scrollLeft') | 1567 @DomName('Element.scrollLeft') |
1598 @DocsEditable() | 1568 @DocsEditable() |
1599 int get scrollLeft => _blink.BlinkElement.instance.scrollLeft_Getter_(unwrap_j
so(this)).round(); | 1569 int get scrollLeft => _blink.BlinkElement.instance.scrollLeft_Getter_(unwrap_j
so(this)).round(); |
1600 | 1570 |
1601 @DomName('Element.scrollLeft') | 1571 @DomName('Element.scrollLeft') |
1602 @DocsEditable() | 1572 @DocsEditable() |
1603 set scrollLeft(int value) => _blink.BlinkElement.instance.scrollLeft_Setter_(u
nwrap_jso(this), value.round()); | 1573 void set scrollLeft(int value) => _blink.BlinkElement.instance.scrollLeft_Sett
er_(unwrap_jso(this), value.round()); |
1604 | 1574 |
1605 @DomName('Element.scrollTop') | 1575 @DomName('Element.scrollTop') |
1606 @DocsEditable() | 1576 @DocsEditable() |
1607 int get scrollTop => _blink.BlinkElement.instance.scrollTop_Getter_(unwrap_jso
(this)).round(); | 1577 int get scrollTop => _blink.BlinkElement.instance.scrollTop_Getter_(unwrap_jso
(this)).round(); |
1608 | 1578 |
1609 @DomName('Element.scrollTop') | 1579 @DomName('Element.scrollTop') |
1610 @DocsEditable() | 1580 @DocsEditable() |
1611 set scrollTop(int value) => _blink.BlinkElement.instance.scrollTop_Setter_(unw
rap_jso(this), value.round()); | 1581 void set scrollTop(int value) => _blink.BlinkElement.instance.scrollTop_Setter
_(unwrap_jso(this), value.round()); |
1612 | 1582 |
1613 @DomName('Element.scrollWidth') | 1583 @DomName('Element.scrollWidth') |
1614 @DocsEditable() | 1584 @DocsEditable() |
1615 int get scrollWidth => _blink.BlinkElement.instance.scrollWidth_Getter_(unwrap
_jso(this)).round(); | 1585 int get scrollWidth => _blink.BlinkElement.instance.scrollWidth_Getter_(unwrap
_jso(this)).round(); |
1616 $else | 1586 $else |
1617 @DomName('Element.offsetHeight') | 1587 @DomName('Element.offsetHeight') |
1618 @DocsEditable() | 1588 @DocsEditable() |
1619 int get offsetHeight => _blink.BlinkElement.offsetHeight_Getter(this).round(); | 1589 int get offsetHeight => _blink.BlinkElement.offsetHeight_Getter(this).round(); |
1620 | 1590 |
1621 @DomName('Element.offsetLeft') | 1591 @DomName('Element.offsetLeft') |
(...skipping 27 matching lines...) Expand all Loading... |
1649 @DomName('Element.scrollHeight') | 1619 @DomName('Element.scrollHeight') |
1650 @DocsEditable() | 1620 @DocsEditable() |
1651 int get scrollHeight => _blink.BlinkElement.scrollHeight_Getter(this).round(); | 1621 int get scrollHeight => _blink.BlinkElement.scrollHeight_Getter(this).round(); |
1652 | 1622 |
1653 @DomName('Element.scrollLeft') | 1623 @DomName('Element.scrollLeft') |
1654 @DocsEditable() | 1624 @DocsEditable() |
1655 int get scrollLeft => _blink.BlinkElement.scrollLeft_Getter(this).round(); | 1625 int get scrollLeft => _blink.BlinkElement.scrollLeft_Getter(this).round(); |
1656 | 1626 |
1657 @DomName('Element.scrollLeft') | 1627 @DomName('Element.scrollLeft') |
1658 @DocsEditable() | 1628 @DocsEditable() |
1659 set scrollLeft(int value) => _blink.BlinkElement.scrollLeft_Setter(this, value
.round()); | 1629 void set scrollLeft(int value) => _blink.BlinkElement.scrollLeft_Setter(this,
value.round()); |
1660 | 1630 |
1661 @DomName('Element.scrollTop') | 1631 @DomName('Element.scrollTop') |
1662 @DocsEditable() | 1632 @DocsEditable() |
1663 int get scrollTop => _blink.BlinkElement.scrollTop_Getter(this).round(); | 1633 int get scrollTop => _blink.BlinkElement.scrollTop_Getter(this).round(); |
1664 | 1634 |
1665 @DomName('Element.scrollTop') | 1635 @DomName('Element.scrollTop') |
1666 @DocsEditable() | 1636 @DocsEditable() |
1667 set scrollTop(int value) => _blink.BlinkElement.scrollTop_Setter(this, value.r
ound()); | 1637 void set scrollTop(int value) => _blink.BlinkElement.scrollTop_Setter(this, va
lue.round()); |
1668 | 1638 |
1669 @DomName('Element.scrollWidth') | 1639 @DomName('Element.scrollWidth') |
1670 @DocsEditable() | 1640 @DocsEditable() |
1671 int get scrollWidth => _blink.BlinkElement.scrollWidth_Getter(this).round(); | 1641 int get scrollWidth => _blink.BlinkElement.scrollWidth_Getter(this).round(); |
1672 $endif | 1642 $endif |
1673 $endif | 1643 $endif |
1674 | 1644 |
1675 $!MEMBERS | 1645 $!MEMBERS |
1676 } | 1646 } |
1677 | 1647 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1710 const ScrollAlignment._internal(this._value); | 1680 const ScrollAlignment._internal(this._value); |
1711 toString() => 'ScrollAlignment.$_value'; | 1681 toString() => 'ScrollAlignment.$_value'; |
1712 | 1682 |
1713 /// Attempt to align the element to the top of the scrollable area. | 1683 /// Attempt to align the element to the top of the scrollable area. |
1714 static const TOP = const ScrollAlignment._internal('TOP'); | 1684 static const TOP = const ScrollAlignment._internal('TOP'); |
1715 /// Attempt to center the element in the scrollable area. | 1685 /// Attempt to center the element in the scrollable area. |
1716 static const CENTER = const ScrollAlignment._internal('CENTER'); | 1686 static const CENTER = const ScrollAlignment._internal('CENTER'); |
1717 /// Attempt to align the element to the bottom of the scrollable area. | 1687 /// Attempt to align the element to the bottom of the scrollable area. |
1718 static const BOTTOM = const ScrollAlignment._internal('BOTTOM'); | 1688 static const BOTTOM = const ScrollAlignment._internal('BOTTOM'); |
1719 } | 1689 } |
OLD | NEW |