/** * Makes a ComboBox more closely mimic an HTML SELECT. Supports clicking and dragging * through the list, with item selection occurring when the mouse button is released. * When used will automatically set {@link #editable} to false and call {@link Ext.Element#unselectable} * on inner elements. Re-enabling editable after calling this will NOT work. * * @author Corey Gilmore * http://extjs.com/forum/showthread.php?t=6392 * * @history 2007-07-08 jvs * Slight mods for Ext 2.0 */ Ext.ux.SelectBox = function(config){ this.searchResetDelay = 1000; config = config || {}; config = Ext.apply(config || {}, { editable: false, forceSelection: true, rowHeight: false, lastSearchTerm: false, triggerAction: 'all', mode: 'local' }); Ext.ux.SelectBox.superclass.constructor.apply(this, arguments); this.lastSelectedIndex = this.selectedIndex || 0; }; Ext.extend(Ext.ux.SelectBox, Ext.form.ComboBox, { lazyInit: false, initEvents : function(){ Ext.ux.SelectBox.superclass.initEvents.apply(this, arguments); // you need to use keypress to capture upper/lower case and shift+key, but it doesn't work in IE this.el.on('keydown', this.keySearch, this, true); this.cshTask = new Ext.util.DelayedTask(this.clearSearchHistory, this); }, keySearch : function(e, target, options) { var raw = e.getKey(); var key = String.fromCharCode(raw); var startIndex = 0; if( !this.store.getCount() ) { return; } switch(raw) { case Ext.EventObject.HOME: e.stopEvent(); this.selectFirst(); return; case Ext.EventObject.END: e.stopEvent(); this.selectLast(); return; case Ext.EventObject.PAGEDOWN: this.selectNextPage(); e.stopEvent(); return; case Ext.EventObject.PAGEUP: this.selectPrevPage(); e.stopEvent(); return; } // skip special keys other than the shift key if( (e.hasModifier() && !e.shiftKey) || e.isNavKeyPress() || e.isSpecialKey() ) { return; } if( this.lastSearchTerm == key ) { startIndex = this.lastSelectedIndex; } this.search(this.displayField, key, startIndex); this.cshTask.delay(this.searchResetDelay); }, onRender : function(ct, position) { this.store.on('load', this.calcRowsPerPage, this); Ext.ux.SelectBox.superclass.onRender.apply(this, arguments); if( this.mode == 'local' ) { this.calcRowsPerPage(); } }, onSelect : function(record, index, skipCollapse){ if(this.fireEvent('beforeselect', this, record, index) !== false){ this.setValue(record.data[this.valueField || this.displayField]); if( !skipCollapse ) { this.collapse(); } this.lastSelectedIndex = index + 1; this.fireEvent('select', this, record, index); } }, render : function(ct) { Ext.ux.SelectBox.superclass.render.apply(this, arguments); if( Ext.isSafari ) { this.el.swallowEvent('mousedown', true); } this.el.unselectable(); this.innerList.unselectable(); this.trigger.unselectable(); this.innerList.on('mouseup', function(e, target, options) { if( target.id && target.id == this.innerList.id ) { return; } this.onViewClick(); }, this); this.innerList.on('mouseover', function(e, target, options) { if( target.id && target.id == this.innerList.id ) { return; } this.lastSelectedIndex = this.view.getSelectedIndexes()[0] + 1; this.cshTask.delay(this.searchResetDelay); }, this); this.trigger.un('click', this.onTriggerClick, this); this.trigger.on('mousedown', function(e, target, options) { e.preventDefault(); this.onTriggerClick(); }, this); this.on('collapse', function(e, target, options) { Ext.getDoc().un('mouseup', this.collapseIf, this); }, this, true); this.on('expand', function(e, target, options) { Ext.getDoc().on('mouseup', this.collapseIf, this); }, this, true); }, clearSearchHistory : function() { this.lastSelectedIndex = 0; this.lastSearchTerm = false; }, selectFirst : function() { this.focusAndSelect(this.store.data.first()); }, selectLast : function() { this.focusAndSelect(this.store.data.last()); }, selectPrevPage : function() { if( !this.rowHeight ) { return; } var index = Math.max(this.selectedIndex-this.rowsPerPage, 0); this.focusAndSelect(this.store.getAt(index)); }, selectNextPage : function() { if( !this.rowHeight ) { return; } var index = Math.min(this.selectedIndex+this.rowsPerPage, this.store.getCount() - 1); this.focusAndSelect(this.store.getAt(index)); }, search : function(field, value, startIndex) { field = field || this.displayField; this.lastSearchTerm = value; var index = this.store.find.apply(this.store, arguments); if( index !== -1 ) { this.focusAndSelect(index); } }, focusAndSelect : function(record) { var index = typeof record === 'number' ? record : this.store.indexOf(record); this.select(index, this.isExpanded()); this.onSelect(this.store.getAt(record), index, this.isExpanded()); }, calcRowsPerPage : function() { if( this.store.getCount() ) { this.rowHeight = Ext.fly(this.view.getNode(0)).getHeight(); this.rowsPerPage = this.maxHeight / this.rowHeight; } else { this.rowHeight = false; } } });