В данном примере я покажу как создать DataView вместо стандартного Ext.menu.Menu на примере обычной кнопки. Это просто концепт, так что принимайте как есть 🙂
Ext.define('app.view.toolbar.cmp.application.Button', { extend: 'Ext.button.Button', requires: [ 'app.view.toolbar.cmp.application.DataView' ], initComponent: function () { this.on('click', this.showDataView, this); this.callParent(); }, showDataView: function (button, e, eOpt) { var dataView = this.getApplicationDataView(), isPointerEvent = !e || e.pointerType; if (dataView && this.rendered) { if (this.tooltip && Ext.quickTipsActive && this.getTipAttr() !== 'title') { Ext.tip.QuickTipManager.getQuickTip().cancelShow(this.el); } if (dataView.isVisible()) { if (isPointerEvent) { dataView.hide(); } else { dataView.focus(); } } else if (!e || this.showEmptyMenu || dataView.getStore().getCount() > 0) { dataView.autoFocus = !isPointerEvent; dataView.showBy(this.el, this.menuAlign); dataView.show(); } } return this; }, getApplicationDataView: function () { if (!this.applicationDataView) { var dataViewConfig = Ext.apply({ items: this.items, hidden: true, listeners: { 'iconItemClick': { fn: this.onIconItemClick, scope: this } }, }, this.dataViewConfig); this.applicationDataView = Ext.create('app.view.toolbar.cmp.application.DataView', dataViewConfig); } return this.applicationDataView; }, onIconItemClick: function(record, item) { this.fireEvent('iconitemclick', this, record, item); }, handler: Ext.emptyFn });
Ext.define('app.view.toolbar.cmp.application.DataView', { extend: 'Ext.view.View', floating: true, numbderOfColumns: 3, scrollable: true, cls: Ext.baseCSSPrefix + 'panel-body-default', itemSelector: 'div.thumb-wrap', initComponent: function () { this.tpl = this.createXTempalte(); this.store = this.createStore(); this.initEvents(); this.callParent(); }, initEvents: function() { this.on('itemclick', this.onIconItemClick, this); this.on('blur', this.onBlur, this); }, onIconItemClick: function(dataView, record, item, index, e, eOpt) { this.fireEvent('iconItemClick', record, item); this.hide(); e.stopEvent(); }, onBlur: function(cmp, e, eOpt) { this.hide(); }, createXTempalte: function() { var me = this; var xTemplate = new Ext.XTemplate( '<table>', '<tpl for=".">', '<tpl if="this.showOpenTr(xindex)">', '<tr>', '</tpl>', '<td style="padding: 10px; text-align: center;" >', '<div style="cursor: pointer;" class="thumb-wrap">', '<span style="font-family: {fontFamily}; font-size: {iconSize}; color: {iconColor}">&#{uniCode};</span>', '<br/><span style="">{text}</span>', '</div>', '</td>', '<tpl if="this.showCloseTr(xindex, xcount)">', '</tr>', '</tpl>', '</tpl>', '</table>', { showOpenTr: function(xIndex) { return xIndex === 0 && xIndex % me.numbderOfColumns === 0; }, showCloseTr: function(xIndex, xCount) { return xIndex === xCount || xIndex % me.numbderOfColumns === 0; } } ); return xTemplate; }, createStore: function () { var store = Ext.create('Ext.data.Store', { fields: [ 'text', 'uniCode', 'fontFamily', 'iconSize', 'iconColor' ] }), items = [], unicode, fontFamily; if(this.items && Ext.isObject(this.items) && Ext.isArray(this.items.items)) { this.items.defaults = this.items.defaults || {}; Ext.Array.each(this.items.items, function(item, index) { items.push(Ext.apply(item, this.items.defaults)); }, this); } else { items = this.items; } Ext.Array.each(items, function(item) { [unicode, fontFamily] = item.glyph.split('@'); store.add({ text: item.text, uniCode: unicode, fontFamily: fontFamily, iconSize: item.iconSize, iconColor: item.iconColor, glyph: item.glyph, handler: item.handler || false, scope: item.scope }); }); return store; }, setOwnerCmp: function (comp, instanced) {}, getCount() { return this.getStore().getCount(); } });
Fiddle: