X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/3789b528d8dd8aad4558e38e22d775bcab1cbd36..6746dc89c47ed01b165cc1152533605f97eb8e8d:/src/form/field/ComboBox.js diff --git a/src/form/field/ComboBox.js b/src/form/field/ComboBox.js index e3db6623..f646337e 100644 --- a/src/form/field/ComboBox.js +++ b/src/form/field/ComboBox.js @@ -1,3 +1,17 @@ +/* + +This file is part of Ext JS 4 + +Copyright (c) 2011 Sencha Inc + +Contact: http://www.sencha.com/contact + +GNU General Public License Usage +This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + +If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact. + +*/ /** * @class Ext.form.field.ComboBox * @extends Ext.form.field.Picker @@ -62,10 +76,6 @@ * ComboBox also allows selection of multiple items from the list; to enable multi-selection set the * {@link #multiSelect} config to `true`. * - * @constructor - * Create a new ComboBox. - * @param {Object} config Configuration options - * @xtype combo * @docauthor Jason Johnston */ Ext.define('Ext.form.field.ComboBox', { @@ -77,48 +87,48 @@ Ext.define('Ext.form.field.ComboBox', { /** * @cfg {String} triggerCls * An additional CSS class used to style the trigger button. The trigger will always get the - * {@link #triggerBaseCls} by default and triggerCls will be appended if specified. + * {@link #triggerBaseCls} by default and triggerCls will be appended if specified. * Defaults to 'x-form-arrow-trigger' for ComboBox. */ triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger', /** - * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to undefined). + * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to undefined). * Acceptable values for this property are: *
- *

See also {@link #queryMode}.

+ *

See also {@link #queryMode}.

*/ /** * @cfg {Boolean} multiSelect - * If set to true, allows the combo field to hold more than one value at a time, and allows selecting + * If set to true, allows the combo field to hold more than one value at a time, and allows selecting * multiple items from the dropdown list. The combo's text field will show all selected values separated by - * the {@link #delimiter}. (Defaults to false.) + * the {@link #delimiter}. (Defaults to false.) */ multiSelect: false, /** * @cfg {String} delimiter * The character(s) used to separate the {@link #displayField display values} of multiple selected items - * when {@link #multiSelect} = true. Defaults to ', '. + * when {@link #multiSelect} = true. Defaults to ', '. */ delimiter: ', ', /** * @cfg {String} displayField The underlying {@link Ext.data.Field#name data field name} to bind to this * ComboBox (defaults to 'text'). - *

See also {@link #valueField}.

+ *

See also {@link #valueField}.

*/ displayField: 'text', @@ -127,16 +137,16 @@ Ext.define('Ext.form.field.ComboBox', { * @required * The underlying {@link Ext.data.Field#name data value name} to bind to this ComboBox (defaults to match * the value of the {@link #displayField} config). - *

Note: use of a valueField requires the user to make a selection in order for a value to be - * mapped. See also {@link #displayField}.

+ *

Note: use of a valueField requires the user to make a selection in order for a value to be + * mapped. See also {@link #displayField}.

*/ /** * @cfg {String} triggerAction The action to execute when the trigger is clicked. *
*

See also {@link #queryParam}.

@@ -150,22 +160,26 @@ Ext.define('Ext.form.field.ComboBox', { allQuery: '', /** - * @cfg {String} queryParam Name of the query ({@link Ext.data.proxy.Proxy#extraParam extraParam} name for the store) - * as it will be passed on the querystring (defaults to 'query'). If explicitly set to a falsey value it will - * not be send. + * @cfg {String} queryParam Name of the parameter used by the Store to pass the typed string when the ComboBox is configured with + * {@link #queryMode}: 'remote' (defaults to 'query'). If explicitly set to a falsy value it will + * not be sent. */ queryParam: 'query', /** * @cfg {String} queryMode - * The mode for queries. Acceptable values are: + * The mode in which the ComboBox uses the configured Store. Acceptable values are: *
*/ @@ -563,9 +577,9 @@ var combo = new Ext.form.field.ComboBox({ * Executes a query to filter the dropdown list. Fires the {@link #beforequery} event prior to performing the * query allowing the query action to be canceled if needed. * @param {String} queryString The SQL query to execute - * @param {Boolean} forceAll true to force the query to execute even if there are currently fewer - * characters in the field than the minimum specified by the {@link #minChars} config option. It - * also clears any filter previously saved in the current store (defaults to false) + * @param {Boolean} forceAll true to force the query to execute even if there are currently fewer + * characters in the field than the minimum specified by the {@link #minChars} config option. It + * also clears any filter previously saved in the current store (defaults to false) * @return {Boolean} true if the query was permitted to run, false if it was cancelled by a {@link #beforequery} handler. */ doQuery: function(queryString, forceAll) { @@ -599,12 +613,19 @@ var combo = new Ext.form.field.ComboBox({ // make sure they aren't querying the same thing if (!me.queryCaching || me.lastQuery !== queryString) { me.lastQuery = queryString; - store.clearFilter(!forceAll); + if (isLocalMode) { - if (!forceAll) { + // forceAll means no filtering - show whole dataset. + if (forceAll) { + store.clearFilter(); + } else { + // Clear filter, but supress event so that the BoundList is not immediately updated. + store.clearFilter(true); store.filter(me.displayField, queryString); } } else { + // In queryMode: 'remote', we assume Store filters are added by the developer as remote filters, + // and these are automatically passed as params with every load call, so we do *not* call clearFilter. store.load({ params: me.getParams(queryString) }); @@ -633,11 +654,11 @@ var combo = new Ext.form.field.ComboBox({ var p = {}, pageSize = this.pageSize, param = this.queryParam; - + if (param) { p[param] = queryString; } - + if (pageSize) { p.start = 0; p.limit = pageSize; @@ -706,7 +727,7 @@ var combo = new Ext.form.field.ComboBox({ me.doQueryTask.delay(me.queryDelay); } } - + if (me.enableKeyEvents) { me.callParent(arguments); } @@ -717,7 +738,7 @@ var combo = new Ext.form.field.ComboBox({ me.callParent(); /* - * Setup keyboard handling. If enableKeyEvents is true, we already have + * Setup keyboard handling. If enableKeyEvents is true, we already have * a listener on the inputEl for keyup, so don't create a second. */ if (!me.enableKeyEvents) { @@ -740,7 +761,8 @@ var combo = new Ext.form.field.ComboBox({ store: me.store, displayField: me.displayField, focusOnToFront: false, - pageSize: me.pageSize + pageSize: me.pageSize, + tpl: me.tpl }, me.listConfig, me.defaultListConfig); picker = me.picker = Ext.create('Ext.view.BoundList', opts); @@ -751,10 +773,7 @@ var combo = new Ext.form.field.ComboBox({ scope: me }); - me.mon(picker.getSelectionModel(), { - selectionChange: me.onListSelectionChange, - scope: me - }); + me.mon(picker.getSelectionModel(), 'selectionchange', me.onListSelectionChange, me); return picker; }, @@ -763,7 +782,7 @@ var combo = new Ext.form.field.ComboBox({ this.alignPicker(); this.syncSelection(); }, - + onItemClick: function(picker, record){ /* * If we're doing single selection, the selection change events won't fire when @@ -773,25 +792,34 @@ var combo = new Ext.form.field.ComboBox({ lastSelection = me.lastSelection, valueField = me.valueField, selected; - + if (!me.multiSelect && lastSelection) { selected = lastSelection[0]; - if (record.get(valueField) === selected.get(valueField)) { + if (selected && (record.get(valueField) === selected.get(valueField))) { me.collapse(); } - } + } }, onListSelectionChange: function(list, selectedRecords) { - var me = this; + var me = this, + isMulti = me.multiSelect, + hasRecords = selectedRecords.length > 0; // Only react to selection if it is not called from setValue, and if our list is // expanded (ignores changes to the selection model triggered elsewhere) if (!me.ignoreSelection && me.isExpanded) { - if (!me.multiSelect) { + if (!isMulti) { Ext.defer(me.collapse, 1, me); } - me.setValue(selectedRecords, false); - if (selectedRecords.length > 0) { + /* + * Only set the value here if we're in multi selection mode or we have + * a selection. Otherwise setValue will be called with an empty value + * which will cause the change event to fire twice. + */ + if (isMulti || hasRecords) { + me.setValue(selectedRecords, false); + } + if (hasRecords) { me.fireEvent('select', me, selectedRecords); } me.inputEl.focus(); @@ -1036,3 +1064,4 @@ var combo = new Ext.form.field.ComboBox({ } } }); +