+++ /dev/null
-/*\r
- * Ext JS Library 2.2.1\r
- * Copyright(c) 2006-2009, Ext JS, LLC.\r
- * licensing@extjs.com\r
- * \r
- * http://extjs.com/license\r
- */\r
-\r
-/**\r
- * @class Ext.form.ComboBox\r
- * @extends Ext.form.TriggerField\r
- * <p>A combobox control with support for autocomplete, remote-loading, paging and many other features.</p>\r
- * A ComboBox works in a similar manner to a traditional HTML <select> field. The difference is that to submit the\r
- * {@link #valueField}, you must specify a {@link #hiddenName} to create a hidden input field to hold the\r
- * value of the valueField. The <i>{@link #displayField}</i> is shown in the text field which is named\r
- * according to the {@link #name}.\r
- * @constructor\r
- * Create a new ComboBox.\r
- * @param {Object} config Configuration options\r
- */\r
-Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {\r
- /**\r
- * @cfg {Mixed} transform The id, DOM node or element of an existing HTML SELECT to convert to a ComboBox.\r
- * Note that if you specify this and the combo is going to be in a {@link Ext.form.BasicForm} or\r
- * {@link Ext.form.FormPanel}, you must also set {@link #lazyRender} = true.\r
- */\r
- /**\r
- * @cfg {Boolean} lazyRender True to prevent the ComboBox from rendering until requested (should always be used when\r
- * rendering into an Ext.Editor, defaults to false).\r
- */\r
- /**\r
- * @cfg {Boolean/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to:\r
- * {tag: "input", type: "text", size: "24", autocomplete: "off"})\r
- */\r
- /**\r
- * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to undefined). This can be\r
- * any {@link Ext.data.Store} subclass, a 1-dimensional array (e.g., ['Foo','Bar']) or a 2-dimensional array (e.g.,\r
- * [['f','Foo'],['b','Bar']]). Arrays will be converted to a {@link Ext.data.SimpleStore} internally.\r
- * 1-dimensional arrays will automatically be expanded (each array item will be the combo value and text) and\r
- * for multi-dimensional arrays, the value in index 0 of each item will be assumed to be the combo value, while\r
- * the value at index 1 is assumed to be the combo text.\r
- */\r
- /**\r
- * @cfg {String} title If supplied, a header element is created containing this text and added into the top of\r
- * the dropdown list (defaults to undefined, with no header element)\r
- */\r
-\r
- // private\r
- defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},\r
- /**\r
- * @cfg {Number} listWidth The width in pixels of the dropdown list (defaults to the width of the ComboBox field)\r
- */\r
- /**\r
- * @cfg {String} displayField The underlying data field name to bind to this ComboBox (defaults to undefined if\r
- * mode = 'remote' or 'text' if transforming a select)\r
- */\r
- /**\r
- * @cfg {String} valueField The underlying data value name to bind to this ComboBox (defaults to undefined if\r
- * mode = 'remote' or 'value' if transforming a select) Note: use of a valueField requires the user to make a selection\r
- * in order for a value to be mapped.\r
- */\r
- /**\r
- * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the\r
- * field's data value (defaults to the underlying DOM element's name). Required for the combo's value to automatically\r
- * post during a form submission. Note that the hidden field's id will also default to this name if {@link #hiddenId}\r
- * is not specified. The combo's id and the hidden field's ids should be different, since no two DOM nodes should\r
- * share the same id, so if the combo and hidden names are the same, you should specify a unique hiddenId.\r
- */\r
- /**\r
- * @cfg {String} hiddenId If {@link #hiddenName} is specified, hiddenId can also be provided to give the hidden field\r
- * a unique id (defaults to the hiddenName). The hiddenId and combo {@link #id} should be different, since no two DOM\r
- * nodes should share the same id.\r
- */\r
- /**\r
- * @cfg {String} listClass CSS class to apply to the dropdown list element (defaults to '')\r
- */\r
- listClass: '',\r
- /**\r
- * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list (defaults to 'x-combo-selected')\r
- */\r
- selectedClass: 'x-combo-selected',\r
- /**\r
- * @cfg {String} triggerClass An additional CSS class used to style the trigger button. The trigger will always get the\r
- * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-arrow-trigger'\r
- * which displays a downward arrow icon).\r
- */\r
- triggerClass : 'x-form-arrow-trigger',\r
- /**\r
- * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right\r
- */\r
- shadow:'sides',\r
- /**\r
- * @cfg {String} listAlign A valid anchor position value. See {@link Ext.Element#alignTo} for details on supported\r
- * anchor positions (defaults to 'tl-bl')\r
- */\r
- listAlign: 'tl-bl?',\r
- /**\r
- * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown (defaults to 300)\r
- */\r
- maxHeight: 300,\r
- /**\r
- * @cfg {Number} minHeight The minimum height in pixels of the dropdown list when the list is constrained by its\r
- * distance to the viewport edges (defaults to 90)\r
- */\r
- minHeight: 90,\r
- /**\r
- * @cfg {String} triggerAction The action to execute when the trigger is clicked. Use 'all' to run the\r
- * query specified by the allQuery config option (defaults to 'query')\r
- */\r
- triggerAction: 'query',\r
- /**\r
- * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and typeahead activate\r
- * (defaults to 4 if remote or 0 if local, does not apply if editable = false)\r
- */\r
- minChars : 4,\r
- /**\r
- * @cfg {Boolean} typeAhead True to populate and autoselect the remainder of the text being typed after a configurable\r
- * delay ({@link #typeAheadDelay}) if it matches a known value (defaults to false)\r
- */\r
- typeAhead: false,\r
- /**\r
- * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and sending the\r
- * query to filter the dropdown list (defaults to 500 if mode = 'remote' or 10 if mode = 'local')\r
- */\r
- queryDelay: 500,\r
- /**\r
- * @cfg {Number} pageSize If greater than 0, a paging toolbar is displayed in the footer of the dropdown list and the\r
- * filter queries will execute with page start and limit parameters. Only applies when mode = 'remote' (defaults to 0)\r
- */\r
- pageSize: 0,\r
- /**\r
- * @cfg {Boolean} selectOnFocus True to select any existing text in the field immediately on focus. Only applies\r
- * when editable = true (defaults to false)\r
- */\r
- selectOnFocus:false,\r
- /**\r
- * @cfg {String} queryParam Name of the query as it will be passed on the querystring (defaults to 'query')\r
- */\r
- queryParam: 'query',\r
- /**\r
- * @cfg {String} loadingText The text to display in the dropdown list while data is loading. Only applies\r
- * when mode = 'remote' (defaults to 'Loading...')\r
- */\r
- loadingText: 'Loading...',\r
- /**\r
- * @cfg {Boolean} resizable True to add a resize handle to the bottom of the dropdown list (defaults to false)\r
- */\r
- resizable: false,\r
- /**\r
- * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if resizable = true (defaults to 8)\r
- */\r
- handleHeight : 8,\r
- /**\r
- * @cfg {Boolean} editable False to prevent the user from typing text directly into the field, just like a\r
- * traditional select (defaults to true)\r
- */\r
- editable: true,\r
- /**\r
- * @cfg {String} allQuery The text query to send to the server to return all records for the list with no filtering (defaults to '')\r
- */\r
- allQuery: '',\r
- /**\r
- * @cfg {String} mode Set to 'local' if the ComboBox loads local data (defaults to 'remote' which loads from the server)\r
- */\r
- mode: 'remote',\r
- /**\r
- * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to 70, will be ignored if\r
- * listWidth has a higher value)\r
- */\r
- minListWidth : 70,\r
- /**\r
- * @cfg {Boolean} forceSelection True to restrict the selected value to one of the values in the list, false to\r
- * allow the user to set arbitrary text into the field (defaults to false)\r
- */\r
- forceSelection:false,\r
- /**\r
- * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed\r
- * if typeAhead = true (defaults to 250)\r
- */\r
- typeAheadDelay : 250,\r
- /**\r
- * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in\r
- * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined). If this\r
- * defaut text is used, it means there is no value set and no validation will occur on this field.\r
- */\r
-\r
- /**\r
- * @cfg {Boolean} lazyInit True to not initialize the list for this combo until the field is focused (defaults to true)\r
- */\r
- lazyInit : true,\r
-\r
- /**\r
- * The value of the match string used to filter the store. Delete this property to force a requery.\r
- * @property lastQuery\r
- * @type String\r
- */\r
-\r
- // private\r
- initComponent : function(){\r
- Ext.form.ComboBox.superclass.initComponent.call(this);\r
- this.addEvents(\r
- /**\r
- * @event expand\r
- * Fires when the dropdown list is expanded\r
- * @param {Ext.form.ComboBox} combo This combo box\r
- */\r
- 'expand',\r
- /**\r
- * @event collapse\r
- * Fires when the dropdown list is collapsed\r
- * @param {Ext.form.ComboBox} combo This combo box\r
- */\r
- 'collapse',\r
- /**\r
- * @event beforeselect\r
- * Fires before a list item is selected. Return false to cancel the selection.\r
- * @param {Ext.form.ComboBox} combo This combo box\r
- * @param {Ext.data.Record} record The data record returned from the underlying store\r
- * @param {Number} index The index of the selected item in the dropdown list\r
- */\r
- 'beforeselect',\r
- /**\r
- * @event select\r
- * Fires when a list item is selected\r
- * @param {Ext.form.ComboBox} combo This combo box\r
- * @param {Ext.data.Record} record The data record returned from the underlying store\r
- * @param {Number} index The index of the selected item in the dropdown list\r
- */\r
- 'select',\r
- /**\r
- * @event beforequery\r
- * Fires before all queries are processed. Return false to cancel the query or set the queryEvent's\r
- * cancel property to true.\r
- * @param {Object} queryEvent An object that has these properties:<ul>\r
- * <li><code>combo</code> : Ext.form.ComboBox <div class="sub-desc">This combo box</div></li>\r
- * <li><code>query</code> : String <div class="sub-desc">The query</div></li>\r
- * <li><code>forceAll</code> : Boolean <div class="sub-desc">True to force "all" query</div></li>\r
- * <li><code>cancel</code> : Boolean <div class="sub-desc">Set to true to cancel the query</div></li>\r
- * </ul>\r
- */\r
- 'beforequery'\r
- );\r
- if(this.transform){\r
- this.allowDomMove = false;\r
- var s = Ext.getDom(this.transform);\r
- if(!this.hiddenName){\r
- this.hiddenName = s.name;\r
- }\r
- if(!this.store){\r
- this.mode = 'local';\r
- var d = [], opts = s.options;\r
- for(var i = 0, len = opts.length;i < len; i++){\r
- var o = opts[i];\r
- var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;\r
- if(o.selected) {\r
- this.value = value;\r
- }\r
- d.push([value, o.text]);\r
- }\r
- this.store = new Ext.data.SimpleStore({\r
- 'id': 0,\r
- fields: ['value', 'text'],\r
- data : d\r
- });\r
- this.valueField = 'value';\r
- this.displayField = 'text';\r
- }\r
- s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference\r
- if(!this.lazyRender){\r
- this.target = true;\r
- this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);\r
- Ext.removeNode(s); // remove it\r
- this.render(this.el.parentNode);\r
- }else{\r
- Ext.removeNode(s); // remove it\r
- }\r
- }\r
- //auto-configure store from local array data\r
- else if(Ext.isArray(this.store)){\r
- if (Ext.isArray(this.store[0])){\r
- this.store = new Ext.data.SimpleStore({\r
- fields: ['value','text'],\r
- data: this.store\r
- });\r
- this.valueField = 'value';\r
- }else{\r
- this.store = new Ext.data.SimpleStore({\r
- fields: ['text'],\r
- data: this.store,\r
- expandData: true\r
- });\r
- this.valueField = 'text';\r
- }\r
- this.displayField = 'text';\r
- this.mode = 'local';\r
- }\r
-\r
- this.selectedIndex = -1;\r
- if(this.mode == 'local'){\r
- if(this.initialConfig.queryDelay === undefined){\r
- this.queryDelay = 10;\r
- }\r
- if(this.initialConfig.minChars === undefined){\r
- this.minChars = 0;\r
- }\r
- }\r
- },\r
-\r
- // private\r
- onRender : function(ct, position){\r
- Ext.form.ComboBox.superclass.onRender.call(this, ct, position);\r
- if(this.hiddenName){\r
- this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,\r
- id: (this.hiddenId||this.hiddenName)}, 'before', true);\r
-\r
- // prevent input submission\r
- this.el.dom.removeAttribute('name');\r
- }\r
- if(Ext.isGecko){\r
- this.el.dom.setAttribute('autocomplete', 'off');\r
- }\r
-\r
- if(!this.lazyInit){\r
- this.initList();\r
- }else{\r
- this.on('focus', this.initList, this, {single: true});\r
- }\r
-\r
- if(!this.editable){\r
- this.editable = true;\r
- this.setEditable(false);\r
- }\r
- },\r
-\r
- // private\r
- initValue : function(){\r
- Ext.form.ComboBox.superclass.initValue.call(this);\r
- if(this.hiddenField){\r
- this.hiddenField.value =\r
- this.hiddenValue !== undefined ? this.hiddenValue :\r
- this.value !== undefined ? this.value : '';\r
- }\r
- },\r
-\r
- // private\r
- initList : function(){\r
- if(!this.list){\r
- var cls = 'x-combo-list';\r
-\r
- this.list = new Ext.Layer({\r
- shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false\r
- });\r
-\r
- var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);\r
- this.list.setWidth(lw);\r
- this.list.swallowEvent('mousewheel');\r
- this.assetHeight = 0;\r
-\r
- if(this.title){\r
- this.header = this.list.createChild({cls:cls+'-hd', html: this.title});\r
- this.assetHeight += this.header.getHeight();\r
- }\r
-\r
- this.innerList = this.list.createChild({cls:cls+'-inner'});\r
- this.innerList.on('mouseover', this.onViewOver, this);\r
- this.innerList.on('mousemove', this.onViewMove, this);\r
- this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
-\r
- if(this.pageSize){\r
- this.footer = this.list.createChild({cls:cls+'-ft'});\r
- this.pageTb = new Ext.PagingToolbar({\r
- store:this.store,\r
- pageSize: this.pageSize,\r
- renderTo:this.footer\r
- });\r
- this.assetHeight += this.footer.getHeight();\r
- }\r
-\r
- if(!this.tpl){\r
- /**\r
- * @cfg {String/Ext.XTemplate} tpl The template string, or {@link Ext.XTemplate}\r
- * instance to use to display each item in the dropdown list. Use\r
- * this to create custom UI layouts for items in the list.\r
- * <p>\r
- * If you wish to preserve the default visual look of list items, add the CSS\r
- * class name <pre>x-combo-list-item</pre> to the template's container element.\r
- * <p>\r
- * <b>The template must contain one or more substitution parameters using field\r
- * names from the Combo's</b> {@link #store Store}. An example of a custom template\r
- * would be adding an <pre>ext:qtip</pre> attribute which might display other fields\r
- * from the Store.\r
- * <p>\r
- * The dropdown list is displayed in a DataView. See {@link Ext.DataView} for details.\r
- */\r
- this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';\r
- /**\r
- * @cfg {String} itemSelector\r
- * <b>This setting is required if a custom XTemplate has been specified in {@link #tpl}\r
- * which assigns a class other than <pre>'x-combo-list-item'</pre> to dropdown list items</b>.\r
- * A simple CSS selector (e.g. div.some-class or span:first-child) that will be\r
- * used to determine what nodes the DataView which handles the dropdown display will\r
- * be working with.\r
- */\r
- }\r
-\r
- /**\r
- * The {@link Ext.DataView DataView} used to display the ComboBox's options.\r
- * @type Ext.DataView\r
- */\r
- this.view = new Ext.DataView({\r
- applyTo: this.innerList,\r
- tpl: this.tpl,\r
- singleSelect: true,\r
- selectedClass: this.selectedClass,\r
- itemSelector: this.itemSelector || '.' + cls + '-item'\r
- });\r
-\r
- this.view.on('click', this.onViewClick, this);\r
-\r
- this.bindStore(this.store, true);\r
-\r
- if(this.resizable){\r
- this.resizer = new Ext.Resizable(this.list, {\r
- pinned:true, handles:'se'\r
- });\r
- this.resizer.on('resize', function(r, w, h){\r
- this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;\r
- this.listWidth = w;\r
- this.innerList.setWidth(w - this.list.getFrameWidth('lr'));\r
- this.restrictHeight();\r
- }, this);\r
- this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');\r
- }\r
- }\r
- },\r
- \r
- /**\r
- * Returns the store associated with this combo.\r
- * @return {Ext.data.Store} The store\r
- */\r
- getStore : function(){\r
- return this.store;\r
- },\r
-\r
- // private\r
- bindStore : function(store, initial){\r
- if(this.store && !initial){\r
- this.store.un('beforeload', this.onBeforeLoad, this);\r
- this.store.un('load', this.onLoad, this);\r
- this.store.un('loadexception', this.collapse, this);\r
- if(!store){\r
- this.store = null;\r
- if(this.view){\r
- this.view.setStore(null);\r
- }\r
- }\r
- }\r
- if(store){\r
- this.store = Ext.StoreMgr.lookup(store);\r
-\r
- this.store.on('beforeload', this.onBeforeLoad, this);\r
- this.store.on('load', this.onLoad, this);\r
- this.store.on('loadexception', this.collapse, this);\r
-\r
- if(this.view){\r
- this.view.setStore(store);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- initEvents : function(){\r
- Ext.form.ComboBox.superclass.initEvents.call(this);\r
-\r
- this.keyNav = new Ext.KeyNav(this.el, {\r
- "up" : function(e){\r
- this.inKeyMode = true;\r
- this.selectPrev();\r
- },\r
-\r
- "down" : function(e){\r
- if(!this.isExpanded()){\r
- this.onTriggerClick();\r
- }else{\r
- this.inKeyMode = true;\r
- this.selectNext();\r
- }\r
- },\r
-\r
- "enter" : function(e){\r
- this.onViewClick();\r
- this.delayedCheck = true;\r
- this.unsetDelayCheck.defer(10, this);\r
- },\r
-\r
- "esc" : function(e){\r
- this.collapse();\r
- },\r
-\r
- "tab" : function(e){\r
- this.onViewClick(false);\r
- return true;\r
- },\r
-\r
- scope : this,\r
-\r
- doRelay : function(foo, bar, hname){\r
- if(hname == 'down' || this.scope.isExpanded()){\r
- return Ext.KeyNav.prototype.doRelay.apply(this, arguments);\r
- }\r
- return true;\r
- },\r
-\r
- forceKeyDown : true\r
- });\r
- this.queryDelay = Math.max(this.queryDelay || 10,\r
- this.mode == 'local' ? 10 : 250);\r
- this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);\r
- if(this.typeAhead){\r
- this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);\r
- }\r
- if(this.editable !== false){\r
- this.el.on("keyup", this.onKeyUp, this);\r
- }\r
- if(this.forceSelection){\r
- this.on('blur', this.doForce, this);\r
- }\r
- },\r
-\r
- // private\r
- onDestroy : function(){\r
- if(this.view){\r
- Ext.destroy(this.view);\r
- }\r
- if(this.list){\r
- if(this.innerList){\r
- this.innerList.un('mouseover', this.onViewOver, this);\r
- this.innerList.un('mousemove', this.onViewMove, this);\r
- }\r
- this.list.destroy();\r
- }\r
- if (this.dqTask){\r
- this.dqTask.cancel();\r
- this.dqTask = null;\r
- }\r
- this.bindStore(null);\r
- Ext.form.ComboBox.superclass.onDestroy.call(this);\r
- },\r
-\r
- // private\r
- unsetDelayCheck : function(){\r
- delete this.delayedCheck;\r
- },\r
-\r
- // private\r
- fireKey : function(e){\r
- if(e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck){\r
- this.fireEvent("specialkey", this, e);\r
- }\r
- },\r
-\r
- // private\r
- onResize: function(w, h){\r
- Ext.form.ComboBox.superclass.onResize.apply(this, arguments);\r
- if(this.list && this.listWidth === undefined){\r
- var lw = Math.max(w, this.minListWidth);\r
- this.list.setWidth(lw);\r
- this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
- }\r
- },\r
-\r
- // private\r
- onEnable: function(){\r
- Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);\r
- if(this.hiddenField){\r
- this.hiddenField.disabled = false;\r
- }\r
- },\r
-\r
- // private\r
- onDisable: function(){\r
- Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);\r
- if(this.hiddenField){\r
- this.hiddenField.disabled = true;\r
- }\r
- },\r
-\r
- /**\r
- * Allow or prevent the user from directly editing the field text. If false is passed,\r
- * the user will only be able to select from the items defined in the dropdown list. This method\r
- * is the runtime equivalent of setting the 'editable' config option at config time.\r
- * @param {Boolean} value True to allow the user to directly edit the field text\r
- */\r
- setEditable : function(value){\r
- if(value == this.editable){\r
- return;\r
- }\r
- this.editable = value;\r
- if(!value){\r
- this.el.dom.setAttribute('readOnly', true);\r
- this.el.on('mousedown', this.onTriggerClick, this);\r
- this.el.addClass('x-combo-noedit');\r
- }else{\r
- this.el.dom.removeAttribute('readOnly');\r
- this.el.un('mousedown', this.onTriggerClick, this);\r
- this.el.removeClass('x-combo-noedit');\r
- }\r
- },\r
-\r
- // private\r
- onBeforeLoad : function(){\r
- if(!this.hasFocus){\r
- return;\r
- }\r
- this.innerList.update(this.loadingText ?\r
- '<div class="loading-indicator">'+this.loadingText+'</div>' : '');\r
- this.restrictHeight();\r
- this.selectedIndex = -1;\r
- },\r
-\r
- // private\r
- onLoad : function(){\r
- if(!this.hasFocus){\r
- return;\r
- }\r
- if(this.store.getCount() > 0){\r
- this.expand();\r
- this.restrictHeight();\r
- if(this.lastQuery == this.allQuery){\r
- if(this.editable){\r
- this.el.dom.select();\r
- }\r
- if(!this.selectByValue(this.value, true)){\r
- this.select(0, true);\r
- }\r
- }else{\r
- this.selectNext();\r
- if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){\r
- this.taTask.delay(this.typeAheadDelay);\r
- }\r
- }\r
- }else{\r
- this.onEmptyResults();\r
- }\r
- //this.el.focus();\r
- },\r
-\r
- // private\r
- onTypeAhead : function(){\r
- if(this.store.getCount() > 0){\r
- var r = this.store.getAt(0);\r
- var newValue = r.data[this.displayField];\r
- var len = newValue.length;\r
- var selStart = this.getRawValue().length;\r
- if(selStart != len){\r
- this.setRawValue(newValue);\r
- this.selectText(selStart, newValue.length);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- onSelect : function(record, index){\r
- if(this.fireEvent('beforeselect', this, record, index) !== false){\r
- this.setValue(record.data[this.valueField || this.displayField]);\r
- this.collapse();\r
- this.fireEvent('select', this, record, index);\r
- }\r
- },\r
-\r
- /**\r
- * Returns the currently selected field value or empty string if no value is set.\r
- * @return {String} value The selected value\r
- */\r
- getValue : function(){\r
- if(this.valueField){\r
- return typeof this.value != 'undefined' ? this.value : '';\r
- }else{\r
- return Ext.form.ComboBox.superclass.getValue.call(this);\r
- }\r
- },\r
-\r
- /**\r
- * Clears any text/value currently set in the field\r
- */\r
- clearValue : function(){\r
- if(this.hiddenField){\r
- this.hiddenField.value = '';\r
- }\r
- this.setRawValue('');\r
- this.lastSelectionText = '';\r
- this.applyEmptyText();\r
- this.value = '';\r
- },\r
-\r
- /**\r
- * Sets the specified value into the field. If the value finds a match, the corresponding record text\r
- * will be displayed in the field. If the value does not match the data value of an existing item,\r
- * and the valueNotFoundText config option is defined, it will be displayed as the default field text.\r
- * Otherwise the field will be blank (although the value will still be set).\r
- * @param {String} value The value to match\r
- */\r
- setValue : function(v){\r
- var text = v;\r
- if(this.valueField){\r
- var r = this.findRecord(this.valueField, v);\r
- if(r){\r
- text = r.data[this.displayField];\r
- }else if(this.valueNotFoundText !== undefined){\r
- text = this.valueNotFoundText;\r
- }\r
- }\r
- this.lastSelectionText = text;\r
- if(this.hiddenField){\r
- this.hiddenField.value = v;\r
- }\r
- Ext.form.ComboBox.superclass.setValue.call(this, text);\r
- this.value = v;\r
- },\r
-\r
- // private\r
- findRecord : function(prop, value){\r
- var record;\r
- if(this.store.getCount() > 0){\r
- this.store.each(function(r){\r
- if(r.data[prop] == value){\r
- record = r;\r
- return false;\r
- }\r
- });\r
- }\r
- return record;\r
- },\r
-\r
- // private\r
- onViewMove : function(e, t){\r
- this.inKeyMode = false;\r
- },\r
-\r
- // private\r
- onViewOver : function(e, t){\r
- if(this.inKeyMode){ // prevent key nav and mouse over conflicts\r
- return;\r
- }\r
- var item = this.view.findItemFromChild(t);\r
- if(item){\r
- var index = this.view.indexOf(item);\r
- this.select(index, false);\r
- }\r
- },\r
-\r
- // private\r
- onViewClick : function(doFocus){\r
- var index = this.view.getSelectedIndexes()[0];\r
- var r = this.store.getAt(index);\r
- if(r){\r
- this.onSelect(r, index);\r
- }\r
- if(doFocus !== false){\r
- this.el.focus();\r
- }\r
- },\r
-\r
- // private\r
- restrictHeight : function(){\r
- this.innerList.dom.style.height = '';\r
- var inner = this.innerList.dom;\r
- var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight;\r
- var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);\r
- var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;\r
- var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;\r
- var space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;\r
- h = Math.min(h, space, this.maxHeight);\r
-\r
- this.innerList.setHeight(h);\r
- this.list.beginUpdate();\r
- this.list.setHeight(h+pad);\r
- this.list.alignTo(this.wrap, this.listAlign);\r
- this.list.endUpdate();\r
- },\r
-\r
- // private\r
- onEmptyResults : function(){\r
- this.collapse();\r
- },\r
-\r
- /**\r
- * Returns true if the dropdown list is expanded, else false.\r
- */\r
- isExpanded : function(){\r
- return this.list && this.list.isVisible();\r
- },\r
-\r
- /**\r
- * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.\r
- * The store must be loaded and the list expanded for this function to work, otherwise use setValue.\r
- * @param {String} value The data value of the item to select\r
- * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the\r
- * selected item if it is not currently in view (defaults to true)\r
- * @return {Boolean} True if the value matched an item in the list, else false\r
- */\r
- selectByValue : function(v, scrollIntoView){\r
- if(v !== undefined && v !== null){\r
- var r = this.findRecord(this.valueField || this.displayField, v);\r
- if(r){\r
- this.select(this.store.indexOf(r), scrollIntoView);\r
- return true;\r
- }\r
- }\r
- return false;\r
- },\r
-\r
- /**\r
- * 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
- * The store must be loaded and the list expanded for this function to work, otherwise use setValue.\r
- * @param {Number} index The zero-based index of the list item to select\r
- * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the\r
- * selected item if it is not currently in view (defaults to true)\r
- */\r
- select : function(index, scrollIntoView){\r
- this.selectedIndex = index;\r
- this.view.select(index);\r
- if(scrollIntoView !== false){\r
- var el = this.view.getNode(index);\r
- if(el){\r
- this.innerList.scrollChildIntoView(el, false);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- selectNext : function(){\r
- var ct = this.store.getCount();\r
- if(ct > 0){\r
- if(this.selectedIndex == -1){\r
- this.select(0);\r
- }else if(this.selectedIndex < ct-1){\r
- this.select(this.selectedIndex+1);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- selectPrev : function(){\r
- var ct = this.store.getCount();\r
- if(ct > 0){\r
- if(this.selectedIndex == -1){\r
- this.select(0);\r
- }else if(this.selectedIndex != 0){\r
- this.select(this.selectedIndex-1);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- onKeyUp : function(e){\r
- if(this.editable !== false && !e.isSpecialKey()){\r
- this.lastKey = e.getKey();\r
- this.dqTask.delay(this.queryDelay);\r
- }\r
- },\r
-\r
- // private\r
- validateBlur : function(){\r
- return !this.list || !this.list.isVisible();\r
- },\r
-\r
- // private\r
- initQuery : function(){\r
- this.doQuery(this.getRawValue());\r
- },\r
-\r
- // private\r
- doForce : function(){\r
- if(this.el.dom.value.length > 0){\r
- this.el.dom.value =\r
- this.lastSelectionText === undefined ? '' : this.lastSelectionText;\r
- this.applyEmptyText();\r
- }\r
- },\r
-\r
- /**\r
- * Execute a query to filter the dropdown list. Fires the {@link #beforequery} event prior to performing the\r
- * query allowing the query action to be canceled if needed.\r
- * @param {String} query The SQL query to execute\r
- * @param {Boolean} forceAll True to force the query to execute even if there are currently fewer characters\r
- * in the field than the minimum specified by the minChars config option. It also clears any filter previously\r
- * saved in the current store (defaults to false)\r
- */\r
- doQuery : function(q, forceAll){\r
- if(q === undefined || q === null){\r
- q = '';\r
- }\r
- var qe = {\r
- query: q,\r
- forceAll: forceAll,\r
- combo: this,\r
- cancel:false\r
- };\r
- if(this.fireEvent('beforequery', qe)===false || qe.cancel){\r
- return false;\r
- }\r
- q = qe.query;\r
- forceAll = qe.forceAll;\r
- if(forceAll === true || (q.length >= this.minChars)){\r
- if(this.lastQuery !== q){\r
- this.lastQuery = q;\r
- if(this.mode == 'local'){\r
- this.selectedIndex = -1;\r
- if(forceAll){\r
- this.store.clearFilter();\r
- }else{\r
- this.store.filter(this.displayField, q);\r
- }\r
- this.onLoad();\r
- }else{\r
- this.store.baseParams[this.queryParam] = q;\r
- this.store.load({\r
- params: this.getParams(q)\r
- });\r
- this.expand();\r
- }\r
- }else{\r
- this.selectedIndex = -1;\r
- this.onLoad();\r
- }\r
- }\r
- },\r
-\r
- // private\r
- getParams : function(q){\r
- var p = {};\r
- //p[this.queryParam] = q;\r
- if(this.pageSize){\r
- p.start = 0;\r
- p.limit = this.pageSize;\r
- }\r
- return p;\r
- },\r
-\r
- /**\r
- * Hides the dropdown list if it is currently expanded. Fires the {@link #collapse} event on completion.\r
- */\r
- collapse : function(){\r
- if(!this.isExpanded()){\r
- return;\r
- }\r
- this.list.hide();\r
- Ext.getDoc().un('mousewheel', this.collapseIf, this);\r
- Ext.getDoc().un('mousedown', this.collapseIf, this);\r
- this.fireEvent('collapse', this);\r
- },\r
-\r
- // private\r
- collapseIf : function(e){\r
- if(!e.within(this.wrap) && !e.within(this.list)){\r
- this.collapse();\r
- }\r
- },\r
-\r
- /**\r
- * Expands the dropdown list if it is currently hidden. Fires the {@link #expand} event on completion.\r
- */\r
- expand : function(){\r
- if(this.isExpanded() || !this.hasFocus){\r
- return;\r
- }\r
- this.list.alignTo(this.wrap, this.listAlign);\r
- this.list.show();\r
- this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac\r
- Ext.getDoc().on('mousewheel', this.collapseIf, this);\r
- Ext.getDoc().on('mousedown', this.collapseIf, this);\r
- this.fireEvent('expand', this);\r
- },\r
-\r
- /**\r
- * @method onTriggerClick\r
- * @hide\r
- */\r
- // private\r
- // Implements the default empty TriggerField.onTriggerClick function\r
- onTriggerClick : function(){\r
- if(this.disabled){\r
- return;\r
- }\r
- if(this.isExpanded()){\r
- this.collapse();\r
- this.el.focus();\r
- }else {\r
- this.onFocus({});\r
- if(this.triggerAction == 'all') {\r
- this.doQuery(this.allQuery, true);\r
- } else {\r
- this.doQuery(this.getRawValue());\r
- }\r
- this.el.focus();\r
- }\r
- }\r
-\r
- /**\r
- * @hide\r
- * @method autoSize\r
- */\r
- /**\r
- * @cfg {Boolean} grow @hide\r
- */\r
- /**\r
- * @cfg {Number} growMin @hide\r
- */\r
- /**\r
- * @cfg {Number} growMax @hide\r
- */\r
-\r
-});\r
-Ext.reg('combo', Ext.form.ComboBox);
\ No newline at end of file