sencha touch Button Select(点击按钮进行选择)扩展

此扩展基于官方selectfield控件修改而来,变动并不大,使用方法类似。

代码如下:

  1 Ext.define('ux.SelectBtn', {
  2     extend: 'Ext.Button',
  3     xtype: 'selectBtn',
  4     alternateClassName: 'selectBtn',
  5     requires: [
  6         'Ext.Panel',
  7         'Ext.picker.Picker',
  8         'Ext.data.Store',
  9         'Ext.data.StoreManager',
 10         'Ext.dataview.List'
 11     ],
 12     config: {
 13         /**
 14          * @cfg
 15          * @inheritdoc
 16          */
 17         ui: 'select',
 18 
 19 
 20         /**
 21          * @cfg {String/Number} valueField The underlying {@link Ext.data.Field#name data value name} (or numeric Array index) to bind to this
 22          * Select control.
 23          * @accessor
 24          */
 25         valueField: 'value',
 26 
 27         /**
 28          * @cfg {String/Number} displayField The underlying {@link Ext.data.Field#name data value name} (or numeric Array index) to bind to this
 29          * Select control. This resolved value is the visibly rendered value of the available selection options.
 30          * @accessor
 31          */
 32         displayField: 'text',
 33 
 34         /**
 35          * @cfg {Ext.data.Store/Object/String} store The store to provide selection options data.
 36          * Either a Store instance, configuration object or store ID.
 37          * @accessor
 38          */
 39         store: null,
 40 
 41         /**
 42          * @cfg {Array} options An array of select options.
 43          *
 44          *     [
 45          *         {text: 'First Option',  value: 'first'},
 46          *         {text: 'Second Option', value: 'second'},
 47          *         {text: 'Third Option',  value: 'third'}
 48          *     ]
 49          *
 50          * __Note:__ Option object member names should correspond with defined {@link #valueField valueField} and {@link #displayField displayField} values.
 51          * This config will be ignored if a {@link #store store} instance is provided.
 52          * @accessor
 53          */
 54         options: null,
 55 
 56         /**
 57          * @cfg {String} hiddenName Specify a `hiddenName` if you're using the {@link Ext.form.Panel#standardSubmit standardSubmit} option.
 58          * This name will be used to post the underlying value of the select to the server.
 59          * @accessor
 60          */
 61         hiddenName: null,
 62 
 63         /**
 64          * @cfg {Object} component
 65          * @accessor
 66          * @hide
 67          */
 68         component: {
 69             useMask: true
 70         },
 71 
 72 
 73         /**
 74          * @cfg {String/Boolean} usePicker
 75          * `true` if you want this component to always use a {@link Ext.picker.Picker}.
 76          * `false` if you want it to use a popup overlay {@link Ext.List}.
 77          * `auto` if you want to show a {@link Ext.picker.Picker} only on phones.
 78          */
 79         usePicker: 'auto',
 80 
 81         /**
 82          * @cfg {Boolean} autoSelect
 83          * `true` to auto select the first value in the {@link #store} or {@link #options} when they are changed. Only happens when
 84          * the {@link #value} is set to `null`.
 85          */
 86         autoSelect: true,
 87 
 88         /**
 89          * @cfg {Object} defaultPhonePickerConfig
 90          * The default configuration for the picker component when you are on a phone.
 91          */
 92         defaultPhonePickerConfig: null,
 93 
 94         /**
 95          * @cfg {Object} defaultTabletPickerConfig
 96          * The default configuration for the picker component when you are on a tablet.
 97          */
 98         defaultTabletPickerConfig: null,
 99 
100         /**
101          * @cfg
102          * @inheritdoc
103          */
104         name: 'picker',
105 
106         /**
107          * @cfg {String} pickerSlotAlign
108          * The alignment of text in the picker created by this Select
109          * @private
110          */
111         pickerSlotAlign: 'center',
112         value:null
113     },
114 
115     platformConfig: [
116         {
117             theme: ['Windows'],
118             pickerSlotAlign: 'left'
119         },
120         {
121             theme: ['Tizen'],
122             usePicker: false
123         }
124     ],
125 
126     // @private
127     initialize: function () {
128         var me = this;
129         me.callParent();
130         //监听按钮点击事件
131         this.on({
132             scope: me,
133             tap: "showPicker"
134         });
135     },
136 
137     /**
138      * @private
139      */
140     updateDefaultPhonePickerConfig: function (newConfig) {
141         var picker = this.picker;
142         if (picker) {
143             picker.setConfig(newConfig);
144         }
145     },
146 
147     /**
148      * @private
149      */
150     updateDefaultTabletPickerConfig: function (newConfig) {
151         var listPanel = this.listPanel;
152         if (listPanel) {
153             listPanel.setConfig(newConfig);
154         }
155     },
156 
157     /**
158      * @private
159      * Checks if the value is `auto`. If it is, it only uses the picker if the current device type
160      * is a phone.
161      */
162     applyUsePicker: function (usePicker) {
163         if (usePicker == "auto") {
164             usePicker = (Ext.os.deviceType == 'Phone');
165         }
166 
167         return Boolean(usePicker);
168     },
169 
170     /**
171      * @private
172      */
173     applyValue: function (value) {
174         var record = value,
175             index, store;
176 
177         //we call this so that the options configruation gets intiailized, so that a store exists, and we can
178         //find the correct value
179         this.getOptions();
180 
181         store = this.getStore();
182 
183         if ((value != undefined && !value.isModel) && store) {
184             index = store.find(this.getValueField(), value, null, null, null, true);
185 
186             if (index == -1) {
187                 index = store.find(this.getDisplayField(), value, null, null, null, true);
188             }
189 
190             record = store.getAt(index);
191         }
192 
193         return record;
194     },
195 
196     updateValue: function (newValue, oldValue) {
197         this.record = newValue;
198     },
199 
200     getValue: function () {
201         var record = this.record;
202         return (record && record.isModel) ? record.get(this.getValueField()) : null;
203     },
204 
205     /**
206      * Returns the current selected {@link Ext.data.Model record} instance selected in this field.
207      * @return {Ext.data.Model} the record.
208      */
209     getRecord: function () {
210         return this.record;
211     },
212 
213     // @private
214     getPhonePicker: function () {
215         var config = this.getDefaultPhonePickerConfig();
216 
217         if (!this.picker) {
218             this.picker = Ext.create('Ext.picker.Picker', Ext.apply({
219                 slots: [
220                     {
221                         align: this.getPickerSlotAlign(),
222                         name: this.getName(),
223                         valueField: this.getValueField(),
224                         displayField: this.getDisplayField(),
225                         value: this.getValue(),
226                         store: this.getStore()
227                     }
228                 ],
229                 listeners: {
230                     change: this.onPickerChange,
231                     scope: this
232                 }
233             }, config));
234         }
235 
236         return this.picker;
237     },
238 
239     // @private
240     getTabletPicker: function () {
241         var config = this.getDefaultTabletPickerConfig();
242 
243         if (!this.listPanel) {
244             this.listPanel = Ext.create('Ext.Panel', Ext.apply({
245                 left: 0,
246                 top: 0,
247                 modal: true,
248                 cls: Ext.baseCSSPrefix + 'select-overlay',
249                 layout: 'fit',
250                 hideOnMaskTap: true,
251                  Ext.os.is.Phone ? '14em' : '18em',
252                 height: (Ext.os.is.BlackBerry && Ext.os.version.getMajor() === 10) ? '12em' : (Ext.os.is.Phone ? '12.5em' : '22em'),
253                 items: {
254                     xtype: 'list',
255                     store: this.getStore(),
256                     itemTpl: '<span class="x-list-label">{' + this.getDisplayField() + ':htmlEncode}</span>',
257                     listeners: {
258                         select: this.onListSelect,
259                         itemtap: this.onListTap,
260                         scope: this
261                     }
262                 }
263             }, config));
264         }
265 
266         return this.listPanel;
267     },
268 
269     /**
270      * 显示选择器, whether that is a {@link Ext.picker.Picker} or a simple
271      * {@link Ext.List list}.
272      */
273     showPicker: function () {
274         var me = this,
275             store = me.getStore(),
276             value = me.getValue();
277         //check if the store is empty, if it is, return
278         if (!store || store.getCount() === 0) {
279             return;
280         }
281 
282         if (me.getUsePicker()) {
283             var picker = me.getPhonePicker(),
284                 name = me.getName(),
285                 pickerValue = {};
286 
287             pickerValue[name] = value;
288             picker.setValue(pickerValue);
289 
290             if (!picker.getParent()) {
291                 Ext.Viewport.add(picker);
292             }
293 
294             picker.show();
295         } else {
296             var listPanel = me.getTabletPicker(),
297                 list = listPanel.down('list'),
298                 index, record;
299 
300             if (!listPanel.getParent()) {
301                 Ext.Viewport.add(listPanel);
302             }
303             //基于按钮显示
304             listPanel.showBy(me);
305 
306             if (value || me.getAutoSelect()) {
307                 store = list.getStore();
308                 index = store.find(me.getValueField(), value, null, null, null, true);
309                 record = store.getAt(index);
310 
311                 if (record) {
312                     list.select(record, null, true);
313                 }
314             }
315         }
316     },
317 
318     // @private
319     onListSelect: function (item, record) {
320         var me = this;
321         if (record) {
322             me.setValue(record);
323             //选择成功触发事件
324             this.fireEvent('selecSuccess', this, this.getValue(), record);
325         }
326     },
327 
328     onListTap: function () {
329         this.listPanel.hide({
330             type: 'fade',
331             out: true,
332             scope: this
333         });
334     },
335 
336     // @private
337     onPickerChange: function (picker, value) {
338         var me = this,
339             newValue = value[me.getName()],
340             store = me.getStore(),
341             index = store.find(me.getValueField(), newValue, null, null, null, true),
342             record = store.getAt(index);
343 
344         me.setValue(record);
345         //选择成功触发事件
346         this.fireEvent('selecSuccess', this, this.getValue(), record);
347     },
348 
349     onChange: function (component, newValue, oldValue) {
350         var me = this,
351             store = me.getStore(),
352             index = (store) ? store.find(me.getDisplayField(), oldValue, null, null, null, true) : -1,
353             valueField = me.getValueField(),
354             record = (store) ? store.getAt(index) : null;
355 
356         oldValue = (record) ? record.get(valueField) : null;
357 
358         me.fireEvent('change', me, me.getValue(), oldValue);
359     },
360 
361     /**
362      * Updates the underlying `<options>` list with new values.
363      *
364      * @param {Array} newOptions An array of options configurations to insert or append.
365      *
366      *     selectBox.setOptions([
367      *         {text: 'First Option',  value: 'first'},
368      *         {text: 'Second Option', value: 'second'},
369      *         {text: 'Third Option',  value: 'third'}
370      *     ]).setValue('third');
371      *
372      * __Note:__ option object member names should correspond with defined {@link #valueField valueField} and
373      * {@link #displayField displayField} values.
374      *
375      * @return {Ext.field.Select} this
376      */
377     updateOptions: function (newOptions) {
378         var store = this.getStore();
379 
380         if (!store) {
381             this.setStore(true);
382             store = this._store;
383         }
384 
385         if (!newOptions) {
386             store.clearData();
387         }
388         else {
389             store.setData(newOptions);
390             this.onStoreDataChanged(store);
391         }
392         return this;
393     },
394 
395     applyStore: function (store) {
396         if (store === true) {
397             store = Ext.create('Ext.data.Store', {
398                 fields: [this.getValueField(), this.getDisplayField()],
399                 autoDestroy: true
400             });
401         }
402 
403         if (store) {
404             store = Ext.data.StoreManager.lookup(store);
405 
406             store.on({
407                 scope: this,
408                 addrecords: 'onStoreDataChanged',
409                 removerecords: 'onStoreDataChanged',
410                 updaterecord: 'onStoreDataChanged',
411                 refresh: 'onStoreDataChanged'
412             });
413         }
414 
415         return store;
416     },
417 
418     updateStore: function (newStore) {
419         if (newStore) {
420             this.onStoreDataChanged(newStore);
421         }
422 
423         if (this.getUsePicker() && this.picker) {
424             this.picker.down('pickerslot').setStore(newStore);
425         } else if (this.listPanel) {
426             this.listPanel.down('dataview').setStore(newStore);
427         }
428     },
429 
430     /**
431      * Called when the internal {@link #store}'s data has changed.
432      */
433     onStoreDataChanged: function (store) {
434         var initialConfig = this.getInitialConfig(),
435             value = this.getValue();
436 
437         if (value || value == 0) {
438             this.updateValue(this.applyValue(value));
439         }
440 
441         if (this.getValue() === null) {
442             if (initialConfig.hasOwnProperty('value')) {
443                 this.setValue(initialConfig.value);
444             }
445 
446             if (this.getValue() === null && this.getAutoSelect()) {
447                 if (store.getCount() > 0) {
448                     this.setRecord(store.getAt(0));
449                 }
450             }
451         }
452     },
453 
454     /**
455      * Resets the Select field to the value of the first record in the store.
456      * @return {Ext.field.Select} this
457      * @chainable
458      */
459     reset: function () {
460         var store = this.getStore(),
461             record = (this.originalValue) ? this.originalValue : store.getAt(0);
462 
463         if (store && record) {
464             this.setValue(record);
465         }
466 
467         return this;
468     },
469 
470     destroy: function () {
471         this.callParent(arguments);
472         var store = this.getStore();
473 
474         if (store && store.getAutoDestroy()) {
475             Ext.destroy(store);
476         }
477 
478         Ext.destroy(this.listPanel, this.picker);
479     }
480 });

使用示例

引用:

    requires: ['ux.SelectBtn'],

使用(可以参考官方selectfield控件用法):

 1 {
 2                 xtype: 'selectBtn',
 3                 text: '分享',
 4                 align: 'right',
 5                 ui: 'decline',
 6                 valueField: 'name',
 7                 displayField: 'name',
 8                 action:'share',
 9                 store: 'shareList'
10 }

控制层监听

引用:

1 refs: {
2             shareBtn: 'button[action=share]'
3         }

监听(选择成功):

1 control: {
2             shareBtn: {
3                 selecSuccess: function (t, value, record) {
4                     console.log(value,record);
5                 }
6             }
7 }

效果图(点击按钮后):

 

原文地址:https://www.cnblogs.com/mlzs/p/3560234.html