📄 multicombo.js
字号:
updateValue : function(value, text) { this.value = value; if(this.hiddenField){ this.hiddenField.value = value.join(','); } if (typeof(text) == 'string') { this.setRawValue(text); } }, /** * setValue * Accepts a comma-separated list of ids or an array. if given a string, will conver to Array. * @param {Array, String} v */ setValue : function(v) { var text = []; var value = []; if (typeof(v) == 'string') { // <-- "1,2,3" value = v.match(/\d+/g); // <-- strip multiple spaces and split on "," for (var n=0,len=value.length;n<len;n++) { value[n] = parseInt(value[n]); } } else if (Ext.isArray(v)) { // <-- [1,2,3] value = v; } if (value.length) { if (this.mode == 'local') { this.updateValue(value); this.setRawValue(this.getTextValue()); } else { this.updateValue(value); this.store.load({ callback: function() { this.setRawValue(this.getTextValue()); }, scope: this }); this.mode = 'local'; } } }, getTextValue : function() { if (this.value.length == this.store.getCount()) { return this.allSelectedText; } else { var text = []; this.store.data.filterBy(this.store.createFilterFn(this.valueField, new RegExp(this.value.join('|'), "i"), false, false)).each(function(r){ text.push(r.data[this.displayField]); }, this); return text.join(', '); } }, /** * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire. * The store must be loaded and the list expanded for this function to work, otherwise use setValue. * @param {Number} index The zero-based index of the list item to select * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the * selected item if it is not currently in view (defaults to true) */ select : function(index, scrollIntoView){ if (!typeof(index) == 'number') { throw new Error('MultiCombo#select expected @param {Number} index but got: ' + typeof(index)); } this.view.isSelected(index) ? this.view.deselect(index, true) : this.view.select(index, true); this.onSelect(this.store.getAt(index), index); this.matches = null; if(scrollIntoView !== false){ var el = this.view.getNode(index); if(el){ this.innerList.scrollChildIntoView(el, false); } } }, getLastValue : function() { return Ext.util.Format.trim(this.getRawValue().split(',').pop()); }, /** * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire. * The store must be loaded and the list expanded for this function to work, otherwise use setValue. * @param {String} value The data value of the item to select * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the * selected item if it is not currently in view (defaults to true) * @return {Boolean} True if the value matched an item in the list, else false */ selectByValue : function(v, scrollIntoView){ if (v.length) { var indexes = []; var rs = this.store.data.filterBy(this.store.createFilterFn(this.valueField, new RegExp(v.join('|'), "i"))).each(function(r){ indexes.push(this.store.indexOf(r)); }, this); if (indexes.length) { this.view.select(indexes); return true; } } else { this.view.clearSelections(); this.setRawValue(''); return false; } }, // private initEvents : function(){ Ext.form.ComboBox.superclass.initEvents.call(this); this.keyNav = new Ext.KeyNav(this.el, { "up" : function(e){ this.lastKey = Ext.EventObject.UP; this.inKeyMode = true; this.selectPrev(); this.scrollIntoView(); }, "down" : function(e){ this.inKeyMode = true; if(!this.isExpanded()){ this.lastKey = Ext.EventObject.DOWN; this.onTriggerClick(); }else{ this.selectNext(); this.scrollIntoView(); } }, "enter" : function(e){ var idx = this.highlightIndex; if (this.inKeyMode === true) { if (this.plugins.length && (idx <= -1)) { if (this.plugins[idx + 1]) { this.plugins[idx + 1].onEnter(this); } } else if (this.plugins.length && this.highlightIndex == 0 && this.highlightIndexPrev == -1) { if (this.plugins[idx]) { this.plugins[idx].onEnter(this); } } else { var idx = this.getHighlightedIndex() || 0; if (this.highlightIndex != null && idx != null) { this.select(idx, true); //this.delayedCheck = true; //this.unsetDelayCheck.defer(10, this); } } } else { var v = this.getLastValue(); var raw = this.getRawValue(); /** this block should be moved to method getCurrentWord * */ var pos = this.getCaretPosition(raw); var word = ''; if (pos !== false && pos < raw.length) { word = Ext.util.Format.trim(raw.substr(0, pos).split(',').pop()); } else { word = Ext.util.Format.trim(raw.split(',').pop()); } /*******************************************************/ var idx = this.store.find(this.displayField, word); if (idx != -1) { var rec = this.store.getAt(idx); this.select(idx, true); } raw = this.getRawValue(); this.selectText(raw.length, raw.length); this.collapse(); } }, "esc" : function(e){ this.collapse(); }, "tab" : function(e){ if (this.matches != null && this.matches.getCount() == 1) { var idx = this.store.indexOf(this.matches.first()); if (!this.view.isSelected(idx)) { this.select(this.store.indexOf(this.matches.first()), true); } } else if (this.value.length == 0 && this.getRawValue().length > 0) { this.setRawValue(''); } this.collapse(); return true; }, scope : this, doRelay : function(foo, bar, hname){ if(hname == 'down' || this.scope.isExpanded()){ return Ext.KeyNav.prototype.doRelay.apply(this, arguments); } return true; }, forceKeyDown : true }); this.queryDelay = Math.max(this.queryDelay || 10, this.mode == 'local' ? 10 : 250); this.dqTask = new Ext.util.DelayedTask(this.initQuery, this); if(this.typeAhead){ this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this); } if(this.editable !== false){ this.el.on("keyup", this.onKeyUp, this); } if(this.forceSelection){ this.on('blur', this.doForce, this); } }, // private, blur-handler to ensure that rawValue contains only values from selections, in the same order as selected validateSelections : function(field) { var v = this.getValue(); var text = []; for (var i=0,len=v.length;i<len;i++) { var idx = this.store.find(this.valueField, v[i]); if (idx >=0) { text.push(this.store.getAt(idx).data[this.displayField]); } } this.setRawValue(text.join(', ')); }, scrollIntoView : function() { var el = this.getHighlightedNode(); if (el) { this.innerList.scrollChildIntoView(el); } }, // private selectNext : function(){ this.clearHighlight(); if (this.highlightIndex == null) { this.highlightIndex = -1; } if (this.highlightIndex <= -1 && this.highlightIndexPrev != -1) { if (this.plugins.length > 0) { var idx = Math.abs(this.highlightIndex)-1; if (this.plugins.length >= Math.abs(this.highlightIndex)) { this.plugins[idx].selectNext(this); this.highlightIndexPrev = this.highlightIndex; this.highlightIndex++; return false; } } } if (this.highlightIndexPrev == -1 && this.highlightIndex == 0) { this.highlightIndex = -1; } var ct = this.store.getCount(); if(ct > 0){ if (this.highlightIndex == -1 || this.highlightIndex+1 < ct) { if (this.highlightIndex == -1) { this.highlightIndexPrev = 0; } else { this.highlightIndexPrev = this.highlightIndex -1; } this.highlight(++this.highlightIndex); } else { this.highlight(ct-1); } } }, // private selectPrev : function(){ this.clearHighlight(); if (this.highlightIndex <= 0) { var idx = Math.abs(this.highlightIndex); if (this.plugins.length >= idx+1 && this.highlightIndexPrev >= 0) { this.clearHighlight(); this.plugins[idx].selectPrev(this); this.highlightIndexPrev = this.highlightIndex; this.highlightIndex--; if (this.highlightIndex == -1) { this.highlightIndexPrev = -1; } return false; } else { this.highlightIndex = -1; this.highlightIndexPrev = -1; this.collapse(); return; } } this.highlightIndexPrev = this.highlightIndex; var ct = this.store.getCount(); if(ct > 0){ if (this.highlighIndex == -1) { this.highlightIndex = 0; } else if (this.highlightIndex != 0) { this.highlightIndex--; } else if (this.highlightIndex == 0) { this.collapse(); } this.highlight(this.highlightIndex); } }, collapse : function() { if (this.isExpanded()) { this.highlightIndex = null; this.highlightIndexPrev = null; } Ext.ux.MultiCombo.superclass.collapse.call(this); }, highlight : function(index) { this.view.el.select('.'+this.highlightClass).removeClass(this.highlightClass); var node = Ext.fly(this.view.getNode(index)); if (node) { node.addClass(this.highlightClass); } }, getHighlightedIndex : function() { var node = this.view.el.child('.' + this.highlightClass, true); return (node) ? this.store.indexOf(this.view.getRecord(node)) : this.highlightIndex; }, getHighlightedNode : function() { return this.view.el.child('.'+this.highlightClass, true); }, clearHighlight : function() { if (typeof(this.view) != 'object') { return false; } var el = this.view.el.select('.'+this.highlightClass); if (el) { el.removeClass(this.highlightClass); } }, // private initList : function(){ if(!this.list){ var cls = 'x-combo-list'; this.list = new Ext.Layer({ shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false }); var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth); this.list.setWidth(lw); this.list.swallowEvent('mousewheel'); this.assetHeight = 0; if(this.syncFont !== false){ this.list.setStyle('font-size', this.el.getStyle('font-size')); } if(this.title){ this.header = this.list.createChild({cls:cls+'-hd', html: this.title}); this.assetHeight += this.header.getHeight(); } this.innerList = this.list.createChild({cls:cls+'-inner'}); this.innerList.on('mouseover', this.onViewOver, this); this.innerList.on('mousemove', this.onViewMove, this); this.innerList.setWidth(lw - this.list.getFrameWidth('lr')); if(this.pageSize){ this.footer = this.list.createChild({cls:cls+'-ft'}); this.pageTb = new Ext.PagingToolbar({ store:this.store, pageSize: this.pageSize, renderTo:this.footer }); this.assetHeight += this.footer.getHeight(); } if(!this.tpl){ /** * @cfg {String/Ext.XTemplate} tpl The template string, or {@link Ext.XTemplate} * instance to use to display each item in the dropdown list. Use * this to create custom UI layouts for items in the list. * <p> * If you wish to preserve the default visual look of list items, add the CSS * class name <pre>x-combo-list-item</pre> to the template's container element. * <p> * <b>The template must contain one or more substitution parameters using field * names from the Combo's</b> {@link #store Store}. An example of a custom template * would be adding an <pre>ext:qtip</pre> attribute which might display other fields * from the Store. * <p> * The dropdown list is displayed in a DataView. See {@link Ext.DataView} for details. */ this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>'; /** * @cfg {String} itemSelector * <b>This setting is required if a custom XTemplate has been specified in {@link #tpl} * which assigns a class other than <pre>'x-combo-list-item'</pre> to dropdown list items</b>. * A simple CSS selector (e.g. div.some-class or span:first-child) that will be * used to determine what nodes the DataView which handles the dropdown display will * be working with. */ } /** * The {@link Ext.DataView DataView} used to display the ComboBox's options. * @type Ext.DataView */ this.view = new Ext.DataView({ applyTo: this.innerList, tpl: this.tpl, simpleSelect: true, multiSelect: true, overClass: this.overClass, selectedClass: this.selectedClass, itemSelector: this.itemSelector || '.' + cls + '-item' }); this.view.on('click', this.onViewClick, this); this.fireEvent('initview', this, this.view); this.bindStore(this.store, true); if(this.resizable){ this.resizer = new Ext.Resizable(this.list, { pinned:true, handles:'se' }); this.resizer.on('resize', function(r, w, h){ this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight; this.listWidth = w; this.innerList.setWidth(w - this.list.getFrameWidth('lr')); this.restrictHeight(); }, this); this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px'); } } }});Ext.reg('multicombo', Ext.ux.MultiCombo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -