Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1037)

Side by Side Diff: sky/framework/sky-element/sky-element.sky

Issue 836923002: Automate reflected properties in SkyElement. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!-- 1 <!--
2 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Copyright 2014 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be 3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file. 4 // found in the LICENSE file.
5 --> 5 -->
6 <import src="sky-binder.sky" as="binder" /> 6 <import src="sky-binder.sky" as="binder" />
7 <script> 7 <script>
8 var templates = new Map(); 8 var templates = new Map();
9 9
10 var attributeDescriptors = {
11 boolean: {
12 type: 'boolean',
13 convert: function(value) {
14 if (typeof value == 'string')
15 return value == 'true';
16 return !!value;
17 },
18 },
19 number: {
20 type: 'number',
21 convert: function(value) {
22 return Number(value);
23 },
24 },
25 string: {
26 type: 'string',
27 convert: function(value) {
28 if (value == null)
abarth-chromium 2015/01/06 04:02:38 Why handle |null| special but not |undefined|?
esprehn 2015/01/06 04:10:24 undefined is itself a string, if I special case th
29 return "";
30 return String(value);
31 },
32 },
33 };
34
35 function defineReflectedAttribute(prototype, descriptor, name) {
abarth-chromium 2015/01/06 04:02:38 Why not just pass in the convert function instead
esprehn 2015/01/06 04:10:24 Done, originally I had a more complex idea for how
36 Object.defineProperty(prototype, name, {
37 get: function() {
38 return descriptor.convert(this.getAttribute(name));
39 },
40 set: function(newValue) {
41 this.setAttribute(name, descriptor.convert(newValue));
42 },
43 enumerable: true,
44 configurable: true,
45 });
46
47 prototype[name + 'AttributeChanged'] = function(oldValue, newValue) {
48 this.notifyPropertyChanged(name, descriptor.convert(oldValue),
49 descriptor.convert(newValue));
50 };
51 }
52
53 function defineReflectedAttributes(elementClass, list) {
54 var attributeNames = (list || '').split(',');
55 var prototype = elementClass.prototype;
56
57 for (var i = 0; i < attributeNames.length; ++i) {
58 var parts = attributeNames[i].split(':');
59 var name = parts[0].trim();
60 var type = (parts[1] || "").trim();
abarth-chromium 2015/01/06 04:02:38 s/""/''/ for consistency
esprehn 2015/01/06 04:10:24 done.
61 var descriptor = attributeDescriptors[type] || attributeDescriptors.string;
62
63 defineReflectedAttribute(prototype, descriptor, name);
64 }
65 }
66
10 class SkyElement extends HTMLElement { 67 class SkyElement extends HTMLElement {
11 68
12 static register() { 69 static register() {
13 var wrapper = document.currentScript.parentNode; 70 var wrapper = document.currentScript.parentNode;
14 71
15 if (wrapper.localName !== 'sky-element') 72 if (wrapper.localName !== 'sky-element')
16 throw new Error('No <sky-element>.'); 73 throw new Error('No <sky-element>.');
17 74
18 var tagName = wrapper.getAttribute("name"); 75 var tagName = wrapper.getAttribute("name");
19 if (!tagName) 76 if (!tagName)
20 throw new Error('<sky-element> must have a name.'); 77 throw new Error('<sky-element> must have a name.');
21 78
22 var template = wrapper.querySelector('template'); 79 var template = wrapper.querySelector('template');
23 if (template) 80 if (template)
24 templates.set(tagName, template); 81 templates.set(tagName, template);
25 82
83 defineReflectedAttributes(this, wrapper.getAttribute("attributes"));
84
26 return document.registerElement(tagName, { 85 return document.registerElement(tagName, {
27 prototype: this.prototype, 86 prototype: this.prototype,
28 }); 87 });
29 } 88 }
30 89
31 created() { 90 created() {
32 // override 91 // override
33 } 92 }
34 93
35 attached() { 94 attached() {
36 // override 95 // override
37 } 96 }
38 97
39 detached() { 98 detached() {
40 // override 99 // override
41 } 100 }
42 101
43 attributeChanged(attrName, oldValue, newValue) { 102 attributeChanged(attrName, oldValue, newValue) {
44 // override 103 // override
45 } 104 }
46 105
47 shadowRootReady() { 106 shadowRootReady() {
48 // override 107 // override
49 } 108 }
50 109
51 createdCallback() { 110 createdCallback() {
52 this.isAttached = false; 111 this.isAttached = false;
53 this.created(); 112 this.created();
113
114 // Invoke attributeChanged callback when element is first created too.
115 var attributes = this.getAttributes();
116 for (var i = 0; i < attributes.length; ++i) {
117 var attribute = attributes[i];
118 this.attributeChangedCallback(attribute.name, null, attribute.value);
119 }
54 } 120 }
55 121
56 attachedCallback() { 122 attachedCallback() {
57 if (!this.shadowRoot) { 123 if (!this.shadowRoot) {
58 var template = templates.get(this.localName); 124 var template = templates.get(this.localName);
59 if (template) { 125 if (template) {
60 var shadow = this.ensureShadowRoot(); 126 var shadow = this.ensureShadowRoot();
61 var instance = binder.createInstance(template, this); 127 var instance = binder.createInstance(template, this);
62 shadow.appendChild(instance.fragment); 128 shadow.appendChild(instance.fragment);
63 this.shadowRootReady(); 129 this.shadowRootReady();
64 } 130 }
65 } 131 }
66 this.attached(); 132 this.attached();
67 this.isAttached = true; 133 this.isAttached = true;
68 } 134 }
69 135
70 detachedCallback() { 136 detachedCallback() {
71 this.detached(); 137 this.detached();
72 this.isAttached = false; 138 this.isAttached = false;
73 } 139 }
74 140
75 attributeChangedCallback(attrName, oldValue, newValue) { 141 attributeChangedCallback(name, oldValue, newValue) {
76 // reserved for canonical behavior 142 this.attributeChanged(name, oldValue, newValue);
77 this.attributeChanged(attrName, oldValue, newValue); 143 var handler = this[name + 'AttributeChanged'];
144 if (typeof handler == 'function')
145 handler.call(this, oldValue, newValue);
146 }
147
148 notifyPropertyChanged(name, oldValue, newValue) {
149 var notifier = Object.getNotifier(this);
150 notifier.notify({
151 type: 'update',
152 name: name,
153 oldValue: oldValue,
154 });
155 var handler = this[name + 'Changed'];
156 if (typeof handler == 'function')
157 handler.call(this, oldValue, newValue);
78 } 158 }
79 }; 159 };
80 160
81 module.exports = SkyElement; 161 module.exports = SkyElement;
82 </script> 162 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698