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                 width: 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 }

 

效果图(点击按钮后):

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

 

你可能感兴趣的:(Sencha Touch)