diff options
Diffstat (limited to 'node_modules/montage/ui/select-input.reel')
-rw-r--r-- | node_modules/montage/ui/select-input.reel/select-input.js | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/node_modules/montage/ui/select-input.reel/select-input.js b/node_modules/montage/ui/select-input.reel/select-input.js new file mode 100644 index 00000000..76de1a5a --- /dev/null +++ b/node_modules/montage/ui/select-input.reel/select-input.js | |||
@@ -0,0 +1,320 @@ | |||
1 | /* <copyright> | ||
2 | This file contains proprietary software owned by Motorola Mobility, Inc.<br/> | ||
3 | No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> | ||
4 | (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. | ||
5 | </copyright> */ | ||
6 | |||
7 | var Montage = require("montage").Montage, | ||
8 | Component = require("ui/component").Component, | ||
9 | ArrayController = require("ui/controller/array-controller").ArrayController, | ||
10 | NativeControl = require("ui/native-control").NativeControl; | ||
11 | |||
12 | var STRING_CLASS = '[object String]'; | ||
13 | var _toString = Object.prototype.toString; | ||
14 | |||
15 | var isString = function(object) { | ||
16 | return _toString.call(object) === STRING_CLASS; | ||
17 | }; | ||
18 | |||
19 | var SelectInput = exports.SelectInput = Montage.create(NativeControl, { | ||
20 | |||
21 | _fromInput: {value: null}, | ||
22 | |||
23 | __selectedIndexes: {value: null, enumerable: false}, | ||
24 | _selectedIndexes: { | ||
25 | set: function(value) { | ||
26 | this.__selectedIndexes = value; | ||
27 | if(!this._fromInput) { | ||
28 | this.needsDraw = true; | ||
29 | } else { | ||
30 | this._fromInput = false; | ||
31 | } | ||
32 | }, | ||
33 | get: function() { | ||
34 | return this.__selectedIndexes; | ||
35 | } | ||
36 | }, | ||
37 | |||
38 | //----------------------- | ||
39 | // Public API | ||
40 | //----------------------- | ||
41 | |||
42 | _content: {value: null, enumerable: false}, | ||
43 | content: { | ||
44 | set: function(value) { | ||
45 | if(!Array.isArray(value)) { | ||
46 | value = [value]; | ||
47 | } | ||
48 | this._content = value; | ||
49 | |||
50 | if(!this.contentController) { | ||
51 | var contentController = ArrayController.create(); | ||
52 | contentController.content = value; | ||
53 | this.contentController = contentController; | ||
54 | } | ||
55 | |||
56 | this.needsDraw = true; | ||
57 | }, | ||
58 | get: function() { | ||
59 | return this._content; | ||
60 | } | ||
61 | }, | ||
62 | |||
63 | // If contentController is provided, this allows the developer to specify | ||
64 | // which property in each element provides the "value" part of <option> | ||
65 | valuePropertyPath: {value: null}, | ||
66 | // Property on iterated object from which textContent of the <option> | ||
67 | // is received | ||
68 | textPropertyPath: {value: null}, | ||
69 | |||
70 | |||
71 | _contentController: {value: null, enumerable: false}, | ||
72 | contentController: { | ||
73 | get: function() { | ||
74 | return this._contentController; | ||
75 | }, | ||
76 | set: function(value) { | ||
77 | if (this._contentController === value) { | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | if (this._contentController) { | ||
82 | Object.deleteBinding(this, "_selectedIndexes"); | ||
83 | } | ||
84 | |||
85 | this._contentController = value; | ||
86 | |||
87 | if (this._contentController) { | ||
88 | |||
89 | // If we're already getting contentController related values from other bindings...stop that | ||
90 | if (this._bindingDescriptors) { | ||
91 | Object.deleteBinding(this, "content"); | ||
92 | } | ||
93 | |||
94 | Object.defineBinding(this, "content", { | ||
95 | boundObject: this._contentController, | ||
96 | boundObjectPropertyPath: "organizedObjects", | ||
97 | oneway: true | ||
98 | }); | ||
99 | |||
100 | |||
101 | Object.defineBinding(this, "_selectedIndexes", { | ||
102 | boundObject: this._contentController, | ||
103 | boundObjectPropertyPath: "selectedIndexes" | ||
104 | }); | ||
105 | } | ||
106 | |||
107 | } | ||
108 | }, | ||
109 | |||
110 | // ------------------- | ||
111 | // Montage Callbacks | ||
112 | // -------------------- | ||
113 | |||
114 | _addOptionsFromMarkup: { | ||
115 | value: function() { | ||
116 | |||
117 | var el = this.element, options = el.querySelectorAll('option'); | ||
118 | // @todo: if contentController is provided, should we just ignore the <option> | ||
119 | // from the markup ? | ||
120 | |||
121 | // create a new Arraycontroller if one is not provided | ||
122 | // add options to contentController | ||
123 | // look for selected options in the markup and mark these as selected | ||
124 | if(!this.contentController) { | ||
125 | var contentController = ArrayController.create(); | ||
126 | var selectedIndexes = []; | ||
127 | |||
128 | contentController.content = []; | ||
129 | if(options && options.length > 0) { | ||
130 | var i=0, len = options.length, selected; | ||
131 | for(; i< len; i++) { | ||
132 | selected = options[i].getAttribute('selected'); | ||
133 | if(selected) { | ||
134 | selectedIndexes.push(i); | ||
135 | } | ||
136 | contentController.addObjects({ | ||
137 | value: options[i].value, | ||
138 | text: options[i].textContent | ||
139 | }); | ||
140 | } | ||
141 | |||
142 | this.contentController = contentController; | ||
143 | |||
144 | if(selectedIndexes.length > 0) { | ||
145 | this._fromInput = true; | ||
146 | this.contentController.selectedIndexes = selectedIndexes; | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | |||
151 | } | ||
152 | }, | ||
153 | |||
154 | |||
155 | deserializedFromTemplate: { | ||
156 | value: function() { | ||
157 | // @todo - Need a better way to do this. | ||
158 | var fn = Object.getPrototypeOf(SelectInput).deserializedFromTemplate; | ||
159 | fn.call(this); | ||
160 | |||
161 | /* | ||
162 | 1) If <option> is provided in the markup but contentController is not, | ||
163 | fill the contentController with the options from the markup | ||
164 | 2) If contentController is present, options from markup will be overwritten | ||
165 | by the values from contentController when they are available | ||
166 | */ | ||
167 | this._addOptionsFromMarkup(); | ||
168 | } | ||
169 | }, | ||
170 | |||
171 | /** | ||
172 | Description TODO | ||
173 | @function | ||
174 | */ | ||
175 | prepareForDraw: { | ||
176 | enumerable: false, | ||
177 | value: function() { | ||
178 | var el = this.element; | ||
179 | el.addEventListener("focus", this); | ||
180 | el.addEventListener('change', this); | ||
181 | } | ||
182 | }, | ||
183 | |||
184 | _removeAll: { | ||
185 | value: function(elem) { | ||
186 | // remove all existing options | ||
187 | while (elem.firstChild ) { | ||
188 | elem.removeChild( elem.firstChild ); | ||
189 | } | ||
190 | } | ||
191 | }, | ||
192 | |||
193 | _refreshOptions: { | ||
194 | value: function() { | ||
195 | console.log('==== refreshOptions ===='); | ||
196 | var arr = this.content||[], len = arr.length, i, option; | ||
197 | var text, value; | ||
198 | for(i=0; i< len; i++) { | ||
199 | option = document.createElement('option'); | ||
200 | if(isString(arr[i])) { | ||
201 | text = value = arr[i]; | ||
202 | } else { | ||
203 | text = arr[i][this.textPropertyPath || 'text']; | ||
204 | value = arr[i][this.valuePropertyPath || 'value']; | ||
205 | } | ||
206 | |||
207 | option.value = value; | ||
208 | option.textContent = text || value; | ||
209 | |||
210 | if(this._selectedIndexes && this._selectedIndexes.length > 0) { | ||
211 | if(this._selectedIndexes.indexOf(i) >= 0) { | ||
212 | option.setAttribute("selected", "true"); | ||
213 | } | ||
214 | } | ||
215 | this.element |