1. #11
    Sencha Premium Member Troy Wolf's Avatar
    Join Date
    May 2007
    Location
    Kansas City
    Posts
    246
    Vote Rating
    2
    Troy Wolf is on a distinguished road

      0  

    Thumbs up


    Btw, I am using SelectBox now. My ComboBoxes use JsonStore as opposed to SimpleStore. I was able to use your searchByString prototype simply by changing:

    Code:
    Ext.data.SimpleStore.prototype.searchByString = ....
    To:

    Code:
    Ext.data.JsonStore.prototype.searchByString = ....
    So far, it seems to work fine. Firebug is not reporting any errors.

  2. #12
    Ext User
    Join Date
    Nov 2007
    Posts
    5
    Vote Rating
    0
    Tefen is on a distinguished road

      0  

    Default


    Quote Originally Posted by Troy Wolf View Post
    corey.gilmore or others,

    Looking at your Ext.form.SelectBox demo and code, it looks and works very nicely. I found it because I want a Select (or ComboBox) that works more like a normal HTML Select. Mainly, when an item is selected, I do not want the list of options to change to only those that match the selected option text. This default functionality is nice for when a person is typing into the combobox looking for an option, but it is very unnatural when the user wants to later click the arrow to select a different option from the list----and nothing shows but the one selected option.

    Wanting the list of options to remain static upon typing and selection seems like such a natural choice, that I would be very surprised to find that the Ext ComboBox cannot be naturally tweaked to behave this way.

    corey.gilmore, since you obviously had to learn a lot about the ComboBox object, I figure you can easily answer my question. Do I need to use your SelectBox just to get this "basic" functionality?

    Thank you!


    I think the answer is

    triggerAction: 'all'


    Took me a while to figure that one out myself.

  3. #13
    Sencha Premium Member Troy Wolf's Avatar
    Join Date
    May 2007
    Location
    Kansas City
    Posts
    246
    Vote Rating
    2
    Troy Wolf is on a distinguished road

      0  

    Default


    Quote Originally Posted by Tefen View Post
    I think the answer is

    triggerAction: 'all'


    Took me a while to figure that one out myself.
    I think you are correct. In fact, I'm no longer using the custom SelectBox object. I'm back to using the standard ComboBox with triggerAction:'all'. It gives me what I need for my app.

  4. #14
    Ext User
    Join Date
    May 2007
    Posts
    181
    Vote Rating
    1
    akannu is on a distinguished road

      0  

    Default triggerAction

    triggerAction


    Based on the documentation (see below) I would not have guessed that this config option makes the combo box work like a HTML select. What am I missing?
    ----------------
    triggerAction
    triggerAction : String
    The action to execute when the trigger field is activated. Use 'all' to run the query specified by the allQuery config option (defaults to 'query')
    This config option is defined by ComboBox.
    ----------------

  5. #15

    Default


    I never really noticed the requirement of triggerAction:'all' before, but from Combo.js you've got:

    Code:
        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());
                }
                this.el.focus();
            }
        }
    Here's an updated version with some changes by Jack for Ext 2.0 that forces triggerAction etc.

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

  6. #16
    Ext User
    Join Date
    May 2007
    Posts
    181
    Vote Rating
    1
    akannu is on a distinguished road

      0  

    Default


    The User Extension SelectBox does solve what we are looking for (i.e. matching user input with 1st character and auto selecting)

    However, I think in addition to COMBO BOX, Ext should provide the following controls:

    1) DROP DOWN (Ext Widget for SELECT HTML element)
    2) LIST (Ext Widget for SELECT HTML element with Multiple attribute)

    with each having their own config options.

    This would allow for flexibility and let everyone use what is best for them.

  7. #17
    Ext JS Premium Member
    Join Date
    Mar 2007
    Posts
    49
    Vote Rating
    0
    scottw is on a distinguished road

      0  

    Default


    Quote Originally Posted by lgerndt View Post
    One problem: when the user clicks once to open and then clicks again to select (as oppposed to just clicking once and releasing on the item they want), "onselect" gets called twice. I need to hook into that and do something and I don't want it done twice, do you know an easy fix for this?
    I encountered the same problem. I stole your idea from another post to come up with this solution. The 'onSelect' method was updated to:

    Code:
    	onSelect : function(record, index, skipCollapse){
    
    		// THIS ISEXPANDED CHECK IS NEW, THE REST IS UNCHANGED
    		// The authors implementation of this causes this method to be called twice,
    		// once while expanded, and again after closed.
    		// We only want this called once, so we check for expanded.
    		if (this.isExpanded()) {
    
    			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);
    			}
    		}
    	},

  8. #18
    Ext User
    Join Date
    Oct 2007
    Posts
    1
    Vote Rating
    0
    bwenneker is on a distinguished road

      0  

    Default


    There's a bug in the focusAndSelect method:

    Code:
    focusAndSelect : function(record) {
        var index = typeof record === 'number' ? record : this.store.indexOf(record);
        this.select(index, this.isExpanded());
        // => bug: this.store.getAt(record) returns undefined, because record is not always numeric
        this.onSelect(this.store.getAt(record), index, this.isExpanded());
    },
    So focusAndSelect should be:

    Code:
    focusAndSelect : function(record) {
        var index = typeof record === 'number' ? record : this.store.indexOf(record);
        this.select(index, this.isExpanded());
        // => fixed: this.store.getAt(index) returns a record
        this.onSelect(this.store.getAt(index), index, this.isExpanded());
    },
    Great code by the way, thanks!
    My blog: Solutoire.com

  9. #19
    Sencha Premium Member
    Join Date
    Mar 2008
    Location
    San Jose, CA
    Posts
    124
    Vote Rating
    0
    surfyogi is on a distinguished road

      0  

    Default


    I would have to agree; ExtJS does some really amazing things, and then leaves me a bit stranded when I simply try to replace the select tags in my forms... which should be the first goal of the API considering the bugs in IE that make the native select tags such a nightmare to work with/around.

    That said, is there an up to date (2.0) version of this simple example??
    http://crepitus.com/misc/ext/combo.html


    I'm pretty lost here, just trying to 2.0-ify this example; not working; I know I need to change out all the libs, and the SelectBox.js with current 2.0 versions, and I think I need to use .render() instead of appy to; anything else?

    Here's my code that's not working (from above SelectBox Demo.htm):

    Ext.onReady(function() {
    // simple array store
    var store = new Ext.data.SimpleStore({
    fields: ['abbr', 'state'],
    data : Ext.exampledata.states // from states.js
    });
    var combo = new Ext.ux.SelectBox({
    store: store,
    displayField:'state',
    mode: 'local',
    triggerAction: 'all',
    emptyText:'Select a state...',
    selectOnFocus:true
    });

    combo.render('local-states');

    });

    Everything seems cool, until combo.render gets called..

    This is the line that I can get back to on a call stack:

    Ext.ux.SelectBox.superclass.onRender.apply(this, arguments);

    in the onRender method of SelectBox.js.

    Anybody recognize why this example blows up on me?

  10. #20

    Default


    Take a look at the updated code here (post #15 in this thread)