Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / docs / source / Combo.html
1 <html>
2 <head>
3   <title>The source code</title>
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
6 </head>
7 <body  onload="prettyPrint();">
8     <pre class="prettyprint lang-js">/*!
9  * Ext JS Library 3.0.3
10  * Copyright(c) 2006-2009 Ext JS, LLC
11  * licensing@extjs.com
12  * http://www.extjs.com/license
13  */
14 <div id="cls-Ext.form.ComboBox"></div>/**\r
15  * @class Ext.form.ComboBox\r
16  * @extends Ext.form.TriggerField\r
17  * <p>A combobox control with support for autocomplete, remote-loading, paging and many other features.</p>\r
18  * <p>A ComboBox works in a similar manner to a traditional HTML &lt;select> field. The difference is\r
19  * that to submit the {@link #valueField}, you must specify a {@link #hiddenName} to create a hidden input\r
20  * field to hold the value of the valueField. The <i>{@link #displayField}</i> is shown in the text field\r
21  * which is named according to the {@link #name}.</p>\r
22  * <p><b><u>Events</u></b></p>\r
23  * <p>To do something when something in ComboBox is selected, configure the select event:<pre><code>\r
24 var cb = new Ext.form.ComboBox({\r
25     // all of your config options\r
26     listeners:{\r
27          scope: yourScope,\r
28          'select': yourFunction\r
29     }\r
30 });\r
31 \r
32 // Alternatively, you can assign events after the object is created:\r
33 var cb = new Ext.form.ComboBox(yourOptions);\r
34 cb.on('select', yourFunction, yourScope);\r
35  * </code></pre></p>\r
36  *\r
37  * <p><b><u>ComboBox in Grid</u></b></p>\r
38  * <p>If using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a {@link Ext.grid.Column#renderer renderer}\r
39  * will be needed to show the displayField when the editor is not active.  Set up the renderer manually, or implement\r
40  * a reusable render, for example:<pre><code>\r
41 // create reusable renderer\r
42 Ext.util.Format.comboRenderer = function(combo){\r
43     return function(value){\r
44         var record = combo.findRecord(combo.{@link #valueField}, value);\r
45         return record ? record.get(combo.{@link #displayField}) : combo.{@link #valueNotFoundText};\r
46     }\r
47 }\r
48 \r
49 // create the combo instance\r
50 var combo = new Ext.form.ComboBox({\r
51     {@link #typeAhead}: true,\r
52     {@link #triggerAction}: 'all',\r
53     {@link #lazyRender}:true,\r
54     {@link #mode}: 'local',\r
55     {@link #store}: new Ext.data.ArrayStore({\r
56         id: 0,\r
57         fields: [\r
58             'myId',\r
59             'displayText'\r
60         ],\r
61         data: [[1, 'item1'], [2, 'item2']]\r
62     }),\r
63     {@link #valueField}: 'myId',\r
64     {@link #displayField}: 'displayText'\r
65 });\r
66 \r
67 // snippet of column model used within grid\r
68 var cm = new Ext.grid.ColumnModel([{\r
69        ...\r
70     },{\r
71        header: "Some Header",\r
72        dataIndex: 'whatever',\r
73        width: 130,\r
74        editor: combo, // specify reference to combo instance\r
75        renderer: Ext.util.Format.comboRenderer(combo) // pass combo instance to reusable renderer\r
76     },\r
77     ...\r
78 ]);\r
79  * </code></pre></p>\r
80  *\r
81  * <p><b><u>Filtering</u></b></p>\r
82  * <p>A ComboBox {@link #doQuery uses filtering itself}, for information about filtering the ComboBox\r
83  * store manually see <tt>{@link #lastQuery}</tt>.</p>\r
84  * @constructor\r
85  * Create a new ComboBox.\r
86  * @param {Object} config Configuration options\r
87  * @xtype combo\r
88  */\r
89 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {\r
90     <div id="cfg-Ext.form.ComboBox-transform"></div>/**\r
91      * @cfg {Mixed} transform The id, DOM node or element of an existing HTML SELECT to convert to a ComboBox.\r
92      * Note that if you specify this and the combo is going to be in an {@link Ext.form.BasicForm} or\r
93      * {@link Ext.form.FormPanel}, you must also set <tt>{@link #lazyRender} = true</tt>.\r
94      */\r
95     <div id="cfg-Ext.form.ComboBox-lazyRender"></div>/**\r
96      * @cfg {Boolean} lazyRender <tt>true</tt> to prevent the ComboBox from rendering until requested\r
97      * (should always be used when rendering into an {@link Ext.Editor} (e.g. {@link Ext.grid.EditorGridPanel Grids}),\r
98      * defaults to <tt>false</tt>).\r
99      */\r
100     <div id="cfg-Ext.form.ComboBox-autoCreate"></div>/**\r
101      * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or <tt>true</tt> for a default\r
102      * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.\r
103      * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>\r
104      * <pre><code>{tag: "input", type: "text", size: "24", autocomplete: "off"}</code></pre>\r
105      */\r
106     <div id="cfg-Ext.form.ComboBox-store"></div>/**\r
107      * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to <tt>undefined</tt>).\r
108      * Acceptable values for this property are:\r
109      * <div class="mdetail-params"><ul>\r
110      * <li><b>any {@link Ext.data.Store Store} subclass</b></li>\r
111      * <li><b>an Array</b> : Arrays will be converted to a {@link Ext.data.ArrayStore} internally,\r
112      * automatically generating {@link Ext.data.Field#name field names} to work with all data components.\r
113      * <div class="mdetail-params"><ul>\r
114      * <li><b>1-dimensional array</b> : (e.g., <tt>['Foo','Bar']</tt>)<div class="sub-desc">\r
115      * A 1-dimensional array will automatically be expanded (each array item will be used for both the combo\r
116      * {@link #valueField} and {@link #displayField})</div></li>\r
117      * <li><b>2-dimensional array</b> : (e.g., <tt>[['f','Foo'],['b','Bar']]</tt>)<div class="sub-desc">\r
118      * For a multi-dimensional array, the value in index 0 of each item will be assumed to be the combo\r
119      * {@link #valueField}, while the value at index 1 is assumed to be the combo {@link #displayField}.\r
120      * </div></li></ul></div></li></ul></div>\r
121      * <p>See also <tt>{@link #mode}</tt>.</p>\r
122      */\r
123     <div id="cfg-Ext.form.ComboBox-title"></div>/**\r
124      * @cfg {String} title If supplied, a header element is created containing this text and added into the top of\r
125      * the dropdown list (defaults to undefined, with no header element)\r
126      */\r
127 \r
128     // private\r
129     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},\r
130     <div id="cfg-Ext.form.ComboBox-listWidth"></div>/**\r
131      * @cfg {Number} listWidth The width (used as a parameter to {@link Ext.Element#setWidth}) of the dropdown\r
132      * list (defaults to the width of the ComboBox field).  See also <tt>{@link #minListWidth}\r
133      */\r
134     <div id="cfg-Ext.form.ComboBox-displayField"></div>/**\r
135      * @cfg {String} displayField The underlying {@link Ext.data.Field#name data field name} to bind to this\r
136      * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'field1'</tt> if\r
137      * {@link #transform transforming a select} or if the {@link #store field name is autogenerated based on\r
138      * the store configuration}).\r
139      * <p>See also <tt>{@link #valueField}</tt>.</p>\r
140      * <p><b>Note</b>: if using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a\r
141      * {@link Ext.grid.Column#renderer renderer} will be needed to show the displayField when the editor is not\r
142      * active.</p>\r
143      */\r
144     <div id="cfg-Ext.form.ComboBox-valueField"></div>/**\r
145      * @cfg {String} valueField The underlying {@link Ext.data.Field#name data value name} to bind to this\r
146      * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'field2'</tt> if\r
147      * {@link #transform transforming a select} or if the {@link #store field name is autogenerated based on\r
148      * the store configuration}).\r
149      * <p><b>Note</b>: use of a <tt>valueField</tt> requires the user to make a selection in order for a value to be\r
150      * mapped.  See also <tt>{@link #hiddenName}</tt>, <tt>{@link #hiddenValue}</tt>, and <tt>{@link #displayField}</tt>.</p>\r
151      */\r
152     <div id="cfg-Ext.form.ComboBox-hiddenName"></div>/**\r
153      * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the\r
154      * field's data value (defaults to the underlying DOM element's name). Required for the combo's value to automatically\r
155      * post during a form submission.  See also {@link #valueField}.\r
156      * <p><b>Note</b>: the hidden field's id will also default to this name if {@link #hiddenId} is not specified.\r
157      * The ComboBox {@link Ext.Component#id id} and the <tt>{@link #hiddenId}</tt> <b>should be different</b>, since\r
158      * no two DOM nodes should share the same id.  So, if the ComboBox <tt>{@link Ext.form.Field#name name}</tt> and\r
159      * <tt>hiddenName</tt> are the same, you should specify a unique <tt>{@link #hiddenId}</tt>.</p>\r
160      */\r
161     <div id="cfg-Ext.form.ComboBox-hiddenId"></div>/**\r
162      * @cfg {String} hiddenId If <tt>{@link #hiddenName}</tt> is specified, <tt>hiddenId</tt> can also be provided\r
163      * to give the hidden field a unique id (defaults to the <tt>{@link #hiddenName}</tt>).  The <tt>hiddenId</tt>\r
164      * and combo {@link Ext.Component#id id} should be different, since no two DOM\r
165      * nodes should share the same id.\r
166      */\r
167     <div id="cfg-Ext.form.ComboBox-hiddenValue"></div>/**\r
168      * @cfg {String} hiddenValue Sets the initial value of the hidden field if {@link #hiddenName} is\r
169      * specified to contain the selected {@link #valueField}, from the Store. Defaults to the configured\r
170      * <tt>{@link Ext.form.Field#value value}</tt>.\r
171      */\r
172     <div id="cfg-Ext.form.ComboBox-listClass"></div>/**\r
173      * @cfg {String} listClass The CSS class to add to the predefined <tt>'x-combo-list'</tt> class\r
174      * applied the dropdown list element (defaults to '').\r
175      */\r
176     listClass : '',\r
177     <div id="cfg-Ext.form.ComboBox-selectedClass"></div>/**\r
178      * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list\r
179      * (defaults to <tt>'x-combo-selected'</tt>)\r
180      */\r
181     selectedClass : 'x-combo-selected',\r
182     <div id="cfg-Ext.form.ComboBox-listEmptyText"></div>/**\r
183      * @cfg {String} listEmptyText The empty text to display in the data view if no items are found.\r
184      * (defaults to '')\r
185      */\r
186     listEmptyText: '',\r
187     <div id="cfg-Ext.form.ComboBox-triggerClass"></div>/**\r
188      * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always\r
189      * get the class <tt>'x-form-trigger'</tt> and <tt>triggerClass</tt> will be <b>appended</b> if specified\r
190      * (defaults to <tt>'x-form-arrow-trigger'</tt> which displays a downward arrow icon).\r
191      */\r
192     triggerClass : 'x-form-arrow-trigger',\r
193     <div id="cfg-Ext.form.ComboBox-shadow"></div>/**\r
194      * @cfg {Boolean/String} shadow <tt>true</tt> or <tt>"sides"</tt> for the default effect, <tt>"frame"</tt> for\r
195      * 4-way shadow, and <tt>"drop"</tt> for bottom-right\r
196      */\r
197     shadow : 'sides',\r
198     <div id="cfg-Ext.form.ComboBox-listAlign"></div>/**\r
199      * @cfg {String} listAlign A valid anchor position value. See <tt>{@link Ext.Element#alignTo}</tt> for details\r
200      * on supported anchor positions (defaults to <tt>'tl-bl?'</tt>)\r
201      */\r
202     listAlign : 'tl-bl?',\r
203     <div id="cfg-Ext.form.ComboBox-maxHeight"></div>/**\r
204      * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown\r
205      * (defaults to <tt>300</tt>)\r
206      */\r
207     maxHeight : 300,\r
208     <div id="cfg-Ext.form.ComboBox-minHeight"></div>/**\r
209      * @cfg {Number} minHeight The minimum height in pixels of the dropdown list when the list is constrained by its\r
210      * distance to the viewport edges (defaults to <tt>90</tt>)\r
211      */\r
212     minHeight : 90,\r
213     <div id="cfg-Ext.form.ComboBox-triggerAction"></div>/**\r
214      * @cfg {String} triggerAction The action to execute when the trigger is clicked.\r
215      * <div class="mdetail-params"><ul>\r
216      * <li><b><tt>'query'</tt></b> : <b>Default</b>\r
217      * <p class="sub-desc">{@link #doQuery run the query} using the {@link Ext.form.Field#getRawValue raw value}.</p></li>\r
218      * <li><b><tt>'all'</tt></b> :\r
219      * <p class="sub-desc">{@link #doQuery run the query} specified by the <tt>{@link #allQuery}</tt> config option</p></li>\r
220      * </ul></div>\r
221      * <p>See also <code>{@link #queryParam}</code>.</p>\r
222      */\r
223     triggerAction : 'query',\r
224     <div id="cfg-Ext.form.ComboBox-minChars"></div>/**\r
225      * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and\r
226      * {@link #typeAhead} activate (defaults to <tt>4</tt> if <tt>{@link #mode} = 'remote'</tt> or <tt>0</tt> if\r
227      * <tt>{@link #mode} = 'local'</tt>, does not apply if\r
228      * <tt>{@link Ext.form.TriggerField#editable editable} = false</tt>).\r
229      */\r
230     minChars : 4,\r
231     <div id="cfg-Ext.form.ComboBox-typeAhead"></div>/**\r
232      * @cfg {Boolean} typeAhead <tt>true</tt> to populate and autoselect the remainder of the text being\r
233      * typed after a configurable delay ({@link #typeAheadDelay}) if it matches a known value (defaults\r
234      * to <tt>false</tt>)\r
235      */\r
236     typeAhead : false,\r
237     <div id="cfg-Ext.form.ComboBox-queryDelay"></div>/**\r
238      * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and\r
239      * sending the query to filter the dropdown list (defaults to <tt>500</tt> if <tt>{@link #mode} = 'remote'</tt>\r
240      * or <tt>10</tt> if <tt>{@link #mode} = 'local'</tt>)\r
241      */\r
242     queryDelay : 500,\r
243     <div id="cfg-Ext.form.ComboBox-pageSize"></div>/**\r
244      * @cfg {Number} pageSize If greater than <tt>0</tt>, a {@link Ext.PagingToolbar} is displayed in the\r
245      * footer of the dropdown list and the {@link #doQuery filter queries} will execute with page start and\r
246      * {@link Ext.PagingToolbar#pageSize limit} parameters. Only applies when <tt>{@link #mode} = 'remote'</tt>\r
247      * (defaults to <tt>0</tt>).\r
248      */\r
249     pageSize : 0,\r
250     <div id="cfg-Ext.form.ComboBox-selectOnFocus"></div>/**\r
251      * @cfg {Boolean} selectOnFocus <tt>true</tt> to select any existing text in the field immediately on focus.\r
252      * Only applies when <tt>{@link Ext.form.TriggerField#editable editable} = true</tt> (defaults to\r
253      * <tt>false</tt>).\r
254      */\r
255     selectOnFocus : false,\r
256     <div id="cfg-Ext.form.ComboBox-queryParam"></div>/**\r
257      * @cfg {String} queryParam Name of the query ({@link Ext.data.Store#baseParam baseParam} name for the store)\r
258      * as it will be passed on the querystring (defaults to <tt>'query'</tt>)\r
259      */\r
260     queryParam : 'query',\r
261     <div id="cfg-Ext.form.ComboBox-loadingText"></div>/**\r
262      * @cfg {String} loadingText The text to display in the dropdown list while data is loading.  Only applies\r
263      * when <tt>{@link #mode} = 'remote'</tt> (defaults to <tt>'Loading...'</tt>)\r
264      */\r
265     loadingText : 'Loading...',\r
266     <div id="cfg-Ext.form.ComboBox-resizable"></div>/**\r
267      * @cfg {Boolean} resizable <tt>true</tt> to add a resize handle to the bottom of the dropdown list\r
268      * (creates an {@link Ext.Resizable} with 'se' {@link Ext.Resizable#pinned pinned} handles).\r
269      * Defaults to <tt>false</tt>.\r
270      */\r
271     resizable : false,\r
272     <div id="cfg-Ext.form.ComboBox-handleHeight"></div>/**\r
273      * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if\r
274      * <tt>{@link #resizable} = true</tt> (defaults to <tt>8</tt>)\r
275      */\r
276     handleHeight : 8,\r
277     <div id="cfg-Ext.form.ComboBox-allQuery"></div>/**\r
278      * @cfg {String} allQuery The text query to send to the server to return all records for the list\r
279      * with no filtering (defaults to '')\r
280      */\r
281     allQuery: '',\r
282     <div id="cfg-Ext.form.ComboBox-mode"></div>/**\r
283      * @cfg {String} mode Acceptable values are:\r
284      * <div class="mdetail-params"><ul>\r
285      * <li><b><tt>'remote'</tt></b> : <b>Default</b>\r
286      * <p class="sub-desc">Automatically loads the <tt>{@link #store}</tt> the <b>first</b> time the trigger\r
287      * is clicked. If you do not want the store to be automatically loaded the first time the trigger is\r
288      * clicked, set to <tt>'local'</tt> and manually load the store.  To force a requery of the store\r
289      * <b>every</b> time the trigger is clicked see <tt>{@link #lastQuery}</tt>.</p></li>\r
290      * <li><b><tt>'local'</tt></b> :\r
291      * <p class="sub-desc">ComboBox loads local data</p>\r
292      * <pre><code>\r
293 var combo = new Ext.form.ComboBox({\r
294     renderTo: document.body,\r
295     mode: 'local',\r
296     store: new Ext.data.ArrayStore({\r
297         id: 0,\r
298         fields: [\r
299             'myId',  // numeric value is the key\r
300             'displayText'\r
301         ],\r
302         data: [[1, 'item1'], [2, 'item2']]  // data is local\r
303     }),\r
304     valueField: 'myId',\r
305     displayField: 'displayText',\r
306     triggerAction: 'all'\r
307 });\r
308      * </code></pre></li>\r
309      * </ul></div>\r
310      */\r
311     mode: 'remote',\r
312     <div id="cfg-Ext.form.ComboBox-minListWidth"></div>/**\r
313      * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to <tt>70</tt>, will\r
314      * be ignored if <tt>{@link #listWidth}</tt> has a higher value)\r
315      */\r
316     minListWidth : 70,\r
317     <div id="cfg-Ext.form.ComboBox-forceSelection"></div>/**\r
318      * @cfg {Boolean} forceSelection <tt>true</tt> to restrict the selected value to one of the values in the list,\r
319      * <tt>false</tt> to allow the user to set arbitrary text into the field (defaults to <tt>false</tt>)\r
320      */\r
321     forceSelection : false,\r
322     <div id="cfg-Ext.form.ComboBox-typeAheadDelay"></div>/**\r
323      * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed\r
324      * if <tt>{@link #typeAhead} = true</tt> (defaults to <tt>250</tt>)\r
325      */\r
326     typeAheadDelay : 250,\r
327     <div id="cfg-Ext.form.ComboBox-valueNotFoundText"></div>/**\r
328      * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in\r
329      * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined). If this\r
330      * default text is used, it means there is no value set and no validation will occur on this field.\r
331      */\r
332 \r
333     <div id="cfg-Ext.form.ComboBox-lazyInit"></div>/**\r
334      * @cfg {Boolean} lazyInit <tt>true</tt> to not initialize the list for this combo until the field is focused\r
335      * (defaults to <tt>true</tt>)\r
336      */\r
337     lazyInit : true,\r
338 \r
339     <div id="prop-Ext.form.ComboBox-lastQuery"></div>/**\r
340      * The value of the match string used to filter the store. Delete this property to force a requery.\r
341      * Example use:\r
342      * <pre><code>\r
343 var combo = new Ext.form.ComboBox({\r
344     ...\r
345     mode: 'remote',\r
346     ...\r
347     listeners: {\r
348         // delete the previous query in the beforequery event or set\r
349         // combo.lastQuery = null (this will reload the store the next time it expands)\r
350         beforequery: function(qe){\r
351             delete qe.combo.lastQuery;\r
352         }\r
353     }\r
354 });\r
355      * </code></pre>\r
356      * To make sure the filter in the store is not cleared the first time the ComboBox trigger is used\r
357      * configure the combo with <tt>lastQuery=''</tt>. Example use:\r
358      * <pre><code>\r
359 var combo = new Ext.form.ComboBox({\r
360     ...\r
361     mode: 'local',\r
362     triggerAction: 'all',\r
363     lastQuery: ''\r
364 });\r
365      * </code></pre>\r
366      * @property lastQuery\r
367      * @type String\r
368      */\r
369 \r
370     // private\r
371     initComponent : function(){\r
372         Ext.form.ComboBox.superclass.initComponent.call(this);\r
373         this.addEvents(\r
374             <div id="event-Ext.form.ComboBox-expand"></div>/**\r
375              * @event expand\r
376              * Fires when the dropdown list is expanded\r
377              * @param {Ext.form.ComboBox} combo This combo box\r
378              */\r
379             'expand',\r
380             <div id="event-Ext.form.ComboBox-collapse"></div>/**\r
381              * @event collapse\r
382              * Fires when the dropdown list is collapsed\r
383              * @param {Ext.form.ComboBox} combo This combo box\r
384              */\r
385             'collapse',\r
386             <div id="event-Ext.form.ComboBox-beforeselect"></div>/**\r
387              * @event beforeselect\r
388              * Fires before a list item is selected. Return false to cancel the selection.\r
389              * @param {Ext.form.ComboBox} combo This combo box\r
390              * @param {Ext.data.Record} record The data record returned from the underlying store\r
391              * @param {Number} index The index of the selected item in the dropdown list\r
392              */\r
393             'beforeselect',\r
394             <div id="event-Ext.form.ComboBox-select"></div>/**\r
395              * @event select\r
396              * Fires when a list item is selected\r
397              * @param {Ext.form.ComboBox} combo This combo box\r
398              * @param {Ext.data.Record} record The data record returned from the underlying store\r
399              * @param {Number} index The index of the selected item in the dropdown list\r
400              */\r
401             'select',\r
402             <div id="event-Ext.form.ComboBox-beforequery"></div>/**\r
403              * @event beforequery\r
404              * Fires before all queries are processed. Return false to cancel the query or set the queryEvent's\r
405              * cancel property to true.\r
406              * @param {Object} queryEvent An object that has these properties:<ul>\r
407              * <li><code>combo</code> : Ext.form.ComboBox <div class="sub-desc">This combo box</div></li>\r
408              * <li><code>query</code> : String <div class="sub-desc">The query</div></li>\r
409              * <li><code>forceAll</code> : Boolean <div class="sub-desc">True to force "all" query</div></li>\r
410              * <li><code>cancel</code> : Boolean <div class="sub-desc">Set to true to cancel the query</div></li>\r
411              * </ul>\r
412              */\r
413             'beforequery'\r
414         );\r
415         if(this.transform){\r
416             var s = Ext.getDom(this.transform);\r
417             if(!this.hiddenName){\r
418                 this.hiddenName = s.name;\r
419             }\r
420             if(!this.store){\r
421                 this.mode = 'local';\r
422                 var d = [], opts = s.options;\r
423                 for(var i = 0, len = opts.length;i < len; i++){\r
424                     var o = opts[i],\r
425                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;\r
426                     if(o.selected && Ext.isEmpty(this.value, true)) {\r
427                         this.value = value;\r
428                     }\r
429                     d.push([value, o.text]);\r
430                 }\r
431                 this.store = new Ext.data.ArrayStore({\r
432                     'id': 0,\r
433                     fields: ['value', 'text'],\r
434                     data : d,\r
435                     autoDestroy: true\r
436                 });\r
437                 this.valueField = 'value';\r
438                 this.displayField = 'text';\r
439             }\r
440             s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference\r
441             if(!this.lazyRender){\r
442                 this.target = true;\r
443                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);\r
444                 this.render(this.el.parentNode, s);\r
445                 Ext.removeNode(s); // remove it\r
446             }else{\r
447                 Ext.removeNode(s); // remove it\r
448             }\r
449         }\r
450         //auto-configure store from local array data\r
451         else if(this.store){\r
452             this.store = Ext.StoreMgr.lookup(this.store);\r
453             if(this.store.autoCreated){\r
454                 this.displayField = this.valueField = 'field1';\r
455                 if(!this.store.expandData){\r
456                     this.displayField = 'field2';\r
457                 }\r
458                 this.mode = 'local';\r
459             }\r
460         }\r
461 \r
462         this.selectedIndex = -1;\r
463         if(this.mode == 'local'){\r
464             if(!Ext.isDefined(this.initialConfig.queryDelay)){\r
465                 this.queryDelay = 10;\r
466             }\r
467             if(!Ext.isDefined(this.initialConfig.minChars)){\r
468                 this.minChars = 0;\r
469             }\r
470         }\r
471     },\r
472 \r
473     // private\r
474     onRender : function(ct, position){\r
475         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);\r
476         if(this.hiddenName){\r
477             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,\r
478                     id: (this.hiddenId||this.hiddenName)}, 'before', true);\r
479 \r
480             // prevent input submission\r
481             this.el.dom.removeAttribute('name');\r
482         }\r
483         if(Ext.isGecko){\r
484             this.el.dom.setAttribute('autocomplete', 'off');\r
485         }\r
486 \r
487         if(!this.lazyInit){\r
488             this.initList();\r
489         }else{\r
490             this.on('focus', this.initList, this, {single: true});\r
491         }\r
492     },\r
493 \r
494     // private\r
495     initValue : function(){\r
496         Ext.form.ComboBox.superclass.initValue.call(this);\r
497         if(this.hiddenField){\r
498             this.hiddenField.value =\r
499                 Ext.isDefined(this.hiddenValue) ? this.hiddenValue :\r
500                 Ext.isDefined(this.value) ? this.value : '';\r
501         }\r
502     },\r
503 \r
504     // private\r
505     initList : function(){\r
506         if(!this.list){\r
507             var cls = 'x-combo-list';\r
508 \r
509             this.list = new Ext.Layer({\r
510                 parentEl: this.getListParent(),\r
511                 shadow: this.shadow,\r
512                 cls: [cls, this.listClass].join(' '),\r
513                 constrain:false\r
514             });\r
515 \r
516             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);\r
517             this.list.setSize(lw, 0);\r
518             this.list.swallowEvent('mousewheel');\r
519             this.assetHeight = 0;\r
520             if(this.syncFont !== false){\r
521                 this.list.setStyle('font-size', this.el.getStyle('font-size'));\r
522             }\r
523             if(this.title){\r
524                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});\r
525                 this.assetHeight += this.header.getHeight();\r
526             }\r
527 \r
528             this.innerList = this.list.createChild({cls:cls+'-inner'});\r
529             this.mon(this.innerList, 'mouseover', this.onViewOver, this);\r
530             this.mon(this.innerList, 'mousemove', this.onViewMove, this);\r
531             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
532 \r
533             if(this.pageSize){\r
534                 this.footer = this.list.createChild({cls:cls+'-ft'});\r
535                 this.pageTb = new Ext.PagingToolbar({\r
536                     store: this.store,\r
537                     pageSize: this.pageSize,\r
538                     renderTo:this.footer\r
539                 });\r
540                 this.assetHeight += this.footer.getHeight();\r
541             }\r
542 \r
543             if(!this.tpl){\r
544                 <div id="cfg-Ext.form.ComboBox-tpl"></div>/**\r
545                 * @cfg {String/Ext.XTemplate} tpl <p>The template string, or {@link Ext.XTemplate} instance to\r
546                 * use to display each item in the dropdown list. The dropdown list is displayed in a\r
547                 * DataView. See {@link #view}.</p>\r
548                 * <p>The default template string is:</p><pre><code>\r
549                   '&lt;tpl for=".">&lt;div class="x-combo-list-item">{' + this.displayField + '}&lt;/div>&lt;/tpl>'\r
550                 * </code></pre>\r
551                 * <p>Override the default value to create custom UI layouts for items in the list.\r
552                 * For example:</p><pre><code>\r
553                   '&lt;tpl for=".">&lt;div ext:qtip="{state}. {nick}" class="x-combo-list-item">{state}&lt;/div>&lt;/tpl>'\r
554                 * </code></pre>\r
555                 * <p>The template <b>must</b> contain one or more substitution parameters using field\r
556                 * names from the Combo's</b> {@link #store Store}. In the example above an\r
557                 * <pre>ext:qtip</pre> attribute is added to display other fields from the Store.</p>\r
558                 * <p>To preserve the default visual look of list items, add the CSS class name\r
559                 * <pre>x-combo-list-item</pre> to the template's container element.</p>\r
560                 * <p>Also see {@link #itemSelector} for additional details.</p>\r
561                 */\r
562                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';\r
563                 <div id="cfg-Ext.form.ComboBox-itemSelector"></div>/**\r
564                  * @cfg {String} itemSelector\r
565                  * <p>A simple CSS selector (e.g. div.some-class or span:first-child) that will be\r
566                  * used to determine what nodes the {@link #view Ext.DataView} which handles the dropdown\r
567                  * display will be working with.</p>\r
568                  * <p><b>Note</b>: this setting is <b>required</b> if a custom XTemplate has been\r
569                  * specified in {@link #tpl} which assigns a class other than <pre>'x-combo-list-item'</pre>\r
570                  * to dropdown list items</b>\r
571                  */\r
572             }\r
573 \r
574             <div id="prop-Ext.form.ComboBox-view"></div>/**\r
575             * The {@link Ext.DataView DataView} used to display the ComboBox's options.\r
576             * @type Ext.DataView\r
577             */\r
578             this.view = new Ext.DataView({\r
579                 applyTo: this.innerList,\r
580                 tpl: this.tpl,\r
581                 singleSelect: true,\r
582                 selectedClass: this.selectedClass,\r
583                 itemSelector: this.itemSelector || '.' + cls + '-item',\r
584                 emptyText: this.listEmptyText\r
585             });\r
586 \r
587             this.mon(this.view, 'click', this.onViewClick, this);\r
588 \r
589             this.bindStore(this.store, true);\r
590 \r
591             if(this.resizable){\r
592                 this.resizer = new Ext.Resizable(this.list,  {\r
593                    pinned:true, handles:'se'\r
594                 });\r
595                 this.mon(this.resizer, 'resize', function(r, w, h){\r
596                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;\r
597                     this.listWidth = w;\r
598                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));\r
599                     this.restrictHeight();\r
600                 }, this);\r
601 \r
602                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');\r
603             }\r
604         }\r
605     },\r
606 \r
607     <div id="method-Ext.form.ComboBox-getListParent"></div>/**\r
608      * <p>Returns the element used to house this ComboBox's pop-up list. Defaults to the document body.</p>\r
609      * A custom implementation may be provided as a configuration option if the floating list needs to be rendered\r
610      * to a different Element. An example might be rendering the list inside a Menu so that clicking\r
611      * the list does not hide the Menu:<pre><code>\r
612 var store = new Ext.data.ArrayStore({\r
613     autoDestroy: true,\r
614     fields: ['initials', 'fullname'],\r
615     data : [\r
616         ['FF', 'Fred Flintstone'],\r
617         ['BR', 'Barney Rubble']\r
618     ]\r
619 });\r
620 \r
621 var combo = new Ext.form.ComboBox({\r
622     store: store,\r
623     displayField: 'fullname',\r
624     emptyText: 'Select a name...',\r
625     forceSelection: true,\r
626     getListParent: function() {\r
627         return this.el.up('.x-menu');\r
628     },\r
629     iconCls: 'no-icon', //use iconCls if placing within menu to shift to right side of menu\r
630     mode: 'local',\r
631     selectOnFocus: true,\r
632     triggerAction: 'all',\r
633     typeAhead: true,\r
634     width: 135\r
635 });\r
636 \r
637 var menu = new Ext.menu.Menu({\r
638     id: 'mainMenu',\r
639     items: [\r
640         combo // A Field in a Menu\r
641     ]\r
642 });\r
643 </code></pre>\r
644      */\r
645     getListParent : function() {\r
646         return document.body;\r
647     },\r
648 \r
649     <div id="method-Ext.form.ComboBox-getStore"></div>/**\r
650      * Returns the store associated with this combo.\r
651      * @return {Ext.data.Store} The store\r
652      */\r
653     getStore : function(){\r
654         return this.store;\r
655     },\r
656 \r
657     // private\r
658     bindStore : function(store, initial){\r
659         if(this.store && !initial){\r
660             if(this.store !== store && this.store.autoDestroy){\r
661                 this.store.destroy();\r
662             }else{\r
663                 this.store.un('beforeload', this.onBeforeLoad, this);\r
664                 this.store.un('load', this.onLoad, this);\r
665                 this.store.un('exception', this.collapse, this);\r
666             }\r
667             if(!store){\r
668                 this.store = null;\r
669                 if(this.view){\r
670                     this.view.bindStore(null);\r
671                 }\r
672                 if(this.pageTb){\r
673                     this.pageTb.bindStore(null);\r
674                 }\r
675             }\r
676         }\r
677         if(store){\r
678             if(!initial) {\r
679                 this.lastQuery = null;\r
680                 if(this.pageTb) {\r
681                     this.pageTb.bindStore(store);\r
682                 }\r
683             }\r
684 \r
685             this.store = Ext.StoreMgr.lookup(store);\r
686             this.store.on({\r
687                 scope: this,\r
688                 beforeload: this.onBeforeLoad,\r
689                 load: this.onLoad,\r
690                 exception: this.collapse\r
691             });\r
692 \r
693             if(this.view){\r
694                 this.view.bindStore(store);\r
695             }\r
696         }\r
697     },\r
698 \r
699     // private\r
700     initEvents : function(){\r
701         Ext.form.ComboBox.superclass.initEvents.call(this);\r
702 \r
703         this.keyNav = new Ext.KeyNav(this.el, {\r
704             "up" : function(e){\r
705                 this.inKeyMode = true;\r
706                 this.selectPrev();\r
707             },\r
708 \r
709             "down" : function(e){\r
710                 if(!this.isExpanded()){\r
711                     this.onTriggerClick();\r
712                 }else{\r
713                     this.inKeyMode = true;\r
714                     this.selectNext();\r
715                 }\r
716             },\r
717 \r
718             "enter" : function(e){\r
719                 this.onViewClick();\r
720             },\r
721 \r
722             "esc" : function(e){\r
723                 this.collapse();\r
724             },\r
725 \r
726             "tab" : function(e){\r
727                 this.onViewClick(false);\r
728                 return true;\r
729             },\r
730 \r
731             scope : this,\r
732 \r
733             doRelay : function(e, h, hname){\r
734                 if(hname == 'down' || this.scope.isExpanded()){\r
735                     // this MUST be called before ComboBox#fireKey()\r
736                     var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);\r
737                     if(!Ext.isIE && Ext.EventManager.useKeydown){\r
738                         // call Combo#fireKey() for browsers which use keydown event (except IE)\r
739                         this.scope.fireKey(e);\r
740                     }\r
741                     return relay;\r
742                 }\r
743                 return true;\r
744             },\r
745 \r
746             forceKeyDown : true,\r
747             defaultEventAction: 'stopEvent'\r
748         });\r
749         this.queryDelay = Math.max(this.queryDelay || 10,\r
750                 this.mode == 'local' ? 10 : 250);\r
751         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);\r
752         if(this.typeAhead){\r
753             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);\r
754         }\r
755         if(this.editable !== false && !this.enableKeyEvents){\r
756             this.mon(this.el, 'keyup', this.onKeyUp, this);\r
757         }\r
758     },\r
759 \r
760     // private\r
761     onDestroy : function(){\r
762         if (this.dqTask){\r
763             this.dqTask.cancel();\r
764             this.dqTask = null;\r
765         }\r
766         this.bindStore(null);\r
767         Ext.destroy(\r
768             this.resizer,\r
769             this.view,\r
770             this.pageTb,\r
771             this.list\r
772         );\r
773         Ext.form.ComboBox.superclass.onDestroy.call(this);\r
774     },\r
775 \r
776     // private\r
777     fireKey : function(e){\r
778         if (!this.isExpanded()) {\r
779             Ext.form.ComboBox.superclass.fireKey.call(this, e);\r
780         }\r
781     },\r
782 \r
783     // private\r
784     onResize : function(w, h){\r
785         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);\r
786         if(this.isVisible() && this.list){\r
787             this.doResize(w);\r
788         }else{\r
789             this.bufferSize = w;\r
790         }\r
791     },\r
792     \r
793     doResize: function(w){\r
794         if(!Ext.isDefined(this.listWidth)){\r
795             var lw = Math.max(w, this.minListWidth);\r
796             this.list.setWidth(lw);\r
797             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
798         }    \r
799     },\r
800 \r
801     // private\r
802     onEnable : function(){\r
803         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);\r
804         if(this.hiddenField){\r
805             this.hiddenField.disabled = false;\r
806         }\r
807     },\r
808 \r
809     // private\r
810     onDisable : function(){\r
811         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);\r
812         if(this.hiddenField){\r
813             this.hiddenField.disabled = true;\r
814         }\r
815     },\r
816 \r
817     // private\r
818     onBeforeLoad : function(){\r
819         if(!this.hasFocus){\r
820             return;\r
821         }\r
822         this.innerList.update(this.loadingText ?\r
823                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');\r
824         this.restrictHeight();\r
825         this.selectedIndex = -1;\r
826     },\r
827 \r
828     // private\r
829     onLoad : function(){\r
830         if(!this.hasFocus){\r
831             return;\r
832         }\r
833         if(this.store.getCount() > 0 || this.listEmptyText){\r
834             this.expand();\r
835             this.restrictHeight();\r
836             if(this.lastQuery == this.allQuery){\r
837                 if(this.editable){\r
838                     this.el.dom.select();\r
839                 }\r
840                 if(!this.selectByValue(this.value, true)){\r
841                     this.select(0, true);\r
842                 }\r
843             }else{\r
844                 this.selectNext();\r
845                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){\r
846                     this.taTask.delay(this.typeAheadDelay);\r
847                 }\r
848             }\r
849         }else{\r
850             this.onEmptyResults();\r
851         }\r
852         //this.el.focus();\r
853     },\r
854 \r
855     // private\r
856     onTypeAhead : function(){\r
857         if(this.store.getCount() > 0){\r
858             var r = this.store.getAt(0);\r
859             var newValue = r.data[this.displayField];\r
860             var len = newValue.length;\r
861             var selStart = this.getRawValue().length;\r
862             if(selStart != len){\r
863                 this.setRawValue(newValue);\r
864                 this.selectText(selStart, newValue.length);\r
865             }\r
866         }\r
867     },\r
868 \r
869     // private\r
870     onSelect : function(record, index){\r
871         if(this.fireEvent('beforeselect', this, record, index) !== false){\r
872             this.setValue(record.data[this.valueField || this.displayField]);\r
873             this.collapse();\r
874             this.fireEvent('select', this, record, index);\r
875         }\r
876     },\r
877 \r
878     // inherit docs\r
879     getName: function(){\r
880         var hf = this.hiddenField;\r
881         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);\r
882     },\r
883 \r
884     <div id="method-Ext.form.ComboBox-getValue"></div>/**\r
885      * Returns the currently selected field value or empty string if no value is set.\r
886      * @return {String} value The selected value\r
887      */\r
888     getValue : function(){\r
889         if(this.valueField){\r
890             return Ext.isDefined(this.value) ? this.value : '';\r
891         }else{\r
892             return Ext.form.ComboBox.superclass.getValue.call(this);\r
893         }\r
894     },\r
895 \r
896     <div id="method-Ext.form.ComboBox-clearValue"></div>/**\r
897      * Clears any text/value currently set in the field\r
898      */\r
899     clearValue : function(){\r
900         if(this.hiddenField){\r
901             this.hiddenField.value = '';\r
902         }\r
903         this.setRawValue('');\r
904         this.lastSelectionText = '';\r
905         this.applyEmptyText();\r
906         this.value = '';\r
907     },\r
908 \r
909     <div id="method-Ext.form.ComboBox-setValue"></div>/**\r
910      * Sets the specified value into the field.  If the value finds a match, the corresponding record text\r
911      * will be displayed in the field.  If the value does not match the data value of an existing item,\r
912      * and the valueNotFoundText config option is defined, it will be displayed as the default field text.\r
913      * Otherwise the field will be blank (although the value will still be set).\r
914      * @param {String} value The value to match\r
915      * @return {Ext.form.Field} this\r
916      */\r
917     setValue : function(v){\r
918         var text = v;\r
919         if(this.valueField){\r
920             var r = this.findRecord(this.valueField, v);\r
921             if(r){\r
922                 text = r.data[this.displayField];\r
923             }else if(Ext.isDefined(this.valueNotFoundText)){\r
924                 text = this.valueNotFoundText;\r
925             }\r
926         }\r
927         this.lastSelectionText = text;\r
928         if(this.hiddenField){\r
929             this.hiddenField.value = v;\r
930         }\r
931         Ext.form.ComboBox.superclass.setValue.call(this, text);\r
932         this.value = v;\r
933         return this;\r
934     },\r
935 \r
936     // private\r
937     findRecord : function(prop, value){\r
938         var record;\r
939         if(this.store.getCount() > 0){\r
940             this.store.each(function(r){\r
941                 if(r.data[prop] == value){\r
942                     record = r;\r
943                     return false;\r
944                 }\r
945             });\r
946         }\r
947         return record;\r
948     },\r
949 \r
950     // private\r
951     onViewMove : function(e, t){\r
952         this.inKeyMode = false;\r
953     },\r
954 \r
955     // private\r
956     onViewOver : function(e, t){\r
957         if(this.inKeyMode){ // prevent key nav and mouse over conflicts\r
958             return;\r
959         }\r
960         var item = this.view.findItemFromChild(t);\r
961         if(item){\r
962             var index = this.view.indexOf(item);\r
963             this.select(index, false);\r
964         }\r
965     },\r
966 \r
967     // private\r
968     onViewClick : function(doFocus){\r
969         var index = this.view.getSelectedIndexes()[0],\r
970             s = this.store,\r
971             r = s.getAt(index);\r
972         if(r){\r
973             this.onSelect(r, index);\r
974         }else if(s.getCount() === 0){\r
975             this.onEmptyResults();\r
976         }\r
977         if(doFocus !== false){\r
978             this.el.focus();\r
979         }\r
980     },\r
981 \r
982     // private\r
983     restrictHeight : function(){\r
984         this.innerList.dom.style.height = '';\r
985         var inner = this.innerList.dom,\r
986             pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,\r
987             h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),\r
988             ha = this.getPosition()[1]-Ext.getBody().getScroll().top,\r
989             hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,\r
990             space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;\r
991             \r
992         h = Math.min(h, space, this.maxHeight);\r
993 \r
994         this.innerList.setHeight(h);\r
995         this.list.beginUpdate();\r
996         this.list.setHeight(h+pad);\r
997         this.list.alignTo(this.wrap, this.listAlign);\r
998         this.list.endUpdate();\r
999     },\r
1000 \r
1001     // private\r
1002     onEmptyResults : function(){\r
1003         this.collapse();\r
1004     },\r
1005 \r
1006     <div id="method-Ext.form.ComboBox-isExpanded"></div>/**\r
1007      * Returns true if the dropdown list is expanded, else false.\r
1008      */\r
1009     isExpanded : function(){\r
1010         return this.list && this.list.isVisible();\r
1011     },\r
1012 \r
1013     <div id="method-Ext.form.ComboBox-selectByValue"></div>/**\r
1014      * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.\r
1015      * The store must be loaded and the list expanded for this function to work, otherwise use setValue.\r
1016      * @param {String} value The data value of the item to select\r
1017      * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the\r
1018      * selected item if it is not currently in view (defaults to true)\r
1019      * @return {Boolean} True if the value matched an item in the list, else false\r
1020      */\r
1021     selectByValue : function(v, scrollIntoView){\r
1022         if(!Ext.isEmpty(v, true)){\r
1023             var r = this.findRecord(this.valueField || this.displayField, v);\r
1024             if(r){\r
1025                 this.select(this.store.indexOf(r), scrollIntoView);\r
1026                 return true;\r
1027             }\r
1028         }\r
1029         return false;\r
1030     },\r
1031 \r
1032     <div id="method-Ext.form.ComboBox-select"></div>/**\r
1033      * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.\r
1034      * The store must be loaded and the list expanded for this function to work, otherwise use setValue.\r
1035      * @param {Number} index The zero-based index of the list item to select\r
1036      * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the\r
1037      * selected item if it is not currently in view (defaults to true)\r
1038      */\r
1039     select : function(index, scrollIntoView){\r
1040         this.selectedIndex = index;\r
1041         this.view.select(index);\r
1042         if(scrollIntoView !== false){\r
1043             var el = this.view.getNode(index);\r
1044             if(el){\r
1045                 this.innerList.scrollChildIntoView(el, false);\r
1046             }\r
1047         }\r
1048     },\r
1049 \r
1050     // private\r
1051     selectNext : function(){\r
1052         var ct = this.store.getCount();\r
1053         if(ct > 0){\r
1054             if(this.selectedIndex == -1){\r
1055                 this.select(0);\r
1056             }else if(this.selectedIndex < ct-1){\r
1057                 this.select(this.selectedIndex+1);\r
1058             }\r
1059         }\r
1060     },\r
1061 \r
1062     // private\r
1063     selectPrev : function(){\r
1064         var ct = this.store.getCount();\r
1065         if(ct > 0){\r
1066             if(this.selectedIndex == -1){\r
1067                 this.select(0);\r
1068             }else if(this.selectedIndex !== 0){\r
1069                 this.select(this.selectedIndex-1);\r
1070             }\r
1071         }\r
1072     },\r
1073 \r
1074     // private\r
1075     onKeyUp : function(e){\r
1076         var k = e.getKey();\r
1077         if(this.editable !== false && (k == e.BACKSPACE || !e.isSpecialKey())){\r
1078             this.lastKey = k;\r
1079             this.dqTask.delay(this.queryDelay);\r
1080         }\r
1081         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);\r
1082     },\r
1083 \r
1084     // private\r
1085     validateBlur : function(){\r
1086         return !this.list || !this.list.isVisible();\r
1087     },\r
1088 \r
1089     // private\r
1090     initQuery : function(){\r
1091         this.doQuery(this.getRawValue());\r
1092     },\r
1093 \r
1094     // private\r
1095     beforeBlur : function(){\r
1096         var val = this.getRawValue(),\r
1097             rec = this.findRecord(this.displayField, val);\r
1098         if(!rec && this.forceSelection){\r
1099             if(val.length > 0 && val != this.emptyText){\r
1100                 this.el.dom.value = Ext.isDefined(this.lastSelectionText) ? this.lastSelectionText : '';\r
1101                 this.applyEmptyText();\r
1102             }else{\r
1103                 this.clearValue();\r
1104             }\r
1105         }else{\r
1106             if(rec){\r
1107                 val = rec.get(this.valueField || this.displayField);\r
1108             }\r
1109             this.setValue(val);\r
1110         }\r
1111     },\r
1112 \r
1113     <div id="method-Ext.form.ComboBox-doQuery"></div>/**\r
1114      * Execute a query to filter the dropdown list.  Fires the {@link #beforequery} event prior to performing the\r
1115      * query allowing the query action to be canceled if needed.\r
1116      * @param {String} query The SQL query to execute\r
1117      * @param {Boolean} forceAll <tt>true</tt> to force the query to execute even if there are currently fewer\r
1118      * characters in the field than the minimum specified by the <tt>{@link #minChars}</tt> config option.  It\r
1119      * also clears any filter previously saved in the current store (defaults to <tt>false</tt>)\r
1120      */\r
1121     doQuery : function(q, forceAll){\r
1122         q = Ext.isEmpty(q) ? '' : q;\r
1123         var qe = {\r
1124             query: q,\r
1125             forceAll: forceAll,\r
1126             combo: this,\r
1127             cancel:false\r
1128         };\r
1129         if(this.fireEvent('beforequery', qe)===false || qe.cancel){\r
1130             return false;\r
1131         }\r
1132         q = qe.query;\r
1133         forceAll = qe.forceAll;\r
1134         if(forceAll === true || (q.length >= this.minChars)){\r
1135             if(this.lastQuery !== q){\r
1136                 this.lastQuery = q;\r
1137                 if(this.mode == 'local'){\r
1138                     this.selectedIndex = -1;\r
1139                     if(forceAll){\r
1140                         this.store.clearFilter();\r
1141                     }else{\r
1142                         this.store.filter(this.displayField, q);\r
1143                     }\r
1144                     this.onLoad();\r
1145                 }else{\r
1146                     this.store.baseParams[this.queryParam] = q;\r
1147                     this.store.load({\r
1148                         params: this.getParams(q)\r
1149                     });\r
1150                     this.expand();\r
1151                 }\r
1152             }else{\r
1153                 this.selectedIndex = -1;\r
1154                 this.onLoad();\r
1155             }\r
1156         }\r
1157     },\r
1158 \r
1159     // private\r
1160     getParams : function(q){\r
1161         var p = {};\r
1162         //p[this.queryParam] = q;\r
1163         if(this.pageSize){\r
1164             p.start = 0;\r
1165             p.limit = this.pageSize;\r
1166         }\r
1167         return p;\r
1168     },\r
1169 \r
1170     <div id="method-Ext.form.ComboBox-collapse"></div>/**\r
1171      * Hides the dropdown list if it is currently expanded. Fires the {@link #collapse} event on completion.\r
1172      */\r
1173     collapse : function(){\r
1174         if(!this.isExpanded()){\r
1175             return;\r
1176         }\r
1177         this.list.hide();\r
1178         Ext.getDoc().un('mousewheel', this.collapseIf, this);\r
1179         Ext.getDoc().un('mousedown', this.collapseIf, this);\r
1180         this.fireEvent('collapse', this);\r
1181     },\r
1182 \r
1183     // private\r
1184     collapseIf : function(e){\r
1185         if(!e.within(this.wrap) && !e.within(this.list)){\r
1186             this.collapse();\r
1187         }\r
1188     },\r
1189 \r
1190     <div id="method-Ext.form.ComboBox-expand"></div>/**\r
1191      * Expands the dropdown list if it is currently hidden. Fires the {@link #expand} event on completion.\r
1192      */\r
1193     expand : function(){\r
1194         if(this.isExpanded() || !this.hasFocus){\r
1195             return;\r
1196         }\r
1197         if(this.bufferSize){\r
1198             this.doResize(this.bufferSize);\r
1199             delete this.bufferSize;\r
1200         }\r
1201         this.list.alignTo(this.wrap, this.listAlign);\r
1202         this.list.show();\r
1203         if(Ext.isGecko2){\r
1204             this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac\r
1205         }\r
1206         Ext.getDoc().on({\r
1207             scope: this,\r
1208             mousewheel: this.collapseIf,\r
1209             mousedown: this.collapseIf\r
1210         });\r
1211         this.fireEvent('expand', this);\r
1212     },\r
1213 \r
1214     <div id="method-Ext.form.ComboBox-onTriggerClick"></div>/**\r
1215      * @method onTriggerClick\r
1216      * @hide\r
1217      */\r
1218     // private\r
1219     // Implements the default empty TriggerField.onTriggerClick function\r
1220     onTriggerClick : function(){\r
1221         if(this.disabled){\r
1222             return;\r
1223         }\r
1224         if(this.isExpanded()){\r
1225             this.collapse();\r
1226             this.el.focus();\r
1227         }else {\r
1228             this.onFocus({});\r
1229             if(this.triggerAction == 'all') {\r
1230                 this.doQuery(this.allQuery, true);\r
1231             } else {\r
1232                 this.doQuery(this.getRawValue());\r
1233             }\r
1234             this.el.focus();\r
1235         }\r
1236     }\r
1237 \r
1238     <div id="method-Ext.form.ComboBox-autoSize"></div>/**\r
1239      * @hide\r
1240      * @method autoSize\r
1241      */\r
1242     <div id="cfg-Ext.form.ComboBox-grow"></div>/**\r
1243      * @cfg {Boolean} grow @hide\r
1244      */\r
1245     <div id="cfg-Ext.form.ComboBox-growMin"></div>/**\r
1246      * @cfg {Number} growMin @hide\r
1247      */\r
1248     <div id="cfg-Ext.form.ComboBox-growMax"></div>/**\r
1249      * @cfg {Number} growMax @hide\r
1250      */\r
1251 \r
1252 });\r
1253 Ext.reg('combo', Ext.form.ComboBox);</pre>
1254 </body>
1255 </html>