ExtJs5.1多选下拉框CheckComb
ExtJs这么多个版本号了。可就是不提供多选下拉框,老外不用这个玩意吗?
5都出来这么久了,新写的项目就用5吧,把曾经Extjs4.2的时搜到前人的CheckComb改巴改巴。能用了就赶紧贴上来,没有细致測试各种情况。
Ext.define('Ext.ux.CheckCombo', { extend : 'Ext.form.field.ComboBox', alias : 'widget.checkcombo', multiSelect : true, allSelector : false, noData : true, noDataText : 'No combo data', addAllSelector : false, allSelectorHidden : false, enableKeyEvents : true, afterExpandCheck : false, allText : 'All', oldValue : '', listeners : { /* * uncomment if you want to reload store on every combo expand * beforequery: function(qe) { this.store.removeAll(); delete * qe.combo.lastQuery; }, */ focus : function(cpt) { cpt.oldValue = cpt.getValue(); } }, createPicker : function() { var me = this, picker, menuCls = Ext.baseCSSPrefix + 'menu', opts = Ext .apply({ pickerField : me, selectionModel : me.pickerSelectionModel, floating : true, hidden : true, ownerCt : me.ownerCt, cls : me.el.up('.' + menuCls) ? menuCls : '', store : me.getPickerStore(), displayField : me.displayField, preserveScrollOnRefresh : true, pageSize : me.pageSize, tpl : [ '<tpl for=".">', '<div class="x-boundlist-item" role="option"><span class="x-combo-checker"> </span> {' + me.displayField + '}</div>', '</tpl>'] }, me.listConfig, me.defaultListConfig); picker = me.picker = Ext.create('Ext.view.BoundList', opts); if (me.pageSize) { picker.pagingToolbar.on('beforechange', me.onPageChange, me); } // We limit the height of the picker to fit in the space above // or below this field unless the picker has its own ideas about that. if (!picker.initialConfig.maxHeight) { picker.on({ beforeshow : me.onBeforePickerShow, scope : me }); } picker.getSelectionModel().on({ beforeselect : me.onBeforeSelect, beforedeselect : me.onBeforeDeselect, scope : me }); picker.getNavigationModel().navigateOnSpace = false; me.store.on('load', function(store) { if (store.getTotalCount() == 0) { me.allSelectorHidden = true; if (me.allSelector != false) me.allSelector.setStyle('display', 'none'); if (me.noData != false) me.noData.setStyle('display', 'block'); } else { me.allSelectorHidden = false; if (me.allSelector != false) me.allSelector.setStyle('display', 'block'); if (me.noData != false) me.noData.setStyle('display', 'none'); } }); return picker; }, reset : function() { var me = this; me.setValue(''); }, setValue : function(value) { this.value = value; if (!value) { if (this.allSelector != false) this.allSelector.removeCls('x-boundlist-selected'); return this.callParent(arguments); } if (typeof value == 'string') { var me = this, records = [], vals = value.split(','); if (value == '') { if (me.allSelector != false) me.allSelector.removeCls('x-boundlist-selected'); } else { if (vals.length == me.store.getCount() && vals.length != 0) { if (me.allSelector != false) me.allSelector.addCls('x-boundlist-selected'); else me.afterExpandCheck = true; } } Ext.each(vals, function(val) { var record = me.store.getById(parseInt(val)); if (record) records.push(record); }); return me.setValue(records); } else return this.callParent(arguments); }, getValue : function() { if (typeof this.value == 'object') return this.value.join(','); else return this.value; }, getSubmitValue : function() { return this.getValue(); }, expand : function() { var me = this, bodyEl, picker, doc, collapseIf; if (me.rendered && !me.isExpanded && !me.isDestroyed) { bodyEl = me.bodyEl; picker = me.getPicker(); doc = Ext.getDoc(); collapseIf = me.collapseIf; picker.setMaxHeight(picker.initialConfig.maxHeight); if (me.matchFieldWidth) { picker.width = me.bodyEl.getWidth(); } // Show the picker and set isExpanded flag. alignPicker only works // if isExpanded. picker.show(); me.isExpanded = true; me.alignPicker(); bodyEl.addCls(me.openCls); if (me.noData == false) me.noData = picker.getEl().down('.x-boundlist-list-ct') .insertHtml( 'beforeBegin', '<div class="x-boundlist-item" role="option">' + me.noDataText + '</div>', true); if (me.addAllSelector == true && me.allSelector == false) { me.allSelector = picker .getEl() .down('.x-boundlist-list-ct') .insertHtml( 'beforeBegin', '<div class="x-boundlist-item" role="option"><span class="x-combo-checker"> </span> ' + me.allText + '</div>', true); me.allSelector.on('click', function(e) { if (me.allSelector.hasCls('x-boundlist-selected')) { me.allSelector .removeCls('x-boundlist-selected'); me.setValue(''); me.fireEvent('select', me, []); } else { var records = []; me.store.each(function(record) { records.push(record); }); me.allSelector.addCls('x-boundlist-selected'); me.select(records); me.fireEvent('select', me, records); } }); if (me.allSelectorHidden == true) me.allSelector.hide(); else me.allSelector.show(); if (me.afterExpandCheck == true) { me.allSelector.addCls('x-boundlist-selected'); me.afterExpandCheck = false; } } // Collapse on touch outside this component tree. // Because touch platforms do not focus document.body on touch // so no focusleave would occur to trigger a collapse. me.touchListeners = doc.on({ // Do not translate on non-touch platforms. // mousedown will blur the field. translate : false, touchstart : me.collapseIf, scope : me, delegated : false, destroyable : true }); // Scrolling of anything which causes this field to move should // collapse me.scrollListeners = Ext.on({ scroll : me.onGlobalScroll, scope : me, destroyable : true }); // monitor touch and mousewheel me.hideListeners = doc.on({ mousewheel : me.collapseIf, touchstart : me.collapseIf, scope : me, delegated : false, destroyable : true }); // Buffer is used to allow any layouts to complete before we align Ext.on('resize', me.alignPicker, me, { buffer : 1 }); me.fireEvent('expand', me); me.onExpand(); } else { me.fireEvent('expand', me); me.onExpand(); } }, onListSelectionChange : function(list, selectedRecords) { var me = this, isMulti = me.multiSelect, hasRecords = selectedRecords.length > 0; // Only react to selection if it is not called from setValue, and if our // list is // expanded (ignores changes to the selection model triggered elsewhere) if (!me.ignoreSelection && me.isExpanded) { if (!isMulti) { Ext.defer(me.collapse, 1, me); } /* * Only set the value here if we're in multi selection mode or we * have a selection. Otherwise setValue will be called with an empty * value which will cause the change event to fire twice. */ if (isMulti || hasRecords) { me.setValue(selectedRecords, false); } if (hasRecords) { me.fireEvent('select', me, selectedRecords); } me.inputEl.focus(); if (me.addAllSelector == true && me.allSelector != false) { if (selectedRecords.length == me.store.getTotalCount()) me.allSelector.addCls('x-boundlist-selected'); else me.allSelector.removeCls('x-boundlist-selected'); } } } });
还有相关的css啊,图片就自己找吧。我是把4里面的图片copy过来的:
/*ext多选下拉框样式,未选*/ .x-combo-checker { background-position: 50% -2px; margin-left: 1px; background-color: transparent; background-image:url(../thirdjs/extjs513/ext-theme-classic/images/unchecked.gif); background-position: -1px -1px; background-repeat: no-repeat; height: 14px; width: 14px; display: inline-block; } /*ext多选下拉框样式,已选*/ .x-boundlist-selected .x-combo-checker { background-image:url(../thirdjs/extjs513/ext-theme-classic/images/checked.gif); }