Index: sky/framework/sky-element.sky |
diff --git a/sky/framework/sky-element.sky b/sky/framework/sky-element.sky |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b7e16ea6d75d7e7a8c732fa272b0a092c5b8defd |
--- /dev/null |
+++ b/sky/framework/sky-element.sky |
@@ -0,0 +1,85 @@ |
+<!-- |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+--> |
+<script> |
+import "dart:mirrors"; |
+import "dart:sky"; |
+ |
+class _Registration { |
+ Element template; |
+ _Registration(this.template); |
+} |
+ |
+final Map<String, _Registration> _registery = new Map<String, _Registration>(); |
+ |
+String _getTagName(Type type) { |
+ return reflectClass(type).metadata.firstWhere( |
+ (i) => i.reflectee is tagname).reflectee.name; |
+} |
+ |
+abstract class SkyElement extends Element { |
+ // Override these functions to receive lifecycle notifications. |
+ void created() {} |
+ void attached() {} |
+ void detached() {} |
+ void attributeChanged(String attrName, String oldValue, String newValue) {} |
+ void shadowRootReady() {} |
+ |
+ String get tagName => _getTagName(runtimeType); |
+ |
+ // TODO(abarth): Rather than hard-coding "example" here, we should make the |
+ // bindings read the |tagName| property of this object during construction. |
+ SkyElement() : super("example") { |
+ created(); |
+ |
+ // Invoke attributeChanged callback when element is first created too. |
+ for (Attr attribute in getAttributes()) |
+ attributeChangedCallback(attribute.name, null, attribute.value); |
+ } |
+ |
+ attachedCallback() { |
+ if (shadowRoot == null) { |
+ var registration = _registery[tagName]; |
+ if (registration.template != null) { |
+ ShadowRoot shadow = ensureShadowRoot(); |
+ var tree = registration.template.content.cloneNode(deep:true); |
+ shadow.appendChild(tree); |
+ shadowRootReady(); |
+ } |
+ } |
+ attached(); |
+ } |
+ |
+ detachedCallback() { |
+ detached(); |
+ } |
+ |
+ attributeChangedCallback(name, oldValue, newValue) { |
+ attributeChanged(name, oldValue, newValue); |
+ } |
+} |
+ |
+class tagname { |
+ final String name; |
+ const tagname(this.name); |
+} |
+ |
+void register(Element script, Type type) { |
+ Element definition = script.parentNode; |
+ |
+ if (definition.tagName != 'sky-element') |
+ throw new UnsupportedError('register() calls must be inside a <sky-element>.'); |
+ |
+ ClassMirror mirror = reflectClass(type); |
+ if (!mirror.isSubclassOf(reflectClass(SkyElement))) |
+ throw new UnsupportedError('@tagname can only be used on descendants of SkyElement'); |
+ |
+ String tagName = _getTagName(type); |
+ Element template = definition.querySelector('template'); |
+ |
+ document.registerElement(tagName, type); |
+ _registery[tagName] = new _Registration(template); |
+} |
+</script> |