1. 程式人生 > >Extjs 2.3 的多選框控制元件 muiltiCombox

Extjs 2.3 的多選框控制元件 muiltiCombox

在製作報表的查詢條件時,需要有多選下拉框,Ext 2.3預設沒有實現。找來參考資料1的程式碼測試,發現當有多個多選下拉框時,會有資料混亂不能選擇的情況。對其中原始碼進行了修正,現在可以正常使用。主要修改了初始化[this.selections初始化]和setValue()函式,原始碼如下:

/**
 * 程式碼Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->Ext.ns('Ext.ux');
 * http://www.cnblogs.com/damnedmoon/archive/2010/05/11/1732389.html
 */
Ext.ux.MultiComBox = Ext.extend(Ext.form.ComboBox, {
    splitSign : ',',
    selections : [],
    checks : [],
    hiddenValue : '',
    lastSelectionText : '',
    initList : function() {
        var cls = 'x-combo-list';
        this.tpl = '<div class="" '"="">
{' + this.displayField + '}
'; Ext.ux.MultiComBox.superclass.initList.call(this); this.view.updateIndexes = this.updateIndexes.createDelegate(this.view); this.view.refresh = this.refresh.createDelegate(this.view, [this], 0); if (this.view.store) { this.view.setStore(this.view.store, true); } // 再初始化一次,不然多個下拉框時會混用一個變數 this.selections = []; }, refresh : function(multi) { this.clearSelections(false, true); this.el.update(""); var records = this.store.getRange(); if (records.length < 1) { if (!this.deferEmptyText || this.hasSkippedEmptyText) { this.el.update(this.emptyText); } this.hasSkippedEmptyText = true; this.all.clear(); return; } this.tpl.overwrite(this.el, this.collectData(records, 0)); this.all.fill(Ext.query(this.itemSelector, this.el.dom)); multi.createCheck(); this.updateIndexes(0); }, updateIndexes : function(startIndex, endIndex) { var ns = this.all.elements; startIndex = startIndex || 0; endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1)); for (var i = startIndex; i <= endIndex; i++) { ns[i].viewIndex = i; if (ns[i].checkbox) { ns[i].checkbox.index = i; } } }, createCheck : function() { this.checks = []; for (var i = 0; i < this.view.all.elements.length; i++) { var el = this.view.all.elements[i]; var check = new Ext.form.Checkbox({ width : 20, renderTo : Ext.getBody(), //readOnly : true, // 禁用,使點選有效 disabled : true }); check.initCheckEvents = Ext.emptyFn(); var m = { index : el.viewIndex, check : check, node : el }; el.checkbox = m; this.checks.push(m); Ext.fly(el).select('.check-box').insertFirst(check.wrap); } }, findCheckBox : function(index) { for (var i = 0; i < this.checks.length; i++) { if (this.checks[i].index == index) return this.checks[i]; } return null; }, onSelect : function(record, index, checked) { if (this.fireEvent('beforeselect', this, record, index) !== false) { if (!record) return; var checkObj = this.findCheckBox(index); var checkbox = checkObj && checkObj.check; if (!checkbox) return; if (checked == undefined) checked = checkbox.checked; this.toggleCheckBox(index, checked, record, checkbox); this.select(index, false);// 用來設定選擇樣式 this.fireEvent('select', this, record, index); } }, toggleCheckBox : function(index, checked, r, item) { if (checked == false) { item.setValue(1); if (this.isExist(index) == true) return; this.selections.push({ record : r, index : index }); } else { item.setValue(0); for (var i = 0; i < this.selections.length; i++) { if (index == this.selections[i].index) { this.selections.remove(this.selections[i]); } } } this.setValue(r.data[this.valueField || this.displayField], checked); }, isExist : function(index) { for (var i = 0; i < this.selections.length; i++) { if (this.selections[i].index == index) { return true; } } return false; }, setValue : function(v, checked) { var split = Ext.escapeRe(this.splitSign); var text = split + this.lastSelectionText + split; var hiddenValue = split + this.hiddenValue + split; var values = v.toString().split(this.splitSign); for (i = 0, l = values.length; i < l; i++) { var r = this.findRecord(this.valueField, values[i]); if (r) { var name = r.data[this.displayField], value = r.data[this.valueField]; var con = Ext.escapeRe(name.toString()), val = Ext .escapeRe(value.toString()); // var nemeRe = new RegExp("(^" + con + "[" + split + "]?" + ")" // + "|([" + split + "]?" + con + ")", 'g'); // var valueRe = new RegExp("(^" + val + "[" + split + "]?" + ")" // + "|([" + split + "]?" + val + ")", 'g'); var nemeRe = new RegExp("(" + split + con + split + ")", 'g'); var valueRe = new RegExp("(" + split + val + split + ")", 'g'); if (checked == false || typeof checked == "undefined") { text = text.replace(nemeRe, split); hiddenValue = hiddenValue.replace(valueRe, split); if (text.length <= 2 * split.length) { // 空值時 text = split + name + split; hiddenValue = split + value + split; } else { text = text + name + split; hiddenValue = hiddenValue + value + split; } //var separate = !text ? "" : this.splitSign; } else { text = text.replace(nemeRe, split); hiddenValue = hiddenValue.replace(valueRe, split); if (text.length < 2 * split.length) { text = split + split; hiddenValue = split + split; } } } } this.lastSelectionText = text.substring(split.length, text.length - split.length); Ext.form.ComboBox.superclass.setValue.call(this, this.lastSelectionText); this.hiddenValue = hiddenValue.substring(split.length, hiddenValue.length - split.length);// || this.hiddenValue; if (this.hiddenField) { this.hiddenField.value = this.hiddenValue; } this.value = this.hiddenValue; }, getValue : function() { return Ext.ux.MultiComBox.superclass.getValue.call(this); }, selectByValue : function(v, scrollIntoView) { var value = this.getRawValue().trim() || ""; var v1 = value.trim().split(this.splitSign); for (var i = 0; i < v1.length; i++) { var v = v1[i]; if (v) { var r = this.findRecord(this.displayField, v); this.onSelect(r, this.store.indexOf(r), false); } } }, getRawValue : function(flag) { var v = this.rendered ? this.el.getValue() : Ext.value(this.value, ''); if (v === this.emptyText) { v = ''; } if (flag != true) return v; var v1 = v.trim().split(this.splitSign); if (v1.length > 0) { var v2 = ""; for (var i = 0; i < v1.length; i++) { if (v1[i]) v2 = v2 + "(" + v1[i] + ")" + "|"; } if (v2.length - 2 > 0) v2 = v2.substring(0, v2.length - 1); v = new RegExp(v2); v.length = v2.length; } return v; }, onLoad : function() { if (!this.hasFocus) { return; } if (this.store.getCount() > 0) { this.expand(); this.restrictHeight(); if (this.lastQuery == this.allQuery) { if (this.editable) this.el.dom.select(); this.selectByValue(this.value, true); } else { this.selectByValue(this.value, true) } } else { this.onEmptyResults(); } }, initQuery : function() { this.doQuery(this.getRawValue(true)); }, onTriggerClick : function() { if (this.disabled) { return; } if (this.isExpanded()) { this.collapse(); this.el.focus(); } else { this.onFocus({}); if (this.triggerAction == 'all') { this.doQuery(this.allQuery, true); } else { this.doQuery(this.getRawValue(true)); } this.el.focus(); } }, reset : function() { this.clearAll(); Ext.form.ComboBox.superclass.reset.call(this); }, clearAll : function() { for (var i = 0; i < this.checks.length; i ++) { this.checks[i].check.setValue(0); } this.lastSelectionText = ""; this.hiddenValue = ""; this.value = ""; this.selections = []; this.setRawValue(""); Ext.form.ComboBox.superclass.setValue.call(this, ""); } }); Ext.reg('multiCombox', Ext.ux.MultiComBox); /* * Ext.onReady(function() { var myData = [[3300, "彭仁夔"], [3301, "李明"], [3302, * "王華"], [3303, "張三"], [3304, "李四"], [3305, "王五"], [3306, "彭小明"], [3307, "張華"], * [3308, "李小"]]; * * var store1 = new Ext.data.SimpleStore( { fields : [ { name : 'value', type : * 'string' }, { name : 'name', type : 'string' }], data : myData }); * * var test = new Ext.ux.MultiComBox( { store : store1, displayField : 'name', * valueField : 'value', // typeAhead : true, triggerAction : 'all', mode : * 'local', emptyText : '請選擇...', selectOnFocus : true, loadingText : * 'loading....' }) test.render(Ext.getBody()); }); */ 呼叫程式碼跟combox一樣,如:
				items : [ {
					xtype : 'multiCombox',
					fieldLabel : '多選資料',
					id : 'p_data',
					name : 'p_data',
					anchor : '95%',
					triggerAction : 'all',
					valueField : 'name',
					displayField : "name",
					readOnly : true,
					store : dataStore,
					mode : 'remote'
				} ]

預覽效果如圖:

參考資料:

[1]Ext JS多選控制元件 MultiCombo.http://www.cnblogs.com/damnedmoon/archive/2010/05/11/1732389.html