aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/ui/native-control.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/montage/ui/native-control.js')
-rw-r--r--node_modules/montage/ui/native-control.js175
1 files changed, 94 insertions, 81 deletions
diff --git a/node_modules/montage/ui/native-control.js b/node_modules/montage/ui/native-control.js
index d3c3a635..d308ad89 100644
--- a/node_modules/montage/ui/native-control.js
+++ b/node_modules/montage/ui/native-control.js
@@ -11,48 +11,31 @@ var isUndefined = function(obj) {
11 return (typeof obj === 'undefined'); 11 return (typeof obj === 'undefined');
12}; 12};
13 13
14var extend = function(destination, source) {
15 for (var property in source) {
16 destination[property] = source[property];
17 }
18 return destination;
19};
20
21var STRING_CLASS = '[object String]';
22var _toString = Object.prototype.toString;
23var isString = function(object) {
24 return _toString.call(object) === STRING_CLASS;
25};
26 14
27/** 15/**
28 * Base component for all native controls. 16 * Base component for all native controls.
29 */ 17 */
30exports.NativeControl = Montage.create(Component, { 18var NativeControl = exports.NativeControl = Montage.create(Component, {
31 19
32 hasTemplate: { 20 hasTemplate: {
33 value: false 21 value: false
34 }, 22 },
35 23
36 //http://www.w3.org/TR/html5/elements.html#global-attributes 24 element: {
37 _baseElementProperties: { 25 serializable: true,
38 value: { 26 enumerable: true,
39 accesskey: null, 27 get: function() {
40 contenteditable: null, // true, false, inherit 28 return this._element;
41 contextmenu: null, 29 },
42 'class': null, 30 set: function(value) {
43 dir: null, 31 //var component = Object.getPrototypeOf(NativeControl);
44 draggable: {dataType: 'boolean'}, 32 // call super set
45 dropzone: null, // copy/move/link 33 Object.getPropertyDescriptor(Component, "element").set.call(this, value);
46 hidden: {dataType: 'boolean'}, 34 this.didSetElement();
47 //id: null,
48 lang: null,
49 spellcheck: null,
50 style: null,
51 tabindex: null,
52 title: null
53 } 35 }
54 }, 36 },
55 37
38
56 /** Stores values that need to be set on the element. Cleared each draw 39 /** Stores values that need to be set on the element. Cleared each draw
57 * cycle. 40 * cycle.
58 */ 41 */
@@ -64,11 +47,30 @@ exports.NativeControl = Montage.create(Component, {
64 /** Stores the descriptors of the properties that can be set on this 47 /** Stores the descriptors of the properties that can be set on this
65 * control 48 * control
66 */ 49 */
67 _propertyDescriptors: { 50
51 _elementAttributeDescriptors: {
68 value: {}, 52 value: {},
69 distinct: true 53 distinct: true
70 }, 54 },
71 55
56
57 _getElementAttributeDescriptor: {
58 value: function(attributeName) {
59 var attributeDescriptor, instance = this;
60 // walk up the prototype chain from the instance to NativeControl's prototype
61 while(instance && !isUndefined(instance._elementAttributeDescriptors)) {
62 attributeDescriptor = instance._elementAttributeDescriptors[attributeName];
63 if(attributeDescriptor) {
64 break;
65 } else {
66 instance = Object.getPrototypeOf(instance);
67 }
68 }
69
70 return attributeDescriptor;
71 }
72 },
73
72 /** 74 /**
73 * Add a property to this Component. A default getter/setter is provided and a 75 * Add a property to this Component. A default getter/setter is provided and a
74 * "_" property is created by default. Eg: if the property is "title", "_title" is 76 * "_" property is created by default. Eg: if the property is "title", "_title" is
@@ -86,7 +88,8 @@ exports.NativeControl = Montage.create(Component, {
86 return function(value) { 88 return function(value) {
87 var attrName = '_' + name; 89 var attrName = '_' + name;
88 90
89 var desc = this._propertyDescriptors[name]; 91 var desc = this._getElementAttributeDescriptor(name, this);
92
90 // if requested dataType is boolean (eg: checked, readonly etc) 93 // if requested dataType is boolean (eg: checked, readonly etc)
91 // coerce the value to boolean 94 // coerce the value to boolean
92 if(desc && "boolean" === desc.dataType) { 95 if(desc && "boolean" === desc.dataType) {
@@ -121,64 +124,56 @@ exports.NativeControl = Montage.create(Component, {
121 * Add the specified properties as properties of this Component 124 * Add the specified properties as properties of this Component
122 */ 125 */
123 addAttributes: { 126 addAttributes: {
124 value: function(props) { 127 value: function(properties) {
125 var i, desc, prop, obj; 128 var i, descriptor, property, object;
126 var standardAttributes = {}; 129 this._elementAttributeDescriptors = properties;
127 standardAttributes = extend(standardAttributes, this._baseElementProperties);
128 standardAttributes = extend(standardAttributes, props);
129
130 this._propertyDescriptors = standardAttributes;
131 130
132 for(prop in standardAttributes) { 131 for(property in properties) {
133 if(standardAttributes.hasOwnProperty(prop)) { 132 if(properties.hasOwnProperty(property)) {
134 obj = standardAttributes[prop]; 133 object = properties[property];
135 // Make sure that the descriptor is of the correct form. 134 // Make sure that the descriptor is of the correct form.
136 if(obj === null || isString(obj)) { 135 if(object === null || String.isString(object)) {
137 desc = {value: obj, dataType: "string"}; 136 descriptor = {value: object, dataType: "string"};
138 standardAttributes[prop] = desc; 137 properties[property] = descriptor;
139 } else { 138 } else {
140 desc = obj; 139 descriptor = object;
141 } 140 }
142 141
143 // Only add the internal prop, and getter and setter if 142 // Only add the internal property, and getter and setter if
144 // they don't already exist. 143 // they don't already exist.
145 if(isUndefined(this[prop])) { 144 if(isUndefined(this[property])) {
146 this.defineAttribute(prop, desc); 145 this.defineAttribute(property, descriptor);
147 } 146 }
148 } 147 }
149 } 148 }
150 } 149 }
151 }, 150 },
152 151
153 deserializedFromTemplate: { 152 didSetElement: {
154 value: function() { 153 value: function() {
155 // The element is now ready, so we can read the attributes that 154 // The element is now ready, so we can read the attributes that
156 // have been set on it. 155 // have been set on it.
157 var attrs = this.element.attributes || []; 156 var attributes = this.element.attributes || [];
158 var i=0, len = attrs.length, name, value, d, desc; 157 var i=0, length = attributes.length, name, value, attributeName, descriptor, textContent;
159 158
160 for(i=0; i< len; i++) { 159 for(i=0; i< length; i++) {
161 name = attrs[i].name; 160 name = attributes[i].name;
162 value = attrs[i].value; 161 value = attributes[i].value;
163 162
164 if(isUndefined(this._elementAttributeValues[name])) { 163 if(isUndefined(this._elementAttributeValues[name])) {
165 this._elementAttributeValues[name] = value; 164 this._elementAttributeValues[name] = value;
166 // since deserializedFromTemplate is called *after* the initial binding 165 if(isUndefined(this[name]) || this[name] == null) {
167 // is done, override the values only if a value does not already exist
168 if(isUndefined(this[name]) || this[name] === null) {
169 this[name] = value; 166 this[name] = value;
170 } 167 }
171 } 168 }
172 } 169 }
173 170
174 // check if this element has textContent 171 // check if this element has textContent
175 var textContent = this.element.textContent; 172 textContent = this.element.textContent;
176 // set textContent only if it is defined as part of element properties 173 // set textContent only if it is defined as part of element properties
177 if(('textContent' in this) && textContent && ("" !== textContent)) { 174 if(('textContent' in this) && textContent && ("" !== textContent)) {
178 if(isUndefined(this._elementAttributeValues['textContent'])) { 175 if(isUndefined(this._elementAttributeValues['textContent'])) {
179 this._elementAttributeValues['textContent'] = textContent; 176 this._elementAttributeValues['textContent'] = textContent;
180 // since deserializedFromTemplate is called *after* the initial binding
181 // is done, override the values only if a value does not already exist
182 if(isUndefined(this['textContent']) || this['textContent'] === null) { 177 if(isUndefined(this['textContent']) || this['textContent'] === null) {
183 this['textContent'] = textContent; 178 this['textContent'] = textContent;
184 } 179 }
@@ -187,10 +182,10 @@ exports.NativeControl = Montage.create(Component, {
187 182
188 // Set defaults for any properties that weren't serialised or set 183 // Set defaults for any properties that weren't serialised or set
189 // as attributes on the element. 184 // as attributes on the element.
190 for (d in this._propertyDescriptors) { 185 for (attributeName in this._elementAttr