OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library polymer.custom_element; | 5 library polymer.custom_element; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import 'package:mdv/mdv.dart' as mdv; | 9 import 'package:mdv/mdv.dart' as mdv; |
10 import 'package:meta/meta.dart'; | 10 import 'package:meta/meta.dart'; |
(...skipping 30 matching lines...) Expand all Loading... | |
41 if (_customElements.containsKey(localName)) { | 41 if (_customElements.containsKey(localName)) { |
42 throw new ArgumentError('custom element $localName already registered.'); | 42 throw new ArgumentError('custom element $localName already registered.'); |
43 } | 43 } |
44 | 44 |
45 // TODO(jmesserly): validate this is a valid tag name, not a selector. | 45 // TODO(jmesserly): validate this is a valid tag name, not a selector. |
46 _customElements[localName] = create; | 46 _customElements[localName] = create; |
47 | 47 |
48 // Initialize elements already on the page. | 48 // Initialize elements already on the page. |
49 for (var query in [localName, '[is=$localName]']) { | 49 for (var query in [localName, '[is=$localName]']) { |
50 for (var element in document.queryAll(query)) { | 50 for (var element in document.queryAll(query)) { |
51 _initCustomElement(element, create); | 51 _initCustomElement(element, localName, create); |
52 } | 52 } |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 /** | 56 /** |
57 * The base class for all Dart web components. In addition to the [Element] | 57 * The base class for all Dart web components. In addition to the [Element] |
58 * interface, it also provides lifecycle methods: | 58 * interface, it also provides lifecycle methods: |
59 * - [created] | 59 * - [created] |
60 * - [inserted] | 60 * - [inserted] |
61 * - [attributeChanged] | 61 * - [attributeChanged] |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 } | 115 } |
116 | 116 |
117 // TODO(sigmund): delete this. We should techincally only call this method | 117 // TODO(sigmund): delete this. We should techincally only call this method |
118 // on subclasses of polymer element. To delete this we either make this method | 118 // on subclasses of polymer element. To delete this we either make this method |
119 // private in PolymerElement, stop doing compilation, or add support for the | 119 // private in PolymerElement, stop doing compilation, or add support for the |
120 // polymer-element tag. | 120 // polymer-element tag. |
121 void shadowRootReady(ShadowRoot root, String elementName) {} | 121 void shadowRootReady(ShadowRoot root, String elementName) {} |
122 | 122 |
123 getShadowRoot(String componentName) => _generatedRoots[componentName]; | 123 getShadowRoot(String componentName) => _generatedRoots[componentName]; |
124 | 124 |
125 /** Any CSS selector (class, id or element) defined name to mangled name. */ | |
126 ScopedCssMapper _mapper = new ScopedCssMapper({}); | |
127 | |
128 // TODO(terry): Add a mapper per component in the type hierarchy. | |
129 ScopedCssMapper getScopedCss(String componentName) => _mapper; | |
130 void setScopedCss(String componentName, ScopedCssMapper mapper) { | |
131 _mapper = mapper; | |
132 } | |
133 | 125 |
134 /** | 126 /** |
135 * *Warning*: This is an implementation helper for Custom Elements and | 127 * *Warning*: This is an implementation helper for Custom Elements and |
136 * should not be used in your code. | 128 * should not be used in your code. |
137 * | 129 * |
138 * Clones the template, instantiates custom elements and hooks events, then | 130 * Clones the template, instantiates custom elements and hooks events, then |
139 * returns it. | 131 * returns it. |
140 */ | 132 */ |
141 DocumentFragment cloneTemplate(DocumentFragment shadowTemplate) { | 133 DocumentFragment cloneTemplate(DocumentFragment shadowTemplate) { |
142 var result = shadowTemplate.clone(true); | 134 var result = shadowTemplate.clone(true); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 void inserted() {} | 172 void inserted() {} |
181 | 173 |
182 /** Invoked when this component is removed from the DOM tree. */ | 174 /** Invoked when this component is removed from the DOM tree. */ |
183 void removed() {} | 175 void removed() {} |
184 | 176 |
185 // TODO(jmesserly): how do we implement this efficiently? | 177 // TODO(jmesserly): how do we implement this efficiently? |
186 // See https://github.com/dart-lang/web-ui/issues/37 | 178 // See https://github.com/dart-lang/web-ui/issues/37 |
187 /** Invoked when any attribute of the component is modified. */ | 179 /** Invoked when any attribute of the component is modified. */ |
188 void attributeChanged(String name, String oldValue, String newValue) {} | 180 void attributeChanged(String name, String oldValue, String newValue) {} |
189 | 181 |
190 /** | |
191 * **Note**: This is an implementation helper and should not need to be calle | |
192 * from your code. | |
193 * | |
194 * Initializes the contents of the ShadowRoot from template inside the | |
195 * `<element>` element. | |
196 */ | |
197 void initShadow() {} | |
198 | |
199 get model => host.model; | 182 get model => host.model; |
200 | 183 |
201 void set model(newModel) { | 184 void set model(newModel) { |
202 host.model = newModel; | 185 host.model = newModel; |
203 } | 186 } |
204 | 187 |
205 get templateInstance => host.templateInstance; | 188 get templateInstance => host.templateInstance; |
206 get isTemplate => host.isTemplate; | 189 get isTemplate => host.isTemplate; |
207 get ref => host.ref; | 190 get ref => host.ref; |
208 get content => host.content; | 191 get content => host.content; |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 Stream<TouchEvent> get onTouchMove => host.onTouchMove; | 600 Stream<TouchEvent> get onTouchMove => host.onTouchMove; |
618 Stream<TouchEvent> get onTouchStart => host.onTouchStart; | 601 Stream<TouchEvent> get onTouchStart => host.onTouchStart; |
619 Stream<TransitionEvent> get onTransitionEnd => host.onTransitionEnd; | 602 Stream<TransitionEvent> get onTransitionEnd => host.onTransitionEnd; |
620 | 603 |
621 // TODO(sigmund): do the normal forwarding when dartbug.com/7919 is fixed. | 604 // TODO(sigmund): do the normal forwarding when dartbug.com/7919 is fixed. |
622 Stream<WheelEvent> get onMouseWheel { | 605 Stream<WheelEvent> get onMouseWheel { |
623 throw new UnsupportedError('onMouseWheel is not supported'); | 606 throw new UnsupportedError('onMouseWheel is not supported'); |
624 } | 607 } |
625 } | 608 } |
626 | 609 |
627 /** | |
628 * Maps CSS selectors (class and) to a mangled name and maps x-component name | |
629 * to [is='x-component']. | |
630 */ | |
631 class ScopedCssMapper { | |
632 final Map<String, String> _mapping; | |
633 | |
634 ScopedCssMapper(this._mapping); | |
635 | |
636 /** Returns mangled name of selector sans . or # character. */ | |
637 String operator [](String selector) => _mapping[selector]; | |
638 | |
639 /** Returns mangled name of selector w/ . or # character. */ | |
640 String getSelector(String selector) { | |
641 var prefixedName = this[selector]; | |
642 var selectorType = selector[0]; | |
643 if (selectorType == '.' || selectorType == '#') { | |
644 return '$selectorType${prefixedName}'; | |
645 } | |
646 | |
647 return prefixedName; | |
648 } | |
649 } | |
650 | 610 |
651 typedef DocumentFragmentCreated(DocumentFragment fragment); | 611 typedef DocumentFragmentCreated(DocumentFragment fragment); |
652 | 612 |
653 Map<String, Function> _customElements; | 613 Map<String, Function> _customElements; |
654 | 614 |
655 void _createElements(Node node) { | 615 void _createElements(Node node) { |
656 for (var c = node.firstChild; c != null; c = c.nextNode) { | 616 for (var c = node.firstChild; c != null; c = c.nextNode) { |
657 _createElements(c); | 617 _createElements(c); |
658 } | 618 } |
659 if (node is Element) { | 619 if (node is Element) { |
660 var ctor = _customElements[node.localName]; | 620 var name = node.localName; |
621 var ctor = _customElements[name]; | |
661 if (ctor == null) { | 622 if (ctor == null) { |
662 var isAttr = node.attributes['is']; | 623 name = node.attributes['is']; |
663 if (isAttr != null) ctor = _customElements[isAttr]; | 624 if (name != null) ctor = _customElements[name]; |
664 } | 625 } |
665 if (ctor != null) _initCustomElement(node, ctor); | 626 if (ctor != null) _initCustomElement(node, name, ctor); |
666 } | 627 } |
667 } | 628 } |
668 | 629 |
669 void _initCustomElement(Element node, CustomElement ctor()) { | 630 void _initCustomElement(Element node, String localName, CustomElement ctor()) { |
Jennifer Messerly
2013/07/18 23:56:04
do we need this arg?
Siggi Cherem (dart-lang)
2013/07/19 22:52:52
oops, not anymore =) I removed the use of it, but
| |
670 CustomElement element = ctor(); | 631 CustomElement element = ctor(); |
671 element.host = node; | 632 element.host = node; |
672 | 633 |
673 // TODO(jmesserly): replace lifecycle stuff with a proper polyfill. | 634 // TODO(jmesserly): replace lifecycle stuff with a proper polyfill. |
674 element..initShadow()..created(); | 635 element.created(); |
675 | 636 |
676 _registerLifecycleInsert(element); | 637 _registerLifecycleInsert(element); |
677 } | 638 } |
678 | 639 |
679 void _registerLifecycleInsert(CustomElement element) { | 640 void _registerLifecycleInsert(CustomElement element) { |
680 runAsync(() { | 641 runAsync(() { |
681 // TODO(jmesserly): bottom up or top down insert? | 642 // TODO(jmesserly): bottom up or top down insert? |
682 var node = element.host; | 643 var node = element.host; |
683 | 644 |
684 // TODO(jmesserly): need a better check to see if the node has been removed. | 645 // TODO(jmesserly): need a better check to see if the node has been removed. |
(...skipping 25 matching lines...) Expand all Loading... | |
710 /** | 671 /** |
711 * DEPRECATED: this has no effect. Shadow DOM should always be used with custom | 672 * DEPRECATED: this has no effect. Shadow DOM should always be used with custom |
712 * elements. | 673 * elements. |
713 * | 674 * |
714 * Set this to true to use native Shadow DOM if it is supported. | 675 * Set this to true to use native Shadow DOM if it is supported. |
715 * Note that this will change behavior of [WebComponent] APIs for tree | 676 * Note that this will change behavior of [WebComponent] APIs for tree |
716 * traversal. | 677 * traversal. |
717 */ | 678 */ |
718 @deprecated | 679 @deprecated |
719 bool useShadowDom = false; | 680 bool useShadowDom = false; |
OLD | NEW |