Ext JS多选控件 MultiCombo

试过了不少能找到的多选控件,包括Ext官方坛子里的SuperBox啥的,不过越炫的bug越多,改起来越麻烦。算了吧,回归简单,从彭仁X(对不住了,那个字不会念所以也打不出来,惭愧...)老师的书《Ext JS源码分析与开发实例》中扒下来了一个,虽然简单,但是够用。当然由于是例子的关系功能还不是很完善,譬如对于放在Formpanel中数据加载的时候没有处理,所以加上了这一部分,并修复了一点小bug。

代码
Ext.ns('Ext.ux');
Ext.ux.MultiComBox 
= Ext.extend(Ext.form.ComboBox, {
    splitSign : 
',',
    selections : [],
    checks : [],
    hiddenValue : 
'',
    lastSelectionText : 
'',
    initList : 
function() {
        
var cls = 'x-combo-list';
        
this.tpl = '<tpl for="."><div class="'
                
+ cls
                
+ '-item"><table border="0" width=80% height="16px" style="height:18px;"><tr ><td class="check-box" style="20px;height:18px;"></td><td style="font-size:12px;">{'
                
+ this.displayField + '}</td></tr></table></div></tpl>';
        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);
        }
    },
    refresh : 
function(multi) {
        
this.clearSelections(falsetrue);
        
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()
                    });
            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 text = this.lastSelectionText;
        
var hiddenValue = this.hiddenValue;
        
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 split = Ext.escapeRe(this.splitSign);
                
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');

                
if (checked == false || typeof checked == "undefined") {
                    text 
= text.replace(nemeRe, "");
                    hiddenValue 
= hiddenValue.replace(valueRe, "");
                    
var separate = !text ? "" : this.splitSign;
                    text 
= text + separate + name;
                    hiddenValue 
= hiddenValue + separate + value;
                } 
else {
                    text 
= text.replace(nemeRe, "");
                    hiddenValue 
= hiddenValue.replace(valueRe, "");
                }
            }
        }
        
this.lastSelectionText = text;
        Ext.form.ComboBox.superclass.setValue.call(
this, text);
        
this.hiddenValue = hiddenValue || 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();
        }
    }

});
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()); });
 
*/

 没时间详细解释...万一真有人看,有疑问可以看原书或回帖。 

原文地址:https://www.cnblogs.com/damnedmoon/p/1732389.html