| Index: sky/framework/sky-element.sky
 | 
| diff --git a/sky/framework/sky-element.sky b/sky/framework/sky-element.sky
 | 
| deleted file mode 100644
 | 
| index 5a4082316a3f08f5a716a48804a695a8c57c08f9..0000000000000000000000000000000000000000
 | 
| --- a/sky/framework/sky-element.sky
 | 
| +++ /dev/null
 | 
| @@ -1,164 +0,0 @@
 | 
| -<!--
 | 
| -// 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";
 | 
| -
 | 
| -typedef dynamic _Converter(String value);
 | 
| -
 | 
| -final Map<String, _Converter> _kAttributeConverters = {
 | 
| -  'boolean': (String value) {
 | 
| -    return value == 'true';
 | 
| -  },
 | 
| -  'number': (String value) {
 | 
| -    try {
 | 
| -      return double.parse(value);
 | 
| -    } catch(_) {
 | 
| -      return 0.0;
 | 
| -    }
 | 
| -  },
 | 
| -  'string': (String value) {
 | 
| -    return value == null ? '' : value;
 | 
| -  },
 | 
| -};
 | 
| -
 | 
| -class _Registration {
 | 
| -  final Element template;
 | 
| -  final Map<String, _Converter> attributes = new Map();
 | 
| -
 | 
| -  _Registration(this.template);
 | 
| -
 | 
| -  void parseAttributeSpec(definition) {
 | 
| -    String spec = definition.getAttribute('attributes');
 | 
| -    if (spec == null)
 | 
| -      return;
 | 
| -  
 | 
| -    for (String token in spec.split(',')) {
 | 
| -      List<String> parts = token.split(':');
 | 
| -
 | 
| -      if (parts.length != 2) {
 | 
| -        window.console.error(
 | 
| -            'Invalid attribute spec "${spec}", attributes must'
 | 
| -            ' be {name}:{type}, where type is one of boolean, number or'
 | 
| -            ' string.');
 | 
| -        continue;
 | 
| -      }
 | 
| -  
 | 
| -      var name = parts[0].trim();
 | 
| -      var type = parts[1].trim();
 | 
| -  
 | 
| -      defineAttribute(name, type);
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  void defineAttribute(String name, String type) {
 | 
| -    _Converter converter = _kAttributeConverters[type];
 | 
| -
 | 
| -    if (converter == null) {
 | 
| -      window.console.error(
 | 
| -          'Invalid attribute type "${type}", type must be one of boolean,'
 | 
| -          ' number or string.');
 | 
| -      return;
 | 
| -    }
 | 
| -
 | 
| -    attributes[name] = converter;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -final Map<String, _Registration> _registery = new Map<String, _Registration>();
 | 
| -
 | 
| -class Tagname {
 | 
| -  final String name;
 | 
| -  const Tagname(this.name);
 | 
| -}
 | 
| -
 | 
| -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);
 | 
| -  _Registration _registration;
 | 
| -
 | 
| -  SkyElement() {
 | 
| -    _registration = _registery[tagName];
 | 
| -    // Invoke attributeChanged callback when element is first created too.
 | 
| -    // TODO(abarth): Is this necessary? We shouldn't have any attribute yet...
 | 
| -    for (Attr attribute in getAttributes())
 | 
| -      attributeChangedCallback(attribute.name, null, attribute.value);
 | 
| -  }
 | 
| -
 | 
| -  attachedCallback() {
 | 
| -    if (shadowRoot == null) {
 | 
| -      if (_registration.template != null) {
 | 
| -        ShadowRoot shadow = ensureShadowRoot();
 | 
| -        Node content = _registration.template.content;
 | 
| -        shadow.appendChild(document.importNode(content, deep: true));
 | 
| -        shadowRootReady();
 | 
| -      }
 | 
| -    }
 | 
| -    attached();
 | 
| -  }
 | 
| -
 | 
| -  detachedCallback() {
 | 
| -    detached();
 | 
| -  }
 | 
| -
 | 
| -  attributeChangedCallback(name, oldValue, newValue) {
 | 
| -    attributeChanged(name, oldValue, newValue);
 | 
| -
 | 
| -    _Converter converter = _registration.attributes[name];
 | 
| -    if (converter == null)
 | 
| -      return;
 | 
| -    Symbol callback = new Symbol('${name}Changed');
 | 
| -    InstanceMirror mirror = reflect(this);
 | 
| -    if (mirror.type.instanceMembers.containsKey(callback))
 | 
| -      mirror.invoke(callback, [converter(oldValue), converter(newValue)]);
 | 
| -  }
 | 
| -
 | 
| -  noSuchMethod(Invocation invocation) {
 | 
| -    String name = MirrorSystem.getName(invocation.memberName);
 | 
| -    if (name.endsWith('='))
 | 
| -      name = name.substring(0, name.length - 1);
 | 
| -    _Converter converter = _registration.attributes[name];
 | 
| -    if (converter != null) {
 | 
| -      if (invocation.isGetter) {
 | 
| -        return converter(getAttribute(name));
 | 
| -      } else if (invocation.isSetter) {
 | 
| -        setAttribute(name, invocation.positionalArguments[0].toString());
 | 
| -        return;
 | 
| -      }
 | 
| -    }
 | 
| -    return super.noSuchMethod(invocation);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -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)
 | 
| -                        ..parseAttributeSpec(definition);
 | 
| -}
 | 
| -</script>
 | 
| 
 |