]> git.proxmox.com Git - extjs.git/blame - extjs/modern/modern/src/picker/Slot.js
add extjs 6.0.1 sources
[extjs.git] / extjs / modern / modern / src / picker / Slot.js
CommitLineData
6527f429
DM
1/**\r
2 * @private\r
3 *\r
4 * A general {@link Ext.picker.Picker} slot class. Slots are used to organize multiple scrollable slots into\r
5 * a single {@link Ext.picker.Picker}.\r
6 *\r
7 * {\r
8 * name : 'limit_speed',\r
9 * title: 'Speed Limit',\r
10 * data : [\r
11 * {text: '50 KB/s', value: 50},\r
12 * {text: '100 KB/s', value: 100},\r
13 * {text: '200 KB/s', value: 200},\r
14 * {text: '300 KB/s', value: 300}\r
15 * ]\r
16 * }\r
17 *\r
18 * See the {@link Ext.picker.Picker} documentation on how to use slots.\r
19 */\r
20Ext.define('Ext.picker.Slot', {\r
21 extend: 'Ext.dataview.DataView',\r
22 xtype: 'pickerslot',\r
23 \r
24 requires: [\r
25 'Ext.XTemplate',\r
26 'Ext.data.Store',\r
27 'Ext.Component',\r
28 'Ext.data.StoreManager'\r
29 ],\r
30\r
31 /**\r
32 * @event slotpick\r
33 * Fires whenever an slot is picked\r
34 * @param {Ext.picker.Slot} this\r
35 * @param {Mixed} value The value of the pick\r
36 * @param {HTMLElement} node The node element of the pick\r
37 */\r
38\r
39 isSlot: true,\r
40\r
41 config: {\r
42 /**\r
43 * @cfg {String} title The title to use for this slot, or `null` for no title.\r
44 * @accessor\r
45 */\r
46 title: null,\r
47\r
48 /**\r
49 * @private\r
50 * @cfg {Boolean} showTitle\r
51 * @accessor\r
52 */\r
53 showTitle: true,\r
54\r
55 /**\r
56 * @private\r
57 * @cfg {String} cls The main component class\r
58 * @accessor\r
59 */\r
60 cls: Ext.baseCSSPrefix + 'picker-slot',\r
61\r
62 /**\r
63 * @cfg {String} name (required) The name of this slot.\r
64 * @accessor\r
65 */\r
66 name: null,\r
67\r
68 /**\r
69 * @cfg {Number} value The value of this slot\r
70 * @accessor\r
71 */\r
72 value: null,\r
73\r
74 /**\r
75 * @cfg {Number} flex\r
76 * @accessor\r
77 * @private\r
78 */\r
79 flex: 1,\r
80\r
81 /**\r
82 * @cfg {String} align The horizontal alignment of the slot's contents.\r
83 *\r
84 * Valid values are: "left", "center", and "right".\r
85 * @accessor\r
86 */\r
87 align: 'left',\r
88\r
89 /**\r
90 * @cfg {String} displayField The display field in the store.\r
91 * @accessor\r
92 */\r
93 displayField: 'text',\r
94\r
95 /**\r
96 * @cfg {String} valueField The value field in the store.\r
97 * @accessor\r
98 */\r
99 valueField: 'value',\r
100\r
101 /**\r
102 * @cfg {String} itemTpl The template to be used in this slot.\r
103 * If you set this, {@link #displayField} will be ignored.\r
104 */\r
105 itemTpl: null,\r
106\r
107 /**\r
108 * @cfg {Object} scrollable\r
109 * @accessor\r
110 * @hide\r
111 */\r
112 scrollable: {\r
113 x: false,\r
114 indicators: false,\r
115 momentumEasing: {\r
116 minVelocity: 2\r
117 },\r
118 slotSnapEasing: {\r
119 duration: 100\r
120 }\r
121 },\r
122\r
123 /**\r
124 * @cfg {Boolean} verticallyCenterItems\r
125 * @private\r
126 */\r
127 verticallyCenterItems: true\r
128 },\r
129\r
130 constructor: function() {\r
131 /**\r
132 * @property selectedIndex\r
133 * @type Number\r
134 * The current `selectedIndex` of the picker slot.\r
135 * @private\r
136 */\r
137 this.selectedIndex = 0;\r
138\r
139 /**\r
140 * @property picker\r
141 * @type Ext.picker.Picker\r
142 * A reference to the owner Picker.\r
143 * @private\r
144 */\r
145\r
146 this.callParent(arguments);\r
147 },\r
148\r
149 /**\r
150 * Sets the title for this dataview by creating element.\r
151 * @param {String} title\r
152 * @return {String}\r
153 */\r
154 applyTitle: function(title) {\r
155 //check if the title isnt defined\r
156 if (title) {\r
157 //create a new title element\r
158 title = Ext.create('Ext.Component', {\r
159 cls: Ext.baseCSSPrefix + 'picker-slot-title',\r
160 docked: 'top',\r
161 html: title\r
162 });\r
163 }\r
164\r
165 return title;\r
166 },\r
167\r
168 updateTitle: function(newTitle, oldTitle) {\r
169 if (newTitle) {\r
170 this.add(newTitle);\r
171 this.setupBar();\r
172 }\r
173\r
174 if (oldTitle) {\r
175 this.remove(oldTitle);\r
176 }\r
177 },\r
178\r
179 updateShowTitle: function(showTitle) {\r
180 var title = this.getTitle(),\r
181 mode = showTitle ? 'show' : 'hide';\r
182 if (title) {\r
183 title.on(mode, this.setupBar, this, { single: true, delay: 50 });\r
184 title[showTitle ? 'show' : 'hide']();\r
185 }\r
186 },\r
187\r
188 updateDisplayField: function(newDisplayField) {\r
189 if (!this.config.itemTpl) {\r
190 this.setItemTpl('<div class="' + Ext.baseCSSPrefix + 'picker-item {cls} <tpl if="extra">' + Ext.baseCSSPrefix + 'picker-invalid</tpl>">{' + newDisplayField + '}</div>');\r
191 }\r
192 },\r
193\r
194 /**\r
195 * Updates the {@link #align} configuration\r
196 */\r
197 updateAlign: function(newAlign, oldAlign) {\r
198 var element = this.element;\r
199 element.addCls(Ext.baseCSSPrefix + 'picker-' + newAlign);\r
200 element.removeCls(Ext.baseCSSPrefix + 'picker-' + oldAlign);\r
201 },\r
202\r
203 /**\r
204 * Looks at the {@link #data} configuration and turns it into {@link #store}.\r
205 * @param {Object} data\r
206 * @return {Object}\r
207 */\r
208 applyData: function(data) {\r
209 var parsedData = [],\r
210 ln = data && data.length,\r
211 i, item, obj;\r
212\r
213 if (data && Ext.isArray(data) && ln) {\r
214 for (i = 0; i < ln; i++) {\r
215 item = data[i];\r
216 obj = {};\r
217 if (Ext.isArray(item)) {\r
218 obj[this.valueField] = item[0];\r
219 obj[this.displayField] = item[1];\r
220 }\r
221 else if (Ext.isString(item)) {\r
222 obj[this.valueField] = item;\r
223 obj[this.displayField] = item;\r
224 }\r
225 else if (Ext.isObject(item)) {\r
226 obj = item;\r
227 }\r
228 parsedData.push(obj);\r
229 }\r
230 }\r
231\r
232 return data;\r
233 },\r
234\r
235 /**\r
236 * @private\r
237 */\r
238 initialize: function() {\r
239 this.callParent();\r
240\r
241 var scroller = this.getScrollable();\r
242\r
243 this.on({\r
244 scope: this,\r
245 painted: 'onPainted',\r
246 itemtap: 'doItemTap'\r
247 });\r
248\r
249 this.element.on({\r
250 scope: this,\r
251 touchstart: 'onTouchStart',\r
252 touchend: 'onTouchEnd'\r
253 });\r
254\r
255 scroller.on({\r
256 scope: this,\r
257 scrollend: 'onScrollEnd'\r
258 });\r
259 },\r
260\r
261 /**\r
262 * @private\r
263 */\r
264 onPainted: function() {\r
265 this.setupBar();\r
266 },\r
267\r
268 /**\r
269 * Returns an instance of the owner picker.\r
270 * @return {Object}\r
271 * @private\r
272 */\r
273 getPicker: function() {\r
274 if (!this.picker) {\r
275 this.picker = this.getParent();\r
276 }\r
277\r
278 return this.picker;\r
279 },\r
280\r
281 /**\r
282 * @private\r
283 */\r
284 setupBar: function() {\r
285 if (!this.rendered) {\r
286 //if the component isnt rendered yet, there is no point in calculating the padding just eyt\r
287 return;\r
288 }\r
289\r
290 var element = this.element,\r
291 containerElement = this.container.element,\r
292 picker = this.getPicker(),\r
293 bar = picker.bar,\r
294 value = this.getValue(),\r
295 showTitle = this.getShowTitle(),\r
296 title = this.getTitle(),\r
297 scroller = this.getScrollable(),\r
298 titleHeight = 0,\r
299 barHeight, padding;\r
300\r
301 barHeight = bar.dom.getBoundingClientRect().height;\r
302\r
303 if (showTitle && title) {\r
304 titleHeight = title.element.getHeight();\r
305 }\r
306\r
307 padding = Math.ceil((element.getHeight() - titleHeight - barHeight) / 2);\r
308\r
309 if (this.getVerticallyCenterItems()) {\r
310 containerElement.setStyle({\r
311 padding: padding + 'px 0 ' + padding + 'px'\r
312 });\r
313 }\r
314\r
315 scroller.refresh();\r
316 scroller.setSlotSnapSize(barHeight);\r
317 this.setValue(value);\r
318 },\r
319\r
320 /**\r
321 * @private\r
322 */\r
323 doItemTap: function(list, index, item, e) {\r
324 var me = this;\r
325 me.selectedIndex = index;\r
326 me.selectedNode = item;\r
327 me.scrollToItem(item, true);\r
328 },\r
329\r
330 /**\r
331 * @private\r
332 */\r
333 scrollToItem: function(item, animated) {\r
334 var y = item.getY(),\r
335 parentEl = item.parent(),\r
336 parentY = parentEl.getY(),\r
337 scroller = this.getScrollable(),\r
338 difference;\r
339\r
340 difference = y - parentY;\r
341\r
342 scroller.scrollTo(0, difference, animated);\r
343 },\r
344\r
345 /**\r
346 * @private\r
347 */\r
348 onTouchStart: function() {\r
349 this.element.addCls(Ext.baseCSSPrefix + 'scrolling');\r
350 },\r
351\r
352 /**\r
353 * @private\r
354 */\r
355 onTouchEnd: function() {\r
356 this.element.removeCls(Ext.baseCSSPrefix + 'scrolling');\r
357 },\r
358\r
359 /**\r
360 * @private\r
361 */\r
362 onScrollEnd: function(scroller, x, y) {\r
363 var me = this,\r
364 index = Math.round(y / me.picker.bar.dom.getBoundingClientRect().height),\r
365 viewItems = me.getViewItems(),\r
366 item = viewItems[index];\r
367\r
368 if (item) {\r
369 me.selectedIndex = index;\r
370 me.selectedNode = item;\r
371\r
372 me.fireEvent('slotpick', me, me.getValue(), me.selectedNode);\r
373 }\r
374 },\r
375\r
376 /**\r
377 * Returns the value of this slot\r
378 * @private\r
379 */\r
380 getValue: function(useDom) {\r
381 var store = this.getStore(),\r
382 record, value;\r
383\r
384 if (!store) {\r
385 return;\r
386 }\r
387\r
388 if (!this.rendered || !useDom) {\r
389 return this._value;\r
390 }\r
391\r
392 //if the value is ever false, that means we do not want to return anything\r
393 if (this._value === false) {\r
394 return null;\r
395 }\r
396\r
397 record = store.getAt(this.selectedIndex);\r
398\r
399 value = record ? record.get(this.getValueField()) : null;\r
400\r
401 return value;\r
402 },\r
403\r
404 /**\r
405 * Sets the value of this slot\r
406 * @private\r
407 */\r
408 setValue: function(value) {\r
409 return this.doSetValue(value);\r
410 },\r
411\r
412 /**\r
413 * Sets the value of this slot\r
414 * @private\r
415 */\r
416 setValueAnimated: function(value) {\r
417 return this.doSetValue(value, true);\r
418 },\r
419\r
420 doSetValue: function(value, animated) {\r
421 if (!this.rendered) {\r
422 //we don't want to call this until the slot has been rendered\r
423 this._value = value;\r
424 return;\r
425 }\r
426\r
427 var store = this.getStore(),\r
428 viewItems = this.getViewItems(),\r
429 valueField = this.getValueField(),\r
430 index, item;\r
431\r
432 index = store.findExact(valueField, value);\r
433\r
434 if (index == -1) {\r
435 index = 0;\r
436 }\r
437\r
438 item = Ext.get(viewItems[index]);\r
439\r
440 this.selectedIndex = index;\r
441 if (item) {\r
442 this.scrollToItem(item, (animated) ? {\r
443 duration: 100\r
444 } : false);\r
445 this.select(this.selectedIndex);\r
446 }\r
447\r
448 this._value = value;\r
449 }\r
450});\r