pkg-forms-debug.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:264k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.0.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**  * @class Ext.form.Field  * @extends Ext.BoxComponent  * Base class for form fields that provides default event handling, sizing, value handling and other functionality.  * @constructor  * Creates a new Field  * @param {Object} config Configuration options  * @xtype field  */ Ext.form.Field = Ext.extend(Ext.BoxComponent,  {     /**      * @cfg {String} inputType The type attribute for input fields -- e.g. radio, text, password, file (defaults      * to "text"). The types "file" and "password" must be used to render those field types currently -- there are      * no separate Ext components for those. Note that if you use <tt>inputType:'file'</tt>, {@link #emptyText}      * is not supported and should be avoided.      */     /**      * @cfg {Number} tabIndex The tabIndex for this field. Note this only applies to fields that are rendered,      * not those which are built via applyTo (defaults to undefined).      */     /**      * @cfg {Mixed} value A value to initialize this field with (defaults to undefined).      */     /**      * @cfg {String} name The field's HTML name attribute (defaults to "").      * <b>Note</b>: this property must be set if this field is to be automatically included with      * {@link Ext.form.BasicForm#submit form submit()}.      */     /**      * @cfg {String} cls A custom CSS class to apply to the field's underlying element (defaults to "").      */     /**      * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")      */     invalidClass : "x-form-invalid",     /**      * @cfg {String} invalidText The error text to use when marking a field invalid and no message is provided      * (defaults to "The value in this field is invalid")      */     invalidText : "The value in this field is invalid",     /**      * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")      */     focusClass : "x-form-focus",     /**      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable       automatic validation (defaults to "keyup").      */     validationEvent : "keyup",     /**      * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).      */     validateOnBlur : true,     /**      * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation      * is initiated (defaults to 250)      */     validationDelay : 250,     /**      * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or true for a default      * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.      * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>      * <pre><code>{tag: "input", type: "text", size: "20", autocomplete: "off"}</code></pre>      */     defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},     /**      * @cfg {String} fieldClass The default CSS class for the field (defaults to "x-form-field")      */     fieldClass : "x-form-field",     /**      * @cfg {String} msgTarget The location where error text should display.  Should be one of the following values      * (defaults to 'qtip'):      *<pre> Value         Description -----------   ---------------------------------------------------------------------- qtip          Display a quick tip when the user hovers over the field title         Display a default browser title attribute popup under         Add a block div beneath the field containing the error text side          Add an error icon to the right of the field with a popup on hover [element id]  Add the error text directly to the innerHTML of the specified element </pre>      */     msgTarget : 'qtip',     /**      * @cfg {String} msgFx <b>Experimental</b> The effect used when displaying a validation message under the field      * (defaults to 'normal').      */     msgFx : 'normal',     /**      * @cfg {Boolean} readOnly <tt>true</tt> to mark the field as readOnly in HTML      * (defaults to <tt>false</tt>).      * <br><p><b>Note</b>: this only sets the element's readOnly DOM attribute.      * Setting <code>readOnly=true</code>, for example, will not disable triggering a      * ComboBox or DateField; it gives you the option of forcing the user to choose      * via the trigger without typing in the text box. To hide the trigger use      * <code>{@link Ext.form.TriggerField#hideTrigger hideTrigger}</code>.</p>      */     readOnly : false,     /**      * @cfg {Boolean} disabled True to disable the field (defaults to false).      * <p>Be aware that conformant with the <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.12.1">HTML specification</a>,      * disabled Fields will not be {@link Ext.form.BasicForm#submit submitted}.</p>      */     disabled : false,     // private     isFormField : true,     // private     hasFocus : false,     // private     initComponent : function(){         Ext.form.Field.superclass.initComponent.call(this);         this.addEvents(             /**              * @event focus              * Fires when this field receives input focus.              * @param {Ext.form.Field} this              */             'focus',             /**              * @event blur              * Fires when this field loses input focus.              * @param {Ext.form.Field} this              */             'blur',             /**              * @event specialkey              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.              * To handle other keys see {@link Ext.Panel#keys} or {@link Ext.KeyMap}.              * You can check {@link Ext.EventObject#getKey} to determine which key was pressed.              * For example: <pre><code> var form = new Ext.form.FormPanel({     ...     items: [{             fieldLabel: 'Field 1',             name: 'field1',             allowBlank: false         },{             fieldLabel: 'Field 2',             name: 'field2',             listeners: {                 specialkey: function(field, e){                     // e.HOME, e.END, e.PAGE_UP, e.PAGE_DOWN,                     // e.TAB, e.ESC, arrow keys: e.LEFT, e.RIGHT, e.UP, e.DOWN                     if (e.{@link Ext.EventObject#getKey getKey()} == e.ENTER) {                         var form = field.ownerCt.getForm();                         form.submit();                     }                 }             }         }     ],     ... });              * </code></pre>              * @param {Ext.form.Field} this              * @param {Ext.EventObject} e The event object              */             'specialkey',             /**              * @event change              * Fires just before the field blurs if the field value has changed.              * @param {Ext.form.Field} this              * @param {Mixed} newValue The new value              * @param {Mixed} oldValue The original value              */             'change',             /**              * @event invalid              * Fires after the field has been marked as invalid.              * @param {Ext.form.Field} this              * @param {String} msg The validation message              */             'invalid',             /**              * @event valid              * Fires after the field has been validated with no errors.              * @param {Ext.form.Field} this              */             'valid'         );     },     /**      * Returns the {@link Ext.form.Field#name name} or {@link Ext.form.ComboBox#hiddenName hiddenName}      * attribute of the field if available.      * @return {String} name The field {@link Ext.form.Field#name name} or {@link Ext.form.ComboBox#hiddenName hiddenName}        */     getName: function(){         return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';     },     // private     onRender : function(ct, position){         if(!this.el){             var cfg = this.getAutoCreate();             if(!cfg.name){                 cfg.name = this.name || this.id;             }             if(this.inputType){                 cfg.type = this.inputType;             }             this.autoEl = cfg;         }         Ext.form.Field.superclass.onRender.call(this, ct, position);                  var type = this.el.dom.type;         if(type){             if(type == 'password'){                 type = 'text';             }             this.el.addClass('x-form-'+type);         }         if(this.readOnly){             this.el.dom.readOnly = true;         }         if(this.tabIndex !== undefined){             this.el.dom.setAttribute('tabIndex', this.tabIndex);         }         this.el.addClass([this.fieldClass, this.cls]);     },     // private     getItemCt : function(){         return this.el.up('.x-form-item', 4);     },     // private     initValue : function(){         if(this.value !== undefined){             this.setValue(this.value);         }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){             this.setValue(this.el.dom.value);         }         /**          * The original value of the field as configured in the {@link #value} configuration, or          * as loaded by the last form load operation if the form's {@link Ext.form.BasicForm#trackResetOnLoad trackResetOnLoad}          * setting is <code>true</code>.          * @type mixed          * @property originalValue          */         this.originalValue = this.getValue();     },     /**      * <p>Returns true if the value of this Field has been changed from its original value.      * Will return false if the field is disabled or has not been rendered yet.</p>      * <p>Note that if the owning {@link Ext.form.BasicForm form} was configured with      * {@link Ext.form.BasicForm}.{@link Ext.form.BasicForm#trackResetOnLoad trackResetOnLoad}      * then the <i>original value</i> is updated when the values are loaded by      * {@link Ext.form.BasicForm}.{@link Ext.form.BasicForm#setValues setValues}.</p>      * @return {Boolean} True if this field has been changed from its original value (and      * is not disabled), false otherwise.      */     isDirty : function() {         if(this.disabled || !this.rendered) {             return false;         }         return String(this.getValue()) !== String(this.originalValue);     },     // private     afterRender : function(){         Ext.form.Field.superclass.afterRender.call(this);         this.initEvents();         this.initValue();     },     // private     fireKey : function(e){         if(e.isSpecialKey()){             this.fireEvent("specialkey", this, e);         }     },     /**      * Resets the current field value to the originally loaded value and clears any validation messages.      * See {@link Ext.form.BasicForm}.{@link Ext.form.BasicForm#trackResetOnLoad trackResetOnLoad}      */     reset : function(){         this.setValue(this.originalValue);         this.clearInvalid();     },     // private     initEvents : function(){         this.mon(this.el, Ext.EventManager.useKeydown ? "keydown" : "keypress", this.fireKey,  this);         this.mon(this.el, 'focus', this.onFocus, this);         // fix weird FF/Win editor issue when changing OS window focus         var o = this.inEditor && Ext.isWindows && Ext.isGecko ? {buffer:10} : null;         this.mon(this.el, 'blur', this.onBlur, this, o);     },     // private     onFocus : function(){         if(this.focusClass){             this.el.addClass(this.focusClass);         }         if(!this.hasFocus){             this.hasFocus = true;             this.startValue = this.getValue();             this.fireEvent("focus", this);         }     },     // private     beforeBlur : Ext.emptyFn,     // private     onBlur : function(){         this.beforeBlur();         if(this.focusClass){             this.el.removeClass(this.focusClass);         }         this.hasFocus = false;         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){             this.validate();         }         var v = this.getValue();         if(String(v) !== String(this.startValue)){             this.fireEvent('change', this, v, this.startValue);         }         this.fireEvent("blur", this);     },     /**      * Returns whether or not the field value is currently valid      * @param {Boolean} preventMark True to disable marking the field invalid      * @return {Boolean} True if the value is valid, else false      */     isValid : function(preventMark){         if(this.disabled){             return true;         }         var restore = this.preventMark;         this.preventMark = preventMark === true;         var v = this.validateValue(this.processValue(this.getRawValue()));         this.preventMark = restore;         return v;     },     /**      * Validates the field value      * @return {Boolean} True if the value is valid, else false      */     validate : function(){         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){             this.clearInvalid();             return true;         }         return false;     },     // protected - should be overridden by subclasses if necessary to prepare raw values for validation     processValue : function(value){         return value;     },     // private     // Subclasses should provide the validation implementation by overriding this     validateValue : function(value){         return true;     },     /**      * Mark this field as invalid, using {@link #msgTarget} to determine how to display the error and      * applying {@link #invalidClass} to the field's element.      * @param {String} msg (optional) The validation message (defaults to {@link #invalidText})      */     markInvalid : function(msg){         if(!this.rendered || this.preventMark){ // not rendered             return;         }         msg = msg || this.invalidText;         var mt = this.getMessageHandler();         if(mt){             mt.mark(this, msg);         }else if(this.msgTarget){             this.el.addClass(this.invalidClass);             var t = Ext.getDom(this.msgTarget);             if(t){                 t.innerHTML = msg;                 t.style.display = this.msgDisplay;             }         }         this.fireEvent('invalid', this, msg);     },     /**      * Clear any invalid styles/messages for this field      */     clearInvalid : function(){         if(!this.rendered || this.preventMark){ // not rendered             return;         }         this.el.removeClass(this.invalidClass);         var mt = this.getMessageHandler();         if(mt){             mt.clear(this);         }else if(this.msgTarget){             this.el.removeClass(this.invalidClass);             var t = Ext.getDom(this.msgTarget);             if(t){                 t.innerHTML = '';                 t.style.display = 'none';             }         }         this.fireEvent('valid', this);     },     // private     getMessageHandler : function(){         return Ext.form.MessageTargets[this.msgTarget];     },     // private     getErrorCt : function(){         return this.el.findParent('.x-form-element', 5, true) || // use form element wrap if available             this.el.findParent('.x-form-field-wrap', 5, true);   // else direct field wrap     },     // private     alignErrorIcon : function(){         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);     },     /**      * Returns the raw data value which may or may not be a valid, defined value.  To return a normalized value see {@link #getValue}.      * @return {Mixed} value The field value      */     getRawValue : function(){         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');         if(v === this.emptyText){             v = '';         }         return v;     },     /**      * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.      * @return {Mixed} value The field value      */     getValue : function(){         if(!this.rendered) {             return this.value;         }         var v = this.el.getValue();         if(v === this.emptyText || v === undefined){             v = '';         }         return v;     },     /**      * Sets the underlying DOM field's value directly, bypassing validation.  To set the value with validation see {@link #setValue}.      * @param {Mixed} value The value to set      * @return {Mixed} value The field value that is set      */     setRawValue : function(v){         return (this.el.dom.value = (Ext.isEmpty(v) ? '' : v));     },     /**      * Sets a data value into the field and validates it.  To set the value directly without validation see {@link #setRawValue}.      * @param {Mixed} value The value to set      * @return {Ext.form.Field} this      */     setValue : function(v){         this.value = v;         if(this.rendered){             this.el.dom.value = (Ext.isEmpty(v) ? '' : v);             this.validate();         }         return this;     },     // private, does not work for all fields     append : function(v){          this.setValue([this.getValue(), v].join(''));     },     // private     adjustSize : function(w, h){         var s = Ext.form.Field.superclass.adjustSize.call(this, w, h);         s.width = this.adjustWidth(this.el.dom.tagName, s.width);         if(this.offsetCt){             var ct = this.getItemCt();             s.width -= ct.getFrameWidth('lr');             s.height -= ct.getFrameWidth('tb');         }         return s;     },     // private     adjustWidth : function(tag, w){         if(typeof w == 'number' && (Ext.isIE && (Ext.isIE6 || !Ext.isStrict)) && /input|textarea/i.test(tag) && !this.inEditor){             return w - 3;         }         return w;     }     /**      * @cfg {Boolean} autoWidth @hide      */     /**      * @cfg {Boolean} autoHeight @hide      */     /**      * @cfg {String} autoEl @hide      */ }); Ext.form.MessageTargets = {     'qtip' : {         mark: function(field, msg){             field.el.addClass(field.invalidClass);             field.el.dom.qtip = msg;             field.el.dom.qclass = 'x-form-invalid-tip';             if(Ext.QuickTips){ // fix for floating editors interacting with DND                 Ext.QuickTips.enable();             }         },         clear: function(field){             field.el.removeClass(field.invalidClass);             field.el.dom.qtip = '';         }     },     'title' : {         mark: function(field, msg){             field.el.addClass(field.invalidClass);             field.el.dom.title = msg;         },         clear: function(field){             field.el.dom.title = '';         }     },     'under' : {         mark: function(field, msg){             field.el.addClass(field.invalidClass);             if(!field.errorEl){                 var elp = field.getErrorCt();                 if(!elp){ // field has no container el                     field.el.dom.title = msg;                     return;                 }                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});                 field.errorEl.setWidth(elp.getWidth(true)-20);             }             field.errorEl.update(msg);             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);         },         clear: function(field){             field.el.removeClass(field.invalidClass);             if(field.errorEl){                 Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);             }else{                 field.el.dom.title = '';             }         }     },     'side' : {         mark: function(field, msg){             field.el.addClass(field.invalidClass);             if(!field.errorIcon){                 var elp = field.getErrorCt();                 if(!elp){ // field has no container el                     field.el.dom.title = msg;                     return;                 }                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});             }             field.alignErrorIcon();             field.errorIcon.dom.qtip = msg;             field.errorIcon.dom.qclass = 'x-form-invalid-tip';             field.errorIcon.show();             field.on('resize', field.alignErrorIcon, field);         },         clear: function(field){             field.el.removeClass(field.invalidClass);             if(field.errorIcon){                 field.errorIcon.dom.qtip = '';                 field.errorIcon.hide();                 field.un('resize', field.alignErrorIcon, field);             }else{                 field.el.dom.title = '';             }         }     } }; // anything other than normal should be considered experimental Ext.form.Field.msgFx = {     normal : {         show: function(msgEl, f){             msgEl.setDisplayed('block');         },         hide : function(msgEl, f){             msgEl.setDisplayed(false).update('');         }     },     slide : {         show: function(msgEl, f){             msgEl.slideIn('t', {stopFx:true});         },         hide : function(msgEl, f){             msgEl.slideOut('t', {stopFx:true,useDisplay:true});         }     },     slideRight : {         show: function(msgEl, f){             msgEl.fixDisplay();             msgEl.alignTo(f.el, 'tl-tr');             msgEl.slideIn('l', {stopFx:true});         },         hide : function(msgEl, f){             msgEl.slideOut('l', {stopFx:true,useDisplay:true});         }     } }; Ext.reg('field', Ext.form.Field); /**  * @class Ext.form.TextField  * @extends Ext.form.Field  * <p>Basic text field.  Can be used as a direct replacement for traditional text inputs,  * or as the base class for more sophisticated input controls (like {@link Ext.form.TextArea}  * and {@link Ext.form.ComboBox}).</p>  * <p><b><u>Validation</u></b></p>  * <p>Field validation is processed in a particular order.  If validation fails at any particular  * step the validation routine halts.</p>  * <div class="mdetail-params"><ul>  * <li><b>1. Field specific validator</b>  * <div class="sub-desc">  * <p>If a field is configured with a <code>{@link Ext.form.TextField#validator validator}</code> function,  * it will be passed the current field value.  The <code>{@link Ext.form.TextField#validator validator}</code>  * function is expected to return boolean <tt>true</tt> if the value is valid or return a string to  * represent the invalid message if invalid.</p>  * </div></li>  * <li><b>2. Built in Validation</b>  * <div class="sub-desc">  * <p>Basic validation is affected with the following configuration properties:</p>  * <pre>  * <u>Validation</u>    <u>Invalid Message</u>  * <code>{@link Ext.form.TextField#allowBlank allowBlank}    {@link Ext.form.TextField#emptyText emptyText}</code>  * <code>{@link Ext.form.TextField#minLength minLength}     {@link Ext.form.TextField#minLengthText minLengthText}</code>  * <code>{@link Ext.form.TextField#maxLength maxLength}     {@link Ext.form.TextField#maxLengthText maxLengthText}</code>  * </pre>  * </div></li>  * <li><b>3. Preconfigured Validation Types (VTypes)</b>  * <div class="sub-desc">  * <p>Using VTypes offers a convenient way to reuse validation. If a field is configured with a  * <code>{@link Ext.form.TextField#vtype vtype}</code>, the corresponding {@link Ext.form.VTypes VTypes}  * validation function will be used for validation.  If invalid, either the field's  * <code>{@link Ext.form.TextField#vtypeText vtypeText}</code> or the VTypes vtype Text property will be  * used for the invalid message.  Keystrokes on the field will be filtered according to the VTypes  * vtype Mask property.</p>  * </div></li>  * <li><b>4. Field specific regex test</b>  * <div class="sub-desc">  * <p>Each field may also specify a <code>{@link Ext.form.TextField#regex regex}</code> test.  * The invalid message for this test is configured with  * <code>{@link Ext.form.TextField#regexText regexText}</code>.</p>  * </div></li>  * <li><b>Alter Validation Behavior</b>  * <div class="sub-desc">  * <p>Validation behavior for each field can be configured:</p><ul>  * <li><code>{@link Ext.form.TextField#invalidText invalidText}</code> : the default validation message to  * show if any validation step above does not provide a message when invalid</li>  * <li><code>{@link Ext.form.TextField#maskRe maskRe}</code> : filter out keystrokes before any validation occurs</li>  * <li><code>{@link Ext.form.TextField#stripCharsRe stripCharsRe}</code> : filter characters after being typed in,  * but before being validated</li>  * <li><code>{@link Ext.form.Field#invalidClass invalidClass}</code> : alternate style when invalid</li>  * <li><code>{@link Ext.form.Field#validateOnBlur validateOnBlur}</code>,  * <code>{@link Ext.form.Field#validationDelay validationDelay}</code>, and  * <code>{@link Ext.form.Field#validationEvent validationEvent}</code> : modify how/when validation is triggered</li>  * </ul>  * </div></li>  * </ul></div>  * @constructor  * Creates a new TextField  * @param {Object} config Configuration options  * @xtype textfield  */ Ext.form.TextField = Ext.extend(Ext.form.Field,  {     /**      * @cfg {String} vtypeText A custom error message to display in place of the default message provided      * for the <b><code>{@link #vtype}</code></b> currently set for this field (defaults to <tt>''</tt>).  <b>Note</b>:      * only applies if <b><code>{@link #vtype}</code></b> is set, else ignored.      */     /**      * @cfg {RegExp} stripCharsRe A JavaScript RegExp object used to strip unwanted content from the value      * before validation (defaults to <tt>null</tt>).      */     /**      * @cfg {Boolean} grow <tt>true</tt> if this field should automatically grow and shrink to its content      * (defaults to <tt>false</tt>)      */     grow : false,     /**      * @cfg {Number} growMin The minimum width to allow when <code><b>{@link #grow}</b> = true</code> (defaults      * to <tt>30</tt>)      */     growMin : 30,     /**      * @cfg {Number} growMax The maximum width to allow when <code><b>{@link #grow}</b> = true</code> (defaults      * to <tt>800</tt>)      */     growMax : 800,     /**      * @cfg {String} vtype A validation type name as defined in {@link Ext.form.VTypes} (defaults to <tt>null</tt>)      */     vtype : null,     /**      * @cfg {RegExp} maskRe An input mask regular expression that will be used to filter keystrokes that do      * not match (defaults to <tt>null</tt>)      */     maskRe : null,     /**      * @cfg {Boolean} disableKeyFilter Specify <tt>true</tt> to disable input keystroke filtering (defaults      * to <tt>false</tt>)      */     disableKeyFilter : false,     /**      * @cfg {Boolean} allowBlank Specify <tt>false</tt> to validate that the value's length is > 0 (defaults to      * <tt>true</tt>)      */     allowBlank : true,     /**      * @cfg {Number} minLength Minimum input field length required (defaults to <tt>0</tt>)      */     minLength : 0,     /**      * @cfg {Number} maxLength Maximum input field length allowed by validation (defaults to Number.MAX_VALUE).      * This behavior is intended to provide instant feedback to the user by improving usability to allow pasting      * and editing or overtyping and back tracking. To restrict the maximum number of characters that can be      * entered into the field use <tt><b>{@link Ext.form.Field#autoCreate autoCreate}</b></tt> to add      * any attributes you want to a field, for example:<pre><code> var myField = new Ext.form.NumberField({     id: 'mobile',     anchor:'90%',     fieldLabel: 'Mobile',     maxLength: 16, // for validation     autoCreate: {tag: 'input', type: 'text', size: '20', autocomplete: 'off', maxlength: '10'} }); </code></pre>      */     maxLength : Number.MAX_VALUE,     /**      * @cfg {String} minLengthText Error text to display if the <b><tt>{@link #minLength minimum length}</tt></b>      * validation fails (defaults to <tt>'The minimum length for this field is {minLength}'</tt>)      */     minLengthText : 'The minimum length for this field is {0}',     /**      * @cfg {String} maxLengthText Error text to display if the <b><tt>{@link #maxLength maximum length}</tt></b>      * validation fails (defaults to <tt>'The maximum length for this field is {maxLength}'</tt>)      */     maxLengthText : 'The maximum length for this field is {0}',     /**      * @cfg {Boolean} selectOnFocus <tt>true</tt> to automatically select any existing field text when the field      * receives input focus (defaults to <tt>false</tt>)      */     selectOnFocus : false,     /**      * @cfg {String} blankText The error text to display if the <b><tt>{@link #allowBlank}</tt></b> validation      * fails (defaults to <tt>'This field is required'</tt>)      */     blankText : 'This field is required',     /**      * @cfg {Function} validator A custom validation function to be called during field validation      * (defaults to <tt>null</tt>). If specified, this function will be called first, allowing the      * developer to override the default validation process. This function will be passed the current      * field value and expected to return boolean <tt>true</tt> if the value is valid or a string      * error message if invalid.      */     validator : null,     /**      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation      * (defaults to <tt>null</tt>). If the test fails, the field will be marked invalid using      * <b><tt>{@link #regexText}</tt></b>.      */     regex : null,     /**      * @cfg {String} regexText The error text to display if <b><tt>{@link #regex}</tt></b> is used and the      * test fails during validation (defaults to <tt>''</tt>)      */     regexText : '',     /**      * @cfg {String} emptyText The default text to place into an empty field (defaults to <tt>null</tt>).      * <b>Note</b>: that this value will be submitted to the server if this field is enabled and configured      * with a {@link #name}.      */     emptyText : null,     /**      * @cfg {String} emptyClass The CSS class to apply to an empty field to style the <b><tt>{@link #emptyText}</tt></b>      * (defaults to <tt>'x-form-empty-field'</tt>).  This class is automatically added and removed as needed      * depending on the current field value.      */     emptyClass : 'x-form-empty-field',     /**      * @cfg {Boolean} enableKeyEvents <tt>true</tt> to enable the proxying of key events for the HTML input      * field (defaults to <tt>false</tt>)      */     initComponent : function(){         Ext.form.TextField.superclass.initComponent.call(this);         this.addEvents(             /**              * @event autosize              * Fires when the <tt><b>{@link #autoSize}</b></tt> function is triggered. The field may or              * may not have actually changed size according to the default logic, but this event provides              * a hook for the developer to apply additional logic at runtime to resize the field if needed.              * @param {Ext.form.Field} this This text field              * @param {Number} width The new field width              */             'autosize',             /**              * @event keydown              * Keydown input field event. This event only fires if <tt><b>{@link #enableKeyEvents}</b></tt>              * is set to true.              * @param {Ext.form.TextField} this This text field              * @param {Ext.EventObject} e              */             'keydown',             /**              * @event keyup              * Keyup input field event. This event only fires if <tt><b>{@link #enableKeyEvents}</b></tt>              * is set to true.              * @param {Ext.form.TextField} this This text field              * @param {Ext.EventObject} e              */             'keyup',             /**              * @event keypress              * Keypress input field event. This event only fires if <tt><b>{@link #enableKeyEvents}</b></tt>              * is set to true.              * @param {Ext.form.TextField} this This text field              * @param {Ext.EventObject} e              */             'keypress'         );     },     // private     initEvents : function(){         Ext.form.TextField.superclass.initEvents.call(this);         if(this.validationEvent == 'keyup'){             this.validationTask = new Ext.util.DelayedTask(this.validate, this);             this.mon(this.el, 'keyup', this.filterValidation, this);         }         else if(this.validationEvent !== false){          this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});         }         if(this.selectOnFocus || this.emptyText){             this.on('focus', this.preFocus, this);                          this.mon(this.el, 'mousedown', function(){                 if(!this.hasFocus){                     this.el.on('mouseup', function(e){                         e.preventDefault();                     }, this, {single:true});                 }             }, this);                          if(this.emptyText){                 this.on('blur', this.postBlur, this);                 this.applyEmptyText();             }         }         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){          this.mon(this.el, 'keypress', this.filterKeys, this);         }         if(this.grow){          this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50}); this.mon(this.el, 'click', this.autoSize, this);         }         if(this.enableKeyEvents){          this.mon(this.el, 'keyup', this.onKeyUp, this);          this.mon(this.el, 'keydown', this.onKeyDown, this);          this.mon(this.el, 'keypress', this.onKeyPress, this);         }     },     processValue : function(value){         if(this.stripCharsRe){             var newValue = value.replace(this.stripCharsRe, '');             if(newValue !== value){                 this.setRawValue(newValue);                 return newValue;             }         }         return value;     },     filterValidation : function(e){         if(!e.isNavKeyPress()){             this.validationTask.delay(this.validationDelay);         }     },          //private     onDisable: function(){         Ext.form.TextField.superclass.onDisable.call(this);         if(Ext.isIE){             this.el.dom.unselectable = 'on';         }     },          //private     onEnable: function(){         Ext.form.TextField.superclass.onEnable.call(this);         if(Ext.isIE){             this.el.dom.unselectable = '';         }     },     // private     onKeyUpBuffered : function(e){         if(!e.isNavKeyPress()){             this.autoSize();         }     },     // private     onKeyUp : function(e){         this.fireEvent('keyup', this, e);     },     // private     onKeyDown : function(e){         this.fireEvent('keydown', this, e);     },     // private     onKeyPress : function(e){         this.fireEvent('keypress', this, e);     },     /**      * Resets the current field value to the originally-loaded value and clears any validation messages.      * Also adds <tt><b>{@link #emptyText}</b></tt> and <tt><b>{@link #emptyClass}</b></tt> if the      * original value was blank.      */     reset : function(){         Ext.form.TextField.superclass.reset.call(this);         this.applyEmptyText();     },     applyEmptyText : function(){         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){             this.setRawValue(this.emptyText);             this.el.addClass(this.emptyClass);         }     },     // private     preFocus : function(){         var el = this.el;         if(this.emptyText){             if(el.dom.value == this.emptyText){                 this.setRawValue('');             }             el.removeClass(this.emptyClass);         }         if(this.selectOnFocus){             (function(){                 el.dom.select();             }).defer(this.inEditor && Ext.isIE ? 50 : 0);             }     },     // private     postBlur : function(){         this.applyEmptyText();     },     // private     filterKeys : function(e){         // special keys don't generate charCodes, so leave them alone         if(e.ctrlKey || e.isSpecialKey()){             return;         }                  if(!this.maskRe.test(String.fromCharCode(e.getCharCode()))){             e.stopEvent();         }     },     setValue : function(v){         if(this.emptyText && this.el && !Ext.isEmpty(v)){             this.el.removeClass(this.emptyClass);         }         Ext.form.TextField.superclass.setValue.apply(this, arguments);         this.applyEmptyText();         this.autoSize();         return this;     },     /**      * Validates a value according to the field's validation rules and marks the field as invalid      * if the validation fails      * @param {Mixed} value The value to validate      * @return {Boolean} True if the value is valid, else false      */     validateValue : function(value){         if(Ext.isFunction(this.validator)){             var msg = this.validator(value);             if(msg !== true){                 this.markInvalid(msg);                 return false;             }         }         if(value.length < 1 || value === this.emptyText){ // if it's blank              if(this.allowBlank){                  this.clearInvalid();                  return true;              }else{                  this.markInvalid(this.blankText);                  return false;              }         }         if(value.length < this.minLength){             this.markInvalid(String.format(this.minLengthText, this.minLength));             return false;         }         if(value.length > this.maxLength){             this.markInvalid(String.format(this.maxLengthText, this.maxLength));             return false;         }         if(this.vtype){             var vt = Ext.form.VTypes;             if(!vt[this.vtype](value, this)){                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);                 return false;             }         }         if(this.regex && !this.regex.test(value)){             this.markInvalid(this.regexText);             return false;         }         return true;     },     /**      * Selects text in this field      * @param {Number} start (optional) The index where the selection should start (defaults to 0)      * @param {Number} end (optional) The index where the selection should end (defaults to the text length)      */     selectText : function(start, end){         var v = this.getRawValue();         var doFocus = false;         if(v.length > 0){             start = start === undefined ? 0 : start;             end = end === undefined ? v.length : end;             var d = this.el.dom;             if(d.setSelectionRange){                 d.setSelectionRange(start, end);             }else if(d.createTextRange){                 var range = d.createTextRange();                 range.moveStart('character', start);                 range.moveEnd('character', end-v.length);                 range.select();             }             doFocus = Ext.isGecko || Ext.isOpera;         }else{             doFocus = true;         }         if(doFocus){             this.focus();         }     },     /**      * Automatically grows the field to accomodate the width of the text up to the maximum field width allowed.      * This only takes effect if <tt><b>{@link #grow}</b> = true</tt>, and fires the {@link #autosize} event.      */     autoSize : function(){         if(!this.grow || !this.rendered){             return;         }         if(!this.metrics){             this.metrics = Ext.util.TextMetrics.createInstance(this.el);         }         var el = this.el;         var v = el.dom.value;         var d = document.createElement('div');         d.appendChild(document.createTextNode(v));         v = d.innerHTML;         d = null;         Ext.removeNode(d);         v += '&#160;';         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) + /* add extra padding */ 10, this.growMin));         this.el.setWidth(w);         this.fireEvent('autosize', this, w);     }, onDestroy: function(){ if(this.validationTask){ this.validationTask.cancel(); this.validationTask = null; } Ext.form.TextField.superclass.onDestroy.call(this); } }); Ext.reg('textfield', Ext.form.TextField); /**  * @class Ext.form.TriggerField  * @extends Ext.form.TextField  * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).  * The trigger has no default action, so you must assign a function to implement the trigger click handler by  * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox  * for which you can provide a custom implementation.  For example:  * <pre><code> var trigger = new Ext.form.TriggerField(); trigger.onTriggerClick = myTriggerFn; trigger.applyToMarkup('my-field'); </code></pre>  *  * However, in general you will most likely want to use TriggerField as the base class for a reusable component.  * {@link Ext.form.DateField} and {@link Ext.form.ComboBox} are perfect examples of this.  *   * @constructor  * Create a new TriggerField.  * @param {Object} config Configuration options (valid {@Ext.form.TextField} config options will also be applied  * to the base TextField)  * @xtype trigger  */ Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {     /**      * @cfg {String} triggerClass      * An additional CSS class used to style the trigger button.  The trigger will always get the      * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.      */     /**      * @cfg {Mixed} triggerConfig      * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the      * trigger element for this Field. (Optional).</p>      * <p>Specify this when you need a customized element to act as the trigger button for a TriggerField.</p>      * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing, positioning      * and appearance of the trigger.  Defaults to:</p>      * <pre><code>{tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass}</code></pre>      */     /**      * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or true for a default      * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.      * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>      * <pre><code>{tag: "input", type: "text", size: "16", autocomplete: "off"}</code></pre>      */     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},     /**      * @cfg {Boolean} hideTrigger <tt>true</tt> to hide the trigger element and display only the base      * text field (defaults to <tt>false</tt>)      */     hideTrigger:false,     /**      * @cfg {Boolean} editable <tt>false</tt> to prevent the user from typing text directly into the field,      * the field will only respond to a click on the trigger to set the value. (defaults to <tt>true</tt>)      */     editable: true,     /**      * @cfg {String} wrapFocusClass The class added to the to the wrap of the trigger element. Defaults to      * <tt>x-trigger-wrap-focus</tt>.      */     wrapFocusClass: 'x-trigger-wrap-focus',     /**      * @hide       * @method autoSize      */     autoSize: Ext.emptyFn,     // private     monitorTab : true,     // private     deferHeight : true,     // private     mimicing : false,          actionMode: 'wrap',     // private     onResize : function(w, h){         Ext.form.TriggerField.superclass.onResize.call(this, w, h);         if(typeof w == 'number'){             this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));         }         this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());     },     // private     adjustSize : Ext.BoxComponent.prototype.adjustSize,     // private     getResizeEl : function(){         return this.wrap;     },     // private     getPositionEl : function(){         return this.wrap;     },     // private     alignErrorIcon : function(){         if(this.wrap){             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);         }     },     // private     onRender : function(ct, position){         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});         this.trigger = this.wrap.createChild(this.triggerConfig ||                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});         if(this.hideTrigger){             this.trigger.setDisplayed(false);         }         this.initTrigger();         if(!this.width){             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());         }         if(!this.editable){             this.editable = true;             this.setEditable(false);         }     },     afterRender : function(){         Ext.form.TriggerField.superclass.afterRender.call(this);     },     // private     initTrigger : function(){      this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});         this.trigger.addClassOnOver('x-form-trigger-over');         this.trigger.addClassOnClick('x-form-trigger-click');     },     // private     onDestroy : function(){ Ext.destroy(this.trigger, this.wrap);         if (this.mimicing){             Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);         }         Ext.form.TriggerField.superclass.onDestroy.call(this);     },     // private     onFocus : function(){         Ext.form.TriggerField.superclass.onFocus.call(this);         if(!this.mimicing){             this.wrap.addClass(this.wrapFocusClass);             this.mimicing = true;             Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {delay: 10});             if(this.monitorTab){              this.el.on('keydown', this.checkTab, this);             }         }     },     // private     checkTab : function(e){         if(e.getKey() == e.TAB){             this.triggerBlur();         }     },     // private     onBlur : function(){         // do nothing     },     // private     mimicBlur : function(e){         if(!this.wrap.contains(e.target) && this.validateBlur(e)){             this.triggerBlur();         }     },     // private     triggerBlur : function(){         this.mimicing = false;         Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);         if(this.monitorTab && this.el){             this.el.un("keydown", this.checkTab, this);         }         Ext.form.TriggerField.superclass.onBlur.call(this);         if(this.wrap){             this.wrap.removeClass(this.wrapFocusClass);         }     },     beforeBlur : Ext.emptyFn,           /**      * Allow or prevent the user from directly editing the field text.  If false is passed,      * the user will only be able to modify the field using the trigger.  This method      * is the runtime equivalent of setting the 'editable' config option at config time.      * @param {Boolean} value True to allow the user to directly edit the field text      */     setEditable : function(value){         if(value == this.editable){             return;         }         this.editable = value;         if(!value){             this.el.addClass('x-trigger-noedit').on('click', this.onTriggerClick, this).dom.setAttribute('readOnly', true);         }else{             this.el.removeClass('x-trigger-noedit').un('click', this.onTriggerClick,  this).dom.removeAttribute('readOnly');         }     },     // private     // This should be overriden by any subclass that needs to check whether or not the field can be blurred.     validateBlur : function(e){         return true;     },     /**      * The function that should handle the trigger's click event.  This method does nothing by default      * until overridden by an implementing function.  See Ext.form.ComboBox and Ext.form.DateField for      * sample implementations.      * @method      * @param {EventObject} e      */     onTriggerClick : Ext.emptyFn     /**      * @cfg {Boolean} grow @hide      */     /**      * @cfg {Number} growMin @hide      */     /**      * @cfg {Number} growMax @hide      */ }); /**  * @class Ext.form.TwinTriggerField  * @extends Ext.form.TriggerField  * TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class  * to be extended by an implementing class.  For an example of implementing this class, see the custom  * SearchField implementation here:  * <a href="http://extjs.com/deploy/ext/examples/form/custom.html">http://extjs.com/deploy/ext/examples/form/custom.html</a>  */ Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {     /**      * @cfg {Mixed} triggerConfig      * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the trigger elements      * for this Field. (Optional).</p>      * <p>Specify this when you need a customized element to contain the two trigger elements for this Field.      * Each trigger element must be marked by the CSS class <tt>x-form-trigger</tt> (also see      * <tt>{@link #trigger1Class}</tt> and <tt>{@link #trigger2Class}</tt>).</p>      * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing,      * positioning and appearance of the triggers.</p>      */     /**      * @cfg {String} trigger1Class      * An additional CSS class used to style the trigger button.  The trigger will always get the      * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.      */     /**      * @cfg {String} trigger2Class      * An additional CSS class used to style the trigger button.  The trigger will always get the      * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.      */     initComponent : function(){         Ext.form.TwinTriggerField.superclass.initComponent.call(this);         this.triggerConfig = {             tag:'span', cls:'x-form-twin-triggers', cn:[             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}         ]};     },     getTrigger : function(index){         return this.triggers[index];     },     initTrigger : function(){         var ts = this.trigger.select('.x-form-trigger', true);         this.wrap.setStyle('overflow', 'hidden');         var triggerField = this;         ts.each(function(t, all, index){             t.hide = function(){                 var w = triggerField.wrap.getWidth();                 this.dom.style.display = 'none';                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());             };             t.show = function(){                 var w = triggerField.wrap.getWidth();                 this.dom.style.display = '';                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());             };             var triggerIndex = 'Trigger'+(index+1);             if(this['hide'+triggerIndex]){                 t.dom.style.display = 'none';             }             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});             t.addClassOnOver('x-form-trigger-over');             t.addClassOnClick('x-form-trigger-click');         }, this);         this.triggers = ts.elements;     },     /**      * The function that should handle the trigger's click event.  This method does nothing by default      * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}      * for additional information.        * @method      * @param {EventObject} e      */     onTrigger1Click : Ext.emptyFn,     /**      * The function that should handle the trigger's click event.  This method does nothing by default      * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}      * for additional information.        * @method      * @param {EventObject} e      */     onTrigger2Click : Ext.emptyFn }); Ext.reg('trigger', Ext.form.TriggerField);/**  * @class Ext.form.TextArea  * @extends Ext.form.TextField  * Multiline text field.  Can be used as a direct replacement for traditional textarea fields, plus adds  * support for auto-sizing.  * @constructor  * Creates a new TextArea  * @param {Object} config Configuration options  * @xtype textarea  */ Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {     /**      * @cfg {Number} growMin The minimum height to allow when <tt>{@link Ext.form.TextField#grow grow}=true</tt>      * (defaults to <tt>60</tt>)      */     growMin : 60,     /**      * @cfg {Number} growMax The maximum height to allow when <tt>{@link Ext.form.TextField#grow grow}=true</tt>      * (defaults to <tt>1000</tt>)      */     growMax: 1000,     growAppend : '&#160;n&#160;',     growPad : Ext.isWebKit ? -6 : 0,     enterIsSpecial : false,     /**      * @cfg {Boolean} preventScrollbars <tt>true</tt> to prevent scrollbars from appearing regardless of how much text is      * in the field (equivalent to setting overflow: hidden, defaults to <tt>false</tt>)      */     preventScrollbars: false,     /**      * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or true for a default      * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.      * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>      * <pre><code>{tag: "textarea", style: "width:100px;height:60px;", autocomplete: "off"}</code></pre>      */     // private     onRender : function(ct, position){         if(!this.el){             this.defaultAutoCreate = {                 tag: "textarea",                 style:"width:100px;height:60px;",                 autocomplete: "off"             };         }         Ext.form.TextArea.superclass.onRender.call(this, ct, position);         if(this.grow){             this.textSizeEl = Ext.DomHelper.append(document.body, {                 tag: "pre", cls: "x-form-grow-sizer"             });             if(this.preventScrollbars){                 this.el.setStyle("overflow", "hidden");             }             this.el.setHeight(this.growMin);         }     },     onDestroy : function(){         Ext.destroy(this.textSizeEl);         Ext.form.TextArea.superclass.onDestroy.call(this);     },     fireKey : function(e){         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){             this.fireEvent("specialkey", this, e);         }     },     // private     onKeyUp : function(e){         if(!e.isNavKeyPress() || e.getKey() == e.ENTER){             this.autoSize();         }         Ext.form.TextArea.superclass.onKeyUp.call(this, e);     },     /**      * Automatically grows the field to accomodate the height of the text up to the maximum field height allowed.      * This only takes effect if grow = true, and fires the {@link #autosize} event if the height changes.      */     autoSize: function(){         if(!this.grow || !this.textSizeEl){             return;         }         var el = this.el;         var v = el.dom.value;         var ts = this.textSizeEl;         ts.innerHTML = '';         ts.appendChild(document.createTextNode(v));         v = ts.innerHTML;         Ext.fly(ts).setWidth(this.el.getWidth());         if(v.length < 1){             v = "&#160;&#160;";         }else{             v += this.growAppend;             if(Ext.isIE){                 v = v.replace(/n/g, '<br />');             }         }         ts.innerHTML = v;         var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin) + this.growPad);         if(h != this.lastHeight){             this.lastHeight = h;             this.el.setHeight(h);             this.fireEvent("autosize", this, h);         }     } }); Ext.reg('textarea', Ext.form.TextArea);/**  * @class Ext.form.NumberField  * @extends Ext.form.TextField  * Numeric text field that provides automatic keystroke filtering and numeric validation.  * @constructor  * Creates a new NumberField  * @param {Object} config Configuration options  * @xtype numberfield  */ Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {     /**      * @cfg {RegExp} stripCharsRe @hide      */     /**      * @cfg {RegExp} maskRe @hide      */     /**      * @cfg {String} fieldClass The default CSS class for the field (defaults to "x-form-field x-form-num-field")      */     fieldClass: "x-form-field x-form-num-field",     /**      * @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)      */     allowDecimals : true,     /**      * @cfg {String} decimalSeparator Character(s) to allow as the decimal separator (defaults to '.')      */     decimalSeparator : ".",     /**      * @cfg {Number} decimalPrecision The maximum precision to display after the decimal separator (defaults to 2)      */     decimalPrecision : 2,     /**      * @cfg {Boolean} allowNegative False to prevent entering a negative sign (defaults to true)      */     allowNegative : true,     /**      * @cfg {Number} minValue The minimum allowed value (defaults to Number.NEGATIVE_INFINITY)      */     minValue : Number.NEGATIVE_INFINITY,     /**      * @cfg {Number} maxValue The maximum allowed value (defaults to Number.MAX_VALUE)      */     maxValue : Number.MAX_VALUE,     /**      * @cfg {String} minText Error text to display if the minimum value validation fails (defaults to "The minimum value for this field is {minValue}")      */     minText : "The minimum value for this field is {0}",     /**      * @cfg {String} maxText Error text to display if the maximum value validation fails (defaults to "The maximum value for this field is {maxValue}")      */     maxText : "The maximum value for this field is {0}",     /**      * @cfg {String} nanText Error text to display if the value is not a valid number.  For example, this can happen      * if a valid character like '.' or '-' is left in the field with no number (defaults to "{value} is not a valid number")      */     nanText : "{0} is not a valid number",     /**      * @cfg {String} baseChars The base set of characters to evaluate as valid numbers (defaults to '0123456789').      */     baseChars : "0123456789",     // private     initEvents : function(){         var allowed = this.baseChars + '';         if (this.allowDecimals) {             allowed += this.decimalSeparator;         }         if (this.allowNegative) {             allowed += '-';         }         this.maskRe = new RegExp('[' + Ext.escapeRe(allowed) + ']');         Ext.form.NumberField.superclass.initEvents.call(this);     },     // private     validateValue : function(value){         if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){             return false;         }         if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid              return true;         }         value = String(value).replace(this.decimalSeparator, ".");         if(isNaN(value)){             this.markInvalid(String.format(this.nanText, value));             return false;         }         var num = this.parseValue(value);         if(num < this.minValue){             this.markInvalid(String.format(this.minText, this.minValue));             return false;         }         if(num > this.maxValue){             this.markInvalid(String.format(this.maxText, this.maxValue));             return false;         }         return true;     },     getValue : function(){         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));     },     setValue : function(v){      v = typeof v == 'number' ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);         return Ext.form.NumberField.superclass.setValue.call(this, v);     },     // private     parseValue : function(value){         value = parseFloat(String(value).replace(this.decimalSeparator, "."));         return isNaN(value) ? '' : value;     },     // private     fixPrecision : function(value){         var nan = isNaN(value);         if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){            return nan ? '' : value;         }         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));     },     beforeBlur : function(){         var v = this.parseValue(this.getRawValue());         if(!Ext.isEmpty(v)){             this.setValue(this.fixPrecision(v));         }     } }); Ext.reg('numberfield', Ext.form.NumberField);/**  * @class Ext.form.DateField  * @extends Ext.form.TriggerField  * Provides a date input field with a {@link Ext.DatePicker} dropdown and automatic date validation.  * @constructor  * Create a new DateField  * @param {Object} config  * @xtype datefield  */ Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {     /**      * @cfg {String} format      * The default date format string which can be overriden for localization support.  The format must be      * valid according to {@link Date#parseDate} (defaults to <tt>'m/d/Y'</tt>).      */     format : "m/d/Y",     /**      * @cfg {String} altFormats      * Multiple date formats separated by "<tt>|</tt>" to try when parsing a user input value and it      * does not match the defined format (defaults to      * <tt>'m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d'</tt>).      */     altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d",     /**      * @cfg {String} disabledDaysText      * The tooltip to display when the date falls on a disabled day (defaults to <tt>'Disabled'</tt>)      */     disabledDaysText : "Disabled",     /**      * @cfg {String} disabledDatesText      * The tooltip text to display when the date falls on a disabled date (defaults to <tt>'Disabled'</tt>)      */     disabledDatesText : "Disabled",     /**      * @cfg {String} minText      * The error text to display when the date in the cell is before <tt>{@link #minValue}</tt> (defaults to      * <tt>'The date in this field must be after {minValue}'</tt>).      */     minText : "The date in this field must be equal to or after {0}",     /**      * @cfg {String} maxText      * The error text to display when the date in the cell is after <tt>{@link #maxValue}</tt> (defaults to      * <tt>'The date in this field must be before {maxValue}'</tt>).      */     maxText : "The date in this field must be equal to or before {0}",     /**      * @cfg {String} invalidText      * The error text to display when the date in the field is invalid (defaults to      * <tt>'{value} is not a valid date - it must be in the format {format}'</tt>).      */     invalidText : "{0} is not a valid date - it must be in the format {1}",     /**      * @cfg {String} triggerClass      * An additional CSS class used to style the trigger button.  The trigger will always get the      * class <tt>'x-form-trigger'</tt> and <tt>triggerClass</tt> will be <b>appended</b> if specified      * (defaults to <tt>'x-form-date-trigger'</tt> which displays a calendar icon).      */     triggerClass : 'x-form-date-trigger',     /**      * @cfg {Boolean} showToday      * <tt>false</tt> to hide the footer area of the DatePicker containing the Today button and disable      * the keyboard handler for spacebar that selects the current date (defaults to <tt>true</tt>).      */     showToday : true,     /**      * @cfg {Date/String} minValue      * The minimum allowed date. Can be either a Javascript date object or a string date in a      * valid format (defaults to null).      */     /**      * @cfg {Date/String} maxValue      * The maximum allowed date. Can be either a Javascript date object or a string date in a      * valid format (defaults to null).      */     /**      * @cfg {Array} disabledDays      * An array of days to disable, 0 based (defaults to null). Some examples:<pre><code> // disable Sunday and Saturday: disabledDays:  [0, 6] // disable weekdays: disabledDays: [1,2,3,4,5]      * </code></pre>      */     /**      * @cfg {Array} disabledDates      * An array of "dates" to disable, as strings. These strings will be used to build a dynamic regular      * expression so they are very powerful. Some examples:<pre><code> // disable these exact dates: disabledDates: ["03/08/2003", "09/16/2003"] // disable these days for every year: disabledDates: ["03/08", "09/16"] // only match the beginning (useful if you are using short years): disabledDates: ["^03/08"] // disable every day in March 2006: disabledDates: ["03/../2006"] // disable every day in every March: disabledDates: ["^03"]      * </code></pre>      * Note that the format of the dates included in the array should exactly match the {@link #format} config.      * In order to support regular expressions, if you are using a {@link #format date format} that has "." in      * it, you will have to escape the dot when restricting dates. For example: <tt>["03\.08\.03"]</tt>.      */     /**      * @cfg {String/Object} autoCreate      * A {@link Ext.DomHelper DomHelper element specification object}, or <tt>true</tt> for the default element      * specification object:<pre><code>      * autoCreate: {tag: "input", type: "text", size: "10", autocomplete: "off"}      * </code></pre>      */     // private     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},     initComponent : function(){         Ext.form.DateField.superclass.initComponent.call(this);         this.addEvents(             /**              * @event select              * Fires when a date is selected via the date picker.              * @param {Ext.form.DateField} this              * @param {Date} date The date that was selected              */             'select'         );         if(Ext.isString(this.minValue)){             this.minValue = this.parseDate(this.minValue);         }         if(Ext.isString(this.maxValue)){             this.maxValue = this.parseDate(this.maxValue);         }         this.disabledDatesRE = null;         this.initDisabledDays();     },     // private     initDisabledDays : function(){         if(this.disabledDates){             var dd = this.disabledDates,                 len = dd.length - 1,                  re = "(?:";                              Ext.each(dd, function(d, i){                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];                 if(i != len){                     re += '|';                 }             }, this);             this.disabledDatesRE = new RegExp(re + ')');         }     },     /**      * Replaces any existing disabled dates with new values and refreshes the DatePicker.      * @param {Array} disabledDates An array of date strings (see the <tt>{@link #disabledDates}</tt> config      * for details on supported values) used to disable a pattern of dates.      */     setDisabledDates : function(dd){         this.disabledDates = dd;         this.initDisabledDays();         if(this.menu){             this.menu.picker.setDisabledDates(this.disabledDatesRE);         }     },     /**      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.      * @param {Array} disabledDays An array of disabled day indexes. See the <tt>{@link #disabledDays}</tt>      * config for details on supported values.      */     setDisabledDays : function(dd){         this.disabledDays = dd;         if(this.menu){             this.menu.picker.setDisabledDays(dd);         }     },     /**      * Replaces any existing <tt>{@link #minValue}</tt> with the new value and refreshes the DatePicker.      * @param {Date} value The minimum date that can be selected      */     setMinValue : function(dt){         this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);         if(this.menu){             this.menu.picker.setMinDate(this.minValue);         }     },     /**      * Replaces any existing <tt>{@link #maxValue}</tt> with the new value and refreshes the DatePicker.      * @param {Date} value The maximum date that can be selected      */     setMaxValue : function(dt){         this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);         if(this.menu){             this.menu.picker.setMaxDate(this.maxValue);         }     },     // private     validateValue : function(value){         value = this.formatDate(value);         if(!Ext.form.DateField.superclass.validateValue.call(this, value)){             return false;         }         if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid              return true;         }         var svalue = value;         value = this.parseDate(value);         if(!value){             this.markInvalid(String.format(this.invalidText, svalue, this.format));             return false;         }         var time = value.getTime();         if(this.minValue && time < this.minValue.getTime()){             this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));             return false;         }         if(this.maxValue && time > this.maxValue.getTime()){             this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));             return false;         }         if(this.disabledDays){             var day = value.getDay();             for(var i = 0; i < this.disabledDays.length; i++) {                 if(day === this.disabledDays[i]){                     this.markInvalid(this.disabledDaysText);                     return false;                 }             }         }         var fvalue = this.formatDate(value);         if(this.disabledDatesRE && this.disabledDatesRE.test(fvalue)){             this.markInvalid(String.format(this.disabledDatesText, fvalue));             return false;         }         return true;     },     // private     // Provides logic to override the default TriggerField.validateBlur which just returns true     validateBlur : function(){         return !this.menu || !this.menu.isVisible();     },     /**      * Returns the current date value of the date field.      * @return {Date} The date value      */     getValue : function(){         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";     },     /**      * Sets the value of the date field.  You can pass a date object or any string that can be      * parsed into a valid date, using <tt>{@link #format}</tt> as the date format, according      * to the same rules as {@link Date#parseDate} (the default format used is <tt>"m/d/Y"</tt>).      * <br />Usage:      * <pre><code> //All of these calls set the same date value (May 4, 2006) //Pass a date object: var dt = new Date('5/4/2006'); dateField.setValue(dt); //Pass a date string (default format): dateField.setValue('05/04/2006'); //Pass a date string (custom format): dateField.format = 'Y-m-d'; dateField.setValue('2006-05-04'); </code></pre>      * @param {String/Date} date The date or valid date string      * @return {Ext.form.Field} this      */     setValue : function(date){         return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));     },     // private     parseDate : function(value){         if(!value || Ext.isDate(value)){             return value;         }         var v = Date.parseDate(value, this.format);         if(!v && this.altFormats){             if(!this.altFormatsArray){                 this.altFormatsArray = this.altFormats.split("|");             }             for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){                 v = Date.parseDate(value, this.altFormatsArray[i]);             }         }         return v;     },     // private     onDestroy : function(){ Ext.destroy(this.menu);         Ext.form.DateField.superclass.onDestroy.call(this);     },     // private     formatDate : function(date){         return Ext.isDate(date) ? date.dateFormat(this.format) : date;     },     /**      * @method onTriggerClick      * @hide      */     // private     // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker     onTriggerClick : function(){         if(this.disabled){             return;         }         if(this.menu == null){             this.menu = new Ext.menu.DateMenu({                 hideOnClick: false             });         }         this.onFocus();         Ext.apply(this.menu.picker,  {             minDate : this.minValue,             maxDate : this.maxValue,             disabledDatesRE : this.disabledDatesRE,             disabledDatesText : this.disabledDatesText,             disabledDays : this.disabledDays,             disabledDaysText : this.disabledDaysText,             format : this.format,             showToday : this.showToday,             minText : String.format(this.minText, this.formatDate(this.minValue)),             maxText : String.format(this.maxText, this.formatDate(this.maxValue))         });         this.menu.picker.setValue(this.getValue() || new Date());         this.menu.show(this.el, "tl-bl?");         this.menuEvents('on');     },          //private     menuEvents: function(method){         this.menu[method]('select', this.onSelect, this);         this.menu[method]('hide', this.onMenuHide, this);         this.menu[method]('show', this.onFocus, this);     },          onSelect: function(m, d){         this.setValue(d);         this.fireEvent('select', this, d);         this.menu.hide();     },          onMenuHide: function(){         this.focus(false, 60);         this.menuEvents('un');     },     // private     beforeBlur : function(){         var v = this.parseDate(this.getRawValue());         if(v){             this.setValue(v);         }     }     /**      * @cfg {Boolean} grow @hide      */     /**      * @cfg {Number} growMin @hide      */     /**      * @cfg {Number} growMax @hide      */     /**      * @hide      * @method autoSize      */ }); Ext.reg('datefield', Ext.form.DateField);/**
  2.  * @class Ext.form.DisplayField
  3.  * @extends Ext.form.Field
  4.  * A display-only text field which is not validated and not submitted.
  5.  * @constructor
  6.  * Creates a new DisplayField.
  7.  * @param {Object} config Configuration options
  8.  * @xtype displayfield
  9.  */
  10. Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
  11.     validationEvent : false,
  12.     validateOnBlur : false,
  13.     defaultAutoCreate : {tag: "div"},
  14.     /**
  15.      * @cfg {String} fieldClass The default CSS class for the field (defaults to <tt>"x-form-display-field"</tt>)
  16.      */
  17.     fieldClass : "x-form-display-field",
  18.     /**
  19.      * @cfg {Boolean} htmlEncode <tt>false</tt> to skip HTML-encoding the text when rendering it (defaults to
  20.      * <tt>false</tt>). This might be useful if you want to include tags in the field's innerHTML rather than
  21.      * rendering them as string literals per the default logic.
  22.      */
  23.     htmlEncode: false,
  24.     // private
  25.     initEvents : Ext.emptyFn,
  26.     isValid : function(){
  27.         return true;
  28.     },
  29.     validate : function(){
  30.         return true;
  31.     },
  32.     getRawValue : function(){
  33.         var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
  34.         if(v === this.emptyText){
  35.             v = '';
  36.         }
  37.         if(this.htmlEncode){
  38.             v = Ext.util.Format.htmlDecode(v);
  39.         }
  40.         return v;
  41.     },
  42.     getValue : function(){
  43.         return this.getRawValue();
  44.     },
  45.     
  46.     getName: function() {
  47.         return this.name;
  48.     },
  49.     setRawValue : function(v){
  50.         if(this.htmlEncode){
  51.             v = Ext.util.Format.htmlEncode(v);
  52.         }
  53.         return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
  54.     },
  55.     setValue : function(v){
  56.         this.setRawValue(v);
  57.         return this;
  58.     }
  59.     /** 
  60.      * @cfg {String} inputType 
  61.      * @hide
  62.      */
  63.     /** 
  64.      * @cfg {Boolean} disabled 
  65.      * @hide
  66.      */
  67.     /** 
  68.      * @cfg {Boolean} readOnly 
  69.      * @hide
  70.      */
  71.     /** 
  72.      * @cfg {Boolean} validateOnBlur 
  73.      * @hide
  74.      */
  75.     /** 
  76.      * @cfg {Number} validationDelay 
  77.      * @hide
  78.      */
  79.     /** 
  80.      * @cfg {String/Boolean} validationEvent 
  81.      * @hide
  82.      */
  83. });
  84. Ext.reg('displayfield', Ext.form.DisplayField);
  85. /**  * @class Ext.form.ComboBox  * @extends Ext.form.TriggerField  * <p>A combobox control with support for autocomplete, remote-loading, paging and many other features.</p>  * <p>A ComboBox works in a similar manner to a traditional HTML &lt;select> field. The difference is  * that to submit the {@link #valueField}, you must specify a {@link #hiddenName} to create a hidden input  * field to hold the value of the valueField. The <i>{@link #displayField}</i> is shown in the text field  * which is named according to the {@link #name}.</p>  * <p><b><u>Events</u></b></p>  * <p>To do something when something in ComboBox is selected, configure the select event:<pre><code> var cb = new Ext.form.ComboBox({     // all of your config options     listeners:{          scope: yourScope,          'select': yourFunction     } }); // Alternatively, you can assign events after the object is created: var cb = new Ext.form.ComboBox(yourOptions); cb.on('select', yourFunction, yourScope);  * </code></pre></p>  *  * <p><b><u>ComboBox in Grid</u></b></p>  * <p>If using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a {@link Ext.grid.Column#renderer renderer}  * will be needed to show the displayField when the editor is not active.  Set up the renderer manually, or implement  * a reusable render, for example:<pre><code> // create reusable renderer Ext.util.Format.comboRenderer = function(combo){     return function(value){         var record = combo.findRecord(combo.{@link #valueField}, value);         return record ? record.get(combo.{@link #displayField}) : combo.{@link #valueNotFoundText};     } } // create the combo instance var combo = new Ext.form.ComboBox({     {@link #typeAhead}: true,     {@link #triggerAction}: 'all',     {@link #lazyRender}:true,     {@link #mode}: 'local',     {@link #store}: new Ext.data.ArrayStore({         id: 0,         fields: [             'myId',             'displayText'         ],         data: [[1, 'item1'], [2, 'item2']]     }),     {@link #valueField}: 'myId',     {@link #displayField}: 'displayText' }); // snippet of column model used within grid var cm = new Ext.grid.ColumnModel([{        ...     },{        header: "Some Header",        dataIndex: 'whatever',        width: 130,        editor: combo, // specify reference to combo instance        renderer: Ext.util.Format.comboRenderer(combo) // pass combo instance to reusable renderer     },     ... ]);  * </code></pre></p>  *  * <p><b><u>Filtering</u></b></p>  * <p>A ComboBox {@link #doQuery uses filtering itself}, for information about filtering the ComboBox  * store manually see <tt>{@link #lastQuery}</tt>.</p>  * @constructor  * Create a new ComboBox.  * @param {Object} config Configuration options  * @xtype combo  */ Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {     /**      * @cfg {Mixed} transform The id, DOM node or element of an existing HTML SELECT to convert to a ComboBox.      * Note that if you specify this and the combo is going to be in an {@link Ext.form.BasicForm} or      * {@link Ext.form.FormPanel}, you must also set <tt>{@link #lazyRender} = true</tt>.      */     /**      * @cfg {Boolean} lazyRender <tt>true</tt> to prevent the ComboBox from rendering until requested      * (should always be used when rendering into an {@link Ext.Editor} (e.g. {@link Ext.grid.EditorGridPanel Grids}),      * defaults to <tt>false</tt>).      */     /**      * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or <tt>true</tt> for a default      * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.      * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>      * <pre><code>{tag: "input", type: "text", size: "24", autocomplete: "off"}</code></pre>      */     /**      * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to <tt>undefined</tt>).      * Acceptable values for this property are:      * <div class="mdetail-params"><ul>      * <li><b>any {@link Ext.data.Store Store} subclass</b></li>      * <li><b>an Array</b> : Arrays will be converted to a {@link Ext.data.ArrayStore} internally.      * <div class="mdetail-params"><ul>      * <li><b>1-dimensional array</b> : (e.g., <tt>['Foo','Bar']</tt>)<div class="sub-desc">      * A 1-dimensional array will automatically be expanded (each array item will be the combo      * {@link #valueField value} and {@link #displayField text})</div></li>      * <li><b>2-dimensional array</b> : (e.g., <tt>[['f','Foo'],['b','Bar']]</tt>)<div class="sub-desc">      * For a multi-dimensional array, the value in index 0 of each item will be assumed to be the combo      * {@link #valueField value}, while the value at index 1 is assumed to be the combo {@link #displayField text}.      * </div></li></ul></div></li></ul></div>      * <p>See also <tt>{@link #mode}</tt>.</p>      */     /**      * @cfg {String} title If supplied, a header element is created containing this text and added into the top of      * the dropdown list (defaults to undefined, with no header element)      */     // private     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},     /**      * @cfg {Number} listWidth The width (used as a parameter to {@link Ext.Element#setWidth}) of the dropdown      * list (defaults to the width of the ComboBox field).  See also <tt>{@link #minListWidth}      */     /**      * @cfg {String} displayField The underlying {@link Ext.data.Field#name data field name} to bind to this      * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'text'</tt> if      * {@link #transform transforming a select} a select).      * <p>See also <tt>{@link #valueField}</tt>.</p>      * <p><b>Note</b>: if using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a      * {@link Ext.grid.Column#renderer renderer} will be needed to show the displayField when the editor is not      * active.</p>      */     /**      * @cfg {String} valueField The underlying {@link Ext.data.Field#name data value name} to bind to this      * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'value'</tt> if      * {@link #transform transforming a select}).      * <p><b>Note</b>: use of a <tt>valueField</tt> requires the user to make a selection in order for a value to be      * mapped.  See also <tt>{@link #hiddenName}</tt>, <tt>{@link #hiddenValue}</tt>, and <tt>{@link #displayField}</tt>.</p>      */     /**      * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the      * field's data value (defaults to the underlying DOM element's name). Required for the combo's value to automatically      * post during a form submission.  See also {@link #valueField}.      * <p><b>Note</b>: the hidden field's id will also default to this name if {@link #hiddenId} is not specified.      * The ComboBox {@link Ext.Component#id id} and the <tt>{@link #hiddenId}</tt> <b>should be different</b>, since      * no two DOM nodes should share the same id.  So, if the ComboBox <tt>{@link Ext.form.Field#name name}</tt> and      * <tt>hiddenName</tt> are the same, you should specify a unique <tt>{@link #hiddenId}</tt>.</p>      */     /**      * @cfg {String} hiddenId If <tt>{@link #hiddenName}</tt> is specified, <tt>hiddenId</tt> can also be provided      * to give the hidden field a unique id (defaults to the <tt>{@link #hiddenName}</tt>).  The <tt>hiddenId</tt>      * and combo {@link Ext.Component#id id} should be different, since no two DOM      * nodes should share the same id.      */     /**      * @cfg {String} hiddenValue Sets the initial value of the hidden field if {@link #hiddenName} is      * specified to contain the selected {@link #valueField}, from the Store. Defaults to the configured      * <tt>{@link Ext.form.Field#value value}</tt>.      */     /**      * @cfg {String} listClass The CSS class to add to the predefined <tt>'x-combo-list'</tt> class      * applied the dropdown list element (defaults to '').      */     listClass : '',     /**      * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list      * (defaults to <tt>'x-combo-selected'</tt>)      */     selectedClass : 'x-combo-selected',     /**      * @cfg {String} listEmptyText The empty text to display in the data view if no items are found.      * (defaults to '')      */     listEmptyText: '',     /**      * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always      * get the class <tt>'x-form-trigger'</tt> and <tt>triggerClass</tt> will be <b>appended</b> if specified      * (defaults to <tt>'x-form-arrow-trigger'</tt> which displays a downward arrow icon).      */     triggerClass : 'x-form-arrow-trigger',     /**      * @cfg {Boolean/String} shadow <tt>true</tt> or <tt>"sides"</tt> for the default effect, <tt>"frame"</tt> for      * 4-way shadow, and <tt>"drop"</tt> for bottom-right      */     shadow : 'sides',     /**      * @cfg {String} listAlign A valid anchor position value. See <tt>{@link Ext.Element#alignTo}</tt> for details      * on supported anchor positions (defaults to <tt>'tl-bl?'</tt>)      */     listAlign : 'tl-bl?',     /**      * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown      * (defaults to <tt>300</tt>)      */     maxHeight : 300,     /**      * @cfg {Number} minHeight The minimum height in pixels of the dropdown list when the list is constrained by its      * distance to the viewport edges (defaults to <tt>90</tt>)      */     minHeight : 90,     /**      * @cfg {String} triggerAction The action to execute when the trigger is clicked.      * <div class="mdetail-params"><ul>      * <li><b><tt>'query'</tt></b> : <b>Default</b>      * <p class="sub-desc">{@link #doQuery run the query} using the {@link Ext.form.Field#getRawValue raw value}.</p></li>      * <li><b><tt>'all'</tt></b> :      * <p class="sub-desc">{@link #doQuery run the query} specified by the <tt>{@link #allQuery}</tt> config option</p></li>      * </ul></div>      * <p>See also <code>{@link #queryParam}</code>.</p>      */     triggerAction : 'query',     /**      * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and      * {@link #typeAhead} activate (defaults to <tt>4</tt> if <tt>{@link #mode} = 'remote'</tt> or <tt>0</tt> if      * <tt>{@link #mode} = 'local'</tt>, does not apply if      * <tt>{@link Ext.form.TriggerField#editable editable} = false</tt>).      */     minChars : 4,     /**      * @cfg {Boolean} typeAhead <tt>true</tt> to populate and autoselect the remainder of the text being      * typed after a configurable delay ({@link #typeAheadDelay}) if it matches a known value (defaults      * to <tt>false</tt>)      */     typeAhead : false,     /**      * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and      * sending the query to filter the dropdown list (defaults to <tt>500</tt> if <tt>{@link #mode} = 'remote'</tt>      * or <tt>10</tt> if <tt>{@link #mode} = 'local'</tt>)      */     queryDelay : 500,     /**      * @cfg {Number} pageSize If greater than <tt>0</tt>, a {@link Ext.PagingToolbar} is displayed in the      * footer of the dropdown list and the {@link #doQuery filter queries} will execute with page start and      * {@link Ext.PagingToolbar#pageSize limit} parameters. Only applies when <tt>{@link #mode} = 'remote'</tt>      * (defaults to <tt>0</tt>).      */     pageSize : 0,     /**      * @cfg {Boolean} selectOnFocus <tt>true</tt> to select any existing text in the field immediately on focus.      * Only applies when <tt>{@link Ext.form.TriggerField#editable editable} = true</tt> (defaults to      * <tt>false</tt>).      */     selectOnFocus : false,     /**      * @cfg {String} queryParam Name of the query ({@link Ext.data.Store#baseParam baseParam} name for the store)      * as it will be passed on the querystring (defaults to <tt>'query'</tt>)      */     queryParam : 'query',     /**      * @cfg {String} loadingText The text to display in the dropdown list while data is loading.  Only applies      * when <tt>{@link #mode} = 'remote'</tt> (defaults to <tt>'Loading...'</tt>)      */     loadingText : 'Loading...',     /**      * @cfg {Boolean} resizable <tt>true</tt> to add a resize handle to the bottom of the dropdown list      * (creates an {@link Ext.Resizable} with 'se' {@link Ext.Resizable#pinned pinned} handles).      * Defaults to <tt>false</tt>.      */     resizable : false,     /**      * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if      * <tt>{@link #resizable} = true</tt> (defaults to <tt>8</tt>)      */     handleHeight : 8,     /**      * @cfg {String} allQuery The text query to send to the server to return all records for the list      * with no filtering (defaults to '')      */     allQuery: '',     /**      * @cfg {String} mode Acceptable values are:      * <div class="mdetail-params"><ul>      * <li><b><tt>'remote'</tt></b> : <b>Default</b>      * <p class="sub-desc">Automatically loads the <tt>{@link #store}</tt> the <b>first</b> time the trigger      * is clicked. If you do not want the store to be automatically loaded the first time the trigger is      * clicked, set to <tt>'local'</tt> and manually load the store.  To force a requery of the store      * <b>every</b> time the trigger is clicked see <tt>{@link #lastQuery}</tt>.</p></li>      * <li><b><tt>'local'</tt></b> :      * <p class="sub-desc">ComboBox loads local data</p>      * <pre><code> var combo = new Ext.form.ComboBox({     renderTo: document.body,     mode: 'local',     store: new Ext.data.ArrayStore({         id: 0,         fields: [             'myId',  // numeric value is the key             'displayText'         ],         data: [[1, 'item1'], [2, 'item2']]  // data is local     }),     valueField: 'myId',     displayField: 'displayText',     triggerAction: 'all' });      * </code></pre></li>      * </ul></div>      */     mode: 'remote',     /**      * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to <tt>70</tt>, will      * be ignored if <tt>{@link #listWidth}</tt> has a higher value)      */     minListWidth : 70,     /**      * @cfg {Boolean} forceSelection <tt>true</tt> to restrict the selected value to one of the values in the list,      * <tt>false</tt> to allow the user to set arbitrary text into the field (defaults to <tt>false</tt>)      */     forceSelection : false,     /**      * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed      * if <tt>{@link #typeAhead} = true</tt> (defaults to <tt>250</tt>)      */     typeAheadDelay : 250,     /**      * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in      * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined). If this      * default text is used, it means there is no value set and no validation will occur on this field.      */     /**      * @cfg {Boolean} lazyInit <tt>true</tt> to not initialize the list for this combo until the field is focused      * (defaults to <tt>true</tt>)      */     lazyInit : true,     /**      * The value of the match string used to filter the store. Delete this property to force a requery.      * Example use:      * <pre><code> var combo = new Ext.form.ComboBox({     ...     mode: 'remote',     ...     listeners: {         // delete the previous query in the beforequery event or set         // combo.lastQuery = null (this will reload the store the next time it expands)         beforequery: function(qe){             delete qe.combo.lastQuery;         }     } });      * </code></pre>      * To make sure the filter in the store is not cleared the first time the ComboBox trigger is used      * configure the combo with <tt>lastQuery=''</tt>. Example use:      * <pre><code> var combo = new Ext.form.ComboBox({     ...     mode: 'local',     triggerAction: 'all',     lastQuery: '' });      * </code></pre>      * @property lastQuery      * @type String      */     // private     initComponent : function(){         Ext.form.ComboBox.superclass.initComponent.call(this);         this.addEvents(             /**              * @event expand              * Fires when the dropdown list is expanded              * @param {Ext.form.ComboBox} combo This combo box              */             'expand',             /**              * @event collapse              * Fires when the dropdown list is collapsed              * @param {Ext.form.ComboBox} combo This combo box              */             'collapse',             /**              * @event beforeselect              * Fires before a list item is selected. Return false to cancel the selection.              * @param {Ext.form.ComboBox} combo This combo box              * @param {Ext.data.Record} record The data record returned from the underlying store              * @param {Number} index The index of the selected item in the dropdown list              */             'beforeselect',             /**              * @event select              * Fires when a list item is selected              * @param {Ext.form.ComboBox} combo This combo box              * @param {Ext.data.Record} record The data record returned from the underlying store              * @param {Number} index The index of the selected item in the dropdown list              */             'select',             /**              * @event beforequery              * Fires before all queries are processed. Return false to cancel the query or set the queryEvent's              * cancel property to true.              * @param {Object} queryEvent An object that has these properties:<ul>              * <li><code>combo</code> : Ext.form.ComboBox <div class="sub-desc">This combo box</div></li>              * <li><code>query</code> : String <div class="sub-desc">The query</div></li>              * <li><code>forceAll</code> : Boolean <div class="sub-desc">True to force "all" query</div></li>              * <li><code>cancel</code> : Boolean <div class="sub-desc">Set to true to cancel the query</div></li>              * </ul>              */             'beforequery'         );         if(this.transform){             var s = Ext.getDom(this.transform);             if(!this.hiddenName){                 this.hiddenName = s.name;             }             if(!this.store){                 this.mode = 'local';                 var d = [], opts = s.options;                 for(var i = 0, len = opts.length;i < len; i++){                     var o = opts[i],                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;                     if(o.selected && Ext.isEmpty(this.value, true)) {                         this.value = value;                     }                     d.push([value, o.text]);                 }                 this.store = new Ext.data.ArrayStore({                     'id': 0,                     fields: ['value', 'text'],                     data : d,                     autoDestroy: true                 });                 this.valueField = 'value';                 this.displayField = 'text';             }             s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference             if(!this.lazyRender){                 this.target = true;                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);                 this.render(this.el.parentNode, s);                 Ext.removeNode(s); // remove it             }else{                 Ext.removeNode(s); // remove it             }         }         //auto-configure store from local array data         else if(this.store){             this.store = Ext.StoreMgr.lookup(this.store);             if(this.store.autoCreated){                 this.displayField = this.valueField = 'field1';                 if(!this.store.expandData){                     this.displayField = 'field2';                 }                 this.mode = 'local';             }         }         this.selectedIndex = -1;         if(this.mode == 'local'){             if(!Ext.isDefined(this.initialConfig.queryDelay)){                 this.queryDelay = 10;             }             if(!Ext.isDefined(this.initialConfig.minChars)){                 this.minChars = 0;             }         }     },     // private     onRender : function(ct, position){         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);         if(this.hiddenName){             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,                     id: (this.hiddenId||this.hiddenName)}, 'before', true);             // prevent input submission             this.el.dom.removeAttribute('name');         }         if(Ext.isGecko){             this.el.dom.setAttribute('autocomplete', 'off');         }         if(!this.lazyInit){             this.initList();         }else{             this.on('focus', this.initList, this, {single: true});         }     },     // private     initValue : function(){         Ext.form.ComboBox.superclass.initValue.call(this);         if(this.hiddenField){             this.hiddenField.value =                 Ext.isDefined(this.hiddenValue) ? this.hiddenValue :                 Ext.isDefined(this.value) ? this.value : '';         }     },     // private     initList : function(){         if(!this.list){             var cls = 'x-combo-list';             this.list = new Ext.Layer({                 parentEl: this.getListParent(),                 shadow: this.shadow,                 cls: [cls, this.listClass].join(' '),                 constrain:false             });             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);             this.list.setSize(lw, 0);             this.list.swallowEvent('mousewheel');             this.assetHeight = 0;             if(this.syncFont !== false){                 this.list.setStyle('font-size', this.el.getStyle('font-size'));             }             if(this.title){                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});                 this.assetHeight += this.header.getHeight();             }             this.innerList = this.list.createChild({cls:cls+'-inner'});             this.mon(this.innerList, 'mouseover', this.onViewOver, this);             this.mon(this.innerList, 'mousemove', this.onViewMove, this);             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));             if(this.pageSize){                 this.footer = this.list.createChild({cls:cls+'-ft'});                 this.pageTb = new Ext.PagingToolbar({                     store: this.store,                     pageSize: this.pageSize,                     renderTo:this.footer                 });                 this.assetHeight += this.footer.getHeight();             }             if(!this.tpl){                 /**                 * @cfg {String/Ext.XTemplate} tpl <p>The template string, or {@link Ext.XTemplate} instance to                 * use to display each item in the dropdown list. The dropdown list is displayed in a                 * DataView. See {@link #view}.</p>                 * <p>The default template string is:</p><pre><code>                   '&lt;tpl for=".">&lt;div class="x-combo-list-item">{' + this.displayField + '}&lt;/div>&lt;/tpl>'                 * </code></pre>                 * <p>Override the default value to create custom UI layouts for items in the list.                 * For example:</p><pre><code>                   '&lt;tpl for=".">&lt;div ext:qtip="{state}. {nick}" class="x-combo-list-item">{state}&lt;/div>&lt;/tpl>'                 * </code></pre>                 * <p>The template <b>must</b> contain one or more substitution parameters using field                 * names from the Combo's</b> {@link #store Store}. In the example above an                 * <pre>ext:qtip</pre> attribute is added to display other fields from the Store.</p>                 * <p>To preserve the default visual look of list items, add the CSS class name                 * <pre>x-combo-list-item</pre> to the template's container element.</p>                 * <p>Also see {@link #itemSelector} for additional details.</p>                 */                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';                 /**                  * @cfg {String} itemSelector                  * <p>A simple CSS selector (e.g. div.some-class or span:first-child) that will be                  * used to determine what nodes the {@link #view Ext.DataView} which handles the dropdown                  * display will be working with.</p>                  * <p><b>Note</b>: this setting is <b>required</b> if a custom XTemplate has been                  * specified in {@link #tpl} which assigns a class other than <pre>'x-combo-list-item'</pre>                  * to dropdown list items</b>                  */             }             /**             * The {@link Ext.DataView DataView} used to display the ComboBox's options.             * @type Ext.DataView             */             this.view = new Ext.DataView({                 applyTo: this.innerList,                 tpl: this.tpl,                 singleSelect: true,                 selectedClass: this.selectedClass,                 itemSelector: this.itemSelector || '.' + cls + '-item',                 emptyText: this.listEmptyText             });             this.mon(this.view, 'click', this.onViewClick, this);             this.bindStore(this.store, true);             if(this.resizable){                 this.resizer = new Ext.Resizable(this.list,  {                    pinned:true, handles:'se'                 });                 this.mon(this.resizer, 'resize', function(r, w, h){                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;                     this.listWidth = w;                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));                     this.restrictHeight();                 }, this);                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');             }         }     },     /**      * <p>Returns the element used to house this ComboBox's pop-up list. Defaults to the document body.</p>      * A custom implementation may be provided as a configuration option if the floating list needs to be rendered      * to a different Element. An example might be rendering the list inside a Menu so that clicking      * the list does not hide the Menu:<pre><code> var store = new Ext.data.ArrayStore({     autoDestroy: true,     fields: ['initials', 'fullname'],     data : [         ['FF', 'Fred Flintstone'],         ['BR', 'Barney Rubble']     ] }); var combo = new Ext.form.ComboBox({     store: store,     displayField: 'fullname',     emptyText: 'Select a name...',     forceSelection: true,     getListParent: function() {         return this.el.up('.x-menu');     },     iconCls: 'no-icon', //use iconCls if placing within menu to shift to right side of menu     mode: 'local',     selectOnFocus: true,     triggerAction: 'all',     typeAhead: true,     width: 135 }); var menu = new Ext.menu.Menu({     id: 'mainMenu',     items: [         combo // A Field in a Menu     ] }); </code></pre>      */     getListParent : function() {         return document.body;     },     /**      * Returns the store associated with this combo.      * @return {Ext.data.Store} The store      */     getStore : function(){         return this.store;     },     // private     bindStore : function(store, initial){         if(this.store && !initial){             this.store.un('beforeload', this.onBeforeLoad, this);             this.store.un('load', this.onLoad, this);             this.store.un('exception', this.collapse, this);             if(this.store !== store && this.store.autoDestroy){                 this.store.destroy();             }             if(!store){                 this.store = null;                 if(this.view){                     this.view.bindStore(null);                 }             }         }         if(store){             if(!initial) {                 this.lastQuery = null;                 if(this.pageTb) {                     this.pageTb.bindStore(store);                 }             }             this.store = Ext.StoreMgr.lookup(store);             this.store.on({                 scope: this,                 beforeload: this.onBeforeLoad,                 load: this.onLoad,                 exception: this.collapse             });             if(this.view){                 this.view.bindStore(store);             }         }     },     // private     initEvents : function(){         Ext.form.ComboBox.superclass.initEvents.call(this);         this.keyNav = new Ext.KeyNav(this.el, {             "up" : function(e){                 this.inKeyMode = true;                 this.selectPrev();             },             "down" : function(e){                 if(!this.isExpanded()){                     this.onTriggerClick();                 }else{                     this.inKeyMode = true;                     this.selectNext();                 }             },             "enter" : function(e){                 this.onViewClick();                 this.delayedCheck = true;                 this.unsetDelayCheck.defer(10, this);             },             "esc" : function(e){                 this.collapse();             },             "tab" : function(e){                 this.onViewClick(false);                 return true;             },             scope : this,             doRelay : function(foo, bar, hname){                 if(hname == 'down' || this.scope.isExpanded()){                    return Ext.KeyNav.prototype.doRelay.apply(this, arguments);                 }                 return true;             },             forceKeyDown : true         });         this.queryDelay = Math.max(this.queryDelay || 10,                 this.mode == 'local' ? 10 : 250);         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);         if(this.typeAhead){             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);         }         if(this.editable !== false && !this.enableKeyEvents){             this.mon(this.el, 'keyup', this.onKeyUp, this);         }     },     // private     onDestroy : function(){         if (this.dqTask){             this.dqTask.cancel();             this.dqTask = null;         }         this.bindStore(null);         Ext.destroy(             this.resizer,             this.view,             this.pageTb,             this.list         );         Ext.form.ComboBox.superclass.onDestroy.call(this);     },     // private     unsetDelayCheck : function(){         delete this.delayedCheck;     },     // private     fireKey : function(e){         var fn = function(ev){             if (ev.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck) {                 this.fireEvent("specialkey", this, ev);             }         };         //For some reason I can't track down, the events fire in a different order in webkit.         //Need a slight delay here         if(this.inEditor && Ext.isWebKit && e.getKey() == e.TAB){             fn.defer(10, this, [new Ext.EventObjectImpl(e)]);         }else{             fn.call(this, e);         }     },     // private     onResize : function(w, h){         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);         if(this.list && !Ext.isDefined(this.listWidth)){             var lw = Math.max(w, this.minListWidth);             this.list.setWidth(lw);             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));         }     },     // private     onEnable : function(){         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);         if(this.hiddenField){             this.hiddenField.disabled = false;         }     },     // private     onDisable : function(){         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);         if(this.hiddenField){             this.hiddenField.disabled = true;         }     },     // private     onBeforeLoad : function(){         if(!this.hasFocus){             return;         }         this.innerList.update(this.loadingText ?                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');         this.restrictHeight();         this.selectedIndex = -1;     },     // private     onLoad : function(){         if(!this.hasFocus){             return;         }         if(this.store.getCount() > 0){             this.expand();             this.restrictHeight();             if(this.lastQuery == this.allQuery){                 if(this.editable){                     this.el.dom.select();                 }                 if(!this.selectByValue(this.value, true)){                     this.select(0, true);                 }             }else{                 this.selectNext();                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){                     this.taTask.delay(this.typeAheadDelay);                 }             }         }else{             this.onEmptyResults();         }         //this.el.focus();     },     // private     onTypeAhead : function(){         if(this.store.getCount() > 0){             var r = this.store.getAt(0);             var newValue = r.data[this.displayField];             var len = newValue.length;             var selStart = this.getRawValue().length;             if(selStart != len){                 this.setRawValue(newValue);                 this.selectText(selStart, newValue.length);             }         }     },     // private     onSelect : function(record, index){         if(this.fireEvent('beforeselect', this, record, index) !== false){             this.setValue(record.data[this.valueField || this.displayField]);             this.collapse();             this.fireEvent('select', this, record, index);         }     },     // inherit docs     getName: function(){         var hf = this.hiddenField;         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);     },     /**      * Returns the currently selected field value or empty string if no value is set.      * @return {String} value The selected value      */     getValue : function(){         if(this.valueField){             return Ext.isDefined(this.value) ? this.value : '';         }else{             return Ext.form.ComboBox.superclass.getValue.call(this);         }     },     /**      * Clears any text/value currently set in the field      */     clearValue : function(){         if(this.hiddenField){             this.hiddenField.value = '';         }         this.setRawValue('');         this.lastSelectionText = '';         this.applyEmptyText();         this.value = '';     },     /**      * Sets the specified value into the field.  If the value finds a match, the corresponding record text      * will be displayed in the field.  If the value does not match the data value of an existing item,      * and the valueNotFoundText config option is defined, it will be displayed as the default field text.      * Otherwise the field will be blank (although the value will still be set).      * @param {String} value The value to match      * @return {Ext.form.Field} this      */     setValue : function(v){         var text = v;         if(this.valueField){             var r = this.findRecord(this.valueField, v);             if(r){                 text = r.data[this.displayField];             }else if(Ext.isDefined(this.valueNotFoundText)){                 text = this.valueNotFoundText;             }         }         this.lastSelectionText = text;         if(this.hiddenField){             this.hiddenField.value = v;         }         Ext.form.ComboBox.superclass.setValue.call(this, text);         this.value = v;         return this;     },     // private     findRecord : function(prop, value){         var record;         if(this.store.getCount() > 0){             this.store.each(function(r){                 if(r.data[prop] == value){                     record = r;                     return false;                 }             });         }         return record;     },     // private     onViewMove : function(e, t){         this.inKeyMode = false;     },     // private     onViewOver : function(e, t){         if(this.inKeyMode){ // prevent key nav and mouse over conflicts             return;         }         var item = this.view.findItemFromChild(t);         if(item){             var index = this.view.indexOf(item);             this.select(index, false);         }     },     // private     onViewClick : function(doFocus){         var index = this.view.getSelectedIndexes()[0];         var r = this.store.getAt(index);         if(r){             this.onSelect(r, index);         }         if(doFocus !== false){             this.el.focus();         }     },     // private     restrictHeight : function(){         this.innerList.dom.style.height = '';         var inner = this.innerList.dom;         var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight;         var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);         var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;         var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;         var space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;         h = Math.min(h, space, this.maxHeight);         this.innerList.setHeight(h);         this.list.beginUpdate();         this.list.setHeight(h+pad);         this.list.alignTo(this.wrap, this.listAlign);         this.list.endUpdate();     },     // private     onEmptyResults : function(){         this.collapse();     },     /**      * Returns true if the dropdown list is expanded, else false.      */     isExpanded : function(){         return this.list && this.list.isVisible();     },     /**      * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.      * The store must be loaded and the list expanded for this function to work, otherwise use setValue.      * @param {String} value The data value of the item to select      * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the      * selected item if it is not currently in view (defaults to true)      * @return {Boolean} True if the value matched an item in the list, else false      */     selectByValue : function(v, scrollIntoView){         if(!Ext.isEmpty(v, true)){             var r = this.findRecord(this.valueField || this.displayField, v);             if(r){                 this.select(this.store.indexOf(r), scrollIntoView);                 return true;             }         }         return false;     },     /**      * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.      * The store must be loaded and the list expanded for this function to work, otherwise use setValue.      * @param {Number} index The zero-based index of the list item to select      * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the      * selected item if it is not currently in view (defaults to true)      */     select : function(index, scrollIntoView){         this.selectedIndex = index;         this.view.select(index);         if(scrollIntoView !== false){             var el = this.view.getNode(index);             if(el){                 this.innerList.scrollChildIntoView(el, false);             }         }     },     // private     selectNext : function(){         var ct = this.store.getCount();         if(ct > 0){             if(this.selectedIndex == -1){                 this.select(0);             }else if(this.selectedIndex < ct-1){                 this.select(this.selectedIndex+1);             }         }     },     // private     selectPrev : function(){         var ct = this.store.getCount();         if(ct > 0){             if(this.selectedIndex == -1){                 this.select(0);             }else if(this.selectedIndex !== 0){                 this.select(this.selectedIndex-1);             }         }     },     // private     onKeyUp : function(e){         var k = e.getKey();         if(this.editable !== false && (k == e.BACKSPACE || !e.isSpecialKey())){             this.lastKey = k;             this.dqTask.delay(this.queryDelay);         }         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);     },     // private     validateBlur : function(){         return !this.list || !this.list.isVisible();     },     // private     initQuery : function(){         this.doQuery(this.getRawValue());     },     // private     beforeBlur : function(){         var val = this.getRawValue();         if(this.forceSelection){             if(val.length > 0 && val != this.emptyText){                this.el.dom.value = Ext.isDefined(this.lastSelectionText) ? this.lastSelectionText : '';                 this.applyEmptyText();             }else{                 this.clearValue();             }         }else{             var rec = this.findRecord(this.displayField, val);             if(rec){                 val = rec.get(this.valueField || this.displayField);             }             this.setValue(val);         }     },     /**      * Execute 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} query The SQL query to execute      * @param {Boolean} forceAll <tt>true</tt> to force the query to execute even if there are currently fewer      * characters in the field than the minimum specified by the <tt>{@link #minChars}</tt> config option.  It      * also clears any filter previously saved in the current store (defaults to <tt>false</tt>)      */     doQuery : function(q, forceAll){         q = Ext.isEmpty(q) ? '' : q;         var qe = {             query: q,             forceAll: forceAll,             combo: this,             cancel:false         };         if(this.fireEvent('beforequery', qe)===false || qe.cancel){             return false;         }         q = qe.query;         forceAll = qe.forceAll;         if(forceAll === true || (q.length >= this.minChars)){             if(this.lastQuery !== q){                 this.lastQuery = q;                 if(this.mode == 'local'){                     this.selectedIndex = -1;                     if(forceAll){                         this.store.clearFilter();                     }else{                         this.store.filter(this.displayField, q);                     }                     this.onLoad();                 }else{                     this.store.baseParams[this.queryParam] = q;                     this.store.load({                         params: this.getParams(q)                     });                     this.expand();                 }             }else{                 this.selectedIndex = -1;                 this.onLoad();             }         }     },     // private     getParams : function(q){         var p = {};         //p[this.queryParam] = q;         if(this.pageSize){             p.start = 0;             p.limit = this.pageSize;         }         return p;     },     /**      * Hides the dropdown list if it is currently expanded. Fires the {@link #collapse} event on completion.      */     collapse : function(){         if(!this.isExpanded()){             return;         }         this.list.hide();         Ext.getDoc().un('mousewheel', this.collapseIf, this);         Ext.getDoc().un('mousedown', this.collapseIf, this);         this.fireEvent('collapse', this);     },     // private     collapseIf : function(e){         if(!e.within(this.wrap) && !e.within(this.list)){             this.collapse();         }     },     /**      * Expands the dropdown list if it is currently hidden. Fires the {@link #expand} event on completion.      */     expand : function(){         if(this.isExpanded() || !this.hasFocus){             return;         }         this.list.alignTo(this.wrap, this.listAlign);         this.list.show();         if(Ext.isGecko2){             this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac         }         Ext.getDoc().on({             scope: this,             mousewheel: this.collapseIf,             mousedown: this.collapseIf         });         this.fireEvent('expand', this);     },     /**      * @method onTriggerClick      * @hide      */     // private     // Implements the default empty TriggerField.onTriggerClick function     onTriggerClick : function(){         if(this.disabled){             return;         }         if(this.isExpanded()){             this.collapse();             this.el.focus();         }else {             this.onFocus({});             if(this.triggerAction == 'all') {                 this.doQuery(this.allQuery, true);             } else {                 this.doQuery(this.getRawValue());             }             this.el.focus();         }     }     /**      * @hide      * @method autoSize      */     /**      * @cfg {Boolean} grow @hide      */     /**      * @cfg {Number} growMin @hide      */     /**      * @cfg {Number} growMax @hide      */ }); Ext.reg('combo', Ext.form.ComboBox);/**  * @class Ext.form.Checkbox  * @extends Ext.form.Field  * Single checkbox field.  Can be used as a direct replacement for traditional checkbox fields.  * @constructor  * Creates a new Checkbox  * @param {Object} config Configuration options  * @xtype checkbox  */ Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {     /**      * @cfg {String} focusClass The CSS class to use when the checkbox receives focus (defaults to undefined)      */     focusClass : undefined,     /**      * @cfg {String} fieldClass The default CSS class for the checkbox (defaults to 'x-form-field')      */     fieldClass : 'x-form-field',     /**      * @cfg {Boolean} checked <tt>true</tt> if the checkbox should render initially checked (defaults to <tt>false</tt>)      */     checked : false,     /**      * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to      * {tag: 'input', type: 'checkbox', autocomplete: 'off'})      */     defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},     /**      * @cfg {String} boxLabel The text that appears beside the checkbox      */     /**      * @cfg {String} inputValue The value that should go into the generated input element's value attribute      */     /**      * @cfg {Function} handler A function called when the {@link #checked} value changes (can be used instead of       * handling the check event). The handler is passed the following parameters:      * <div class="mdetail-params"><ul>      * <li><b>checkbox</b> : Ext.form.Checkbox<div class="sub-desc">The Checkbox being toggled.</div></li>      * <li><b>checked</b> : Boolean<div class="sub-desc">The new checked state of the checkbox.</div></li>      * </ul></div>      */     /**      * @cfg {Object} scope An object to use as the scope ('this' reference) of the {@link #handler} function      * (defaults to this Checkbox).      */     // private     actionMode : 'wrap',      // private     initComponent : function(){         Ext.form.Checkbox.superclass.initComponent.call(this);         this.addEvents(             /**              * @event check              * Fires when the checkbox is checked or unchecked.              * @param {Ext.form.Checkbox} this This checkbox              * @param {Boolean} checked The new checked value              */             'check'         );     },     // private     onResize : function(){         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);         if(!this.boxLabel && !this.fieldLabel){             this.el.alignTo(this.wrap, 'c-c');         }     },     // private     initEvents : function(){         Ext.form.Checkbox.superclass.initEvents.call(this);         this.mon(this.el, 'click', this.onClick, this);         this.mon(this.el, 'change', this.onClick, this);     }, // private     getResizeEl : function(){         return this.wrap;     },     // private     getPositionEl : function(){         return this.wrap;     },     /**      * @hide      * Overridden and disabled. The editor element does not support standard valid/invalid marking.      * @method      */     markInvalid : Ext.emptyFn,     /**      * @hide      * Overridden and disabled. The editor element does not support standard valid/invalid marking.      * @method      */     clearInvalid : Ext.emptyFn,     // private     onRender : function(ct, position){         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);         if(this.inputValue !== undefined){             this.el.dom.value = this.inputValue;         }         this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});         if(this.boxLabel){             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});         }         if(this.checked){             this.setValue(true);         }else{             this.checked = this.el.dom.checked;         }     },     // private     onDestroy : function(){         Ext.destroy(this.wrap);         Ext.form.Checkbox.superclass.onDestroy.call(this);     },     // private     initValue : function() {         this.originalValue = this.getValue();     },     /**      * Returns the checked state of the checkbox.      * @return {Boolean} True if checked, else false      */     getValue : function(){         if(this.rendered){             return this.el.dom.checked;         }         return false;     }, // private     onClick : function(){         if(this.el.dom.checked != this.checked){             this.setValue(this.el.dom.checked);         }     },     /**      * Sets the checked state of the checkbox, fires the 'check' event, and calls a      * <code>{@link #handler}</code> (if configured).      * @param {Boolean/String} checked The following values will check the checkbox:      * <code>true, 'true', '1', or 'on'</code>. Any other value will uncheck the checkbox.      * @return {Ext.form.Field} this      */     setValue : function(v){         var checked = this.checked ;         this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');         if(this.rendered){             this.el.dom.checked = this.checked;             this.el.dom.defaultChecked = this.checked;         }         if(checked != this.checked){             this.fireEvent('check', this, this.checked);             if(this.handler){                 this.handler.call(this.scope || this, this, this.checked);             }         }         return this;     } }); Ext.reg('checkbox', Ext.form.Checkbox); /**  * @class Ext.form.CheckboxGroup  * @extends Ext.form.Field  * <p>A grouping container for {@link Ext.form.Checkbox} controls.</p>  * <p>Sample usage:</p>  * <pre><code> var myCheckboxGroup = new Ext.form.CheckboxGroup({     id:'myGroup',     xtype: 'checkboxgroup',     fieldLabel: 'Single Column',     itemCls: 'x-check-group-alt',     // Put all controls in a single column with width 100%     columns: 1,     items: [         {boxLabel: 'Item 1', name: 'cb-col-1'},         {boxLabel: 'Item 2', name: 'cb-col-2', checked: true},         {boxLabel: 'Item 3', name: 'cb-col-3'}     ] });  * </code></pre>  * @constructor  * Creates a new CheckboxGroup  * @param {Object} config Configuration options  * @xtype checkboxgroup  */ Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {     /**      * @cfg {Array} items An Array of {@link Ext.form.Checkbox Checkbox}es or Checkbox config objects      * to arrange in the group.      */     /**      * @cfg {String/Number/Array} columns Specifies the number of columns to use when displaying grouped      * checkbox/radio controls using automatic layout.  This config can take several types of values:      * <ul><li><b>'auto'</b> : <p class="sub-desc">The controls will be rendered one per column on one row and the width      * of each column will be evenly distributed based on the width of the overall field container. This is the default.</p></li>      * <li><b>Number</b> : <p class="sub-desc">If you specific a number (e.g., 3) that number of columns will be       * created and the contained controls will be automatically distributed based on the value of {@link #vertical}.</p></li>      * <li><b>Array</b> : Object<p class="sub-desc">You can also specify an array of column widths, mixing integer      * (fixed width) and float (percentage width) values as needed (e.g., [100, .25, .75]). Any integer values will      * be rendered first, then any float values will be calculated as a percentage of the remaining space. Float      * values do not have to add up to 1 (100%) although if you want the controls to take up the entire field      * container you should do so.</p></li></ul>      */     columns : 'auto',     /**      * @cfg {Boolean} vertical True to distribute contained controls across columns, completely filling each column       * top to bottom before starting on the next column.  The number of controls in each column will be automatically      * calculated to keep columns as even as possible.  The default value is false, so that controls will be added      * to columns one at a time, completely filling each row left to right before starting on the next row.      */     vertical : false,     /**      * @cfg {Boolean} allowBlank False to validate that at least one item in the group is checked (defaults to true).      * If no items are selected at validation time, {@link @blankText} will be used as the error text.      */     allowBlank : true,     /**      * @cfg {String} blankText Error text to display if the {@link #allowBlank} validation fails (defaults to "You must       * select at least one item in this group")      */     blankText : "You must select at least one item in this group",          // private     defaultType : 'checkbox',          // private     groupCls : 'x-form-check-group',          // private     initComponent: function(){         this.addEvents(             /**              * @event change              * Fires when the state of a child checkbox changes.              * @param {Ext.form.CheckboxGroup} this              * @param {Array} checked An array containing the checked boxes.              */             'change'         );            Ext.form.CheckboxGroup.superclass.initComponent.call(this);     },          // private     onRender : function(ct, position){         if(!this.el){             var panelCfg = {                 cls: this.groupCls,                 layout: 'column',                 border: false,                 renderTo: ct             };             var colCfg = {                 defaultType: this.defaultType,                 layout: 'form',                 border: false,                 defaults: {                     hideLabel: true,                     anchor: '100%'                 }             };                          if(this.items[0].items){                                  // The container has standard ColumnLayout configs, so pass them in directly                                  Ext.apply(panelCfg, {                     layoutConfig: {columns: this.items.length},                     defaults: this.defaults,                     items: this.items                 });                 for(var i=0, len=this.items.length; i<len; i++){                     Ext.applyIf(this.items[i], colCfg);                 }                              }else{                                  // The container has field item configs, so we have to generate the column                 // panels first then move the items into the columns as needed.                                  var numCols, cols = [];                                  if(typeof this.columns == 'string'){ // 'auto' so create a col per item                     this.columns = this.items.length;                 }                 if(!Ext.isArray(this.columns)){                     var cs = [];                     for(var i=0; i<this.columns; i++){                         cs.push((100/this.columns)*.01); // distribute by even %                     }                     this.columns = cs;                 }                                  numCols = this.columns.length;                                  // Generate the column configs with the correct width setting                 for(var i=0; i<numCols; i++){                     var cc = Ext.apply({items:[]}, colCfg);                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];                     if(this.defaults){                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)                     }                     cols.push(cc);                 };                                  // Distribute the original items into the columns                 if(this.vertical){                     var rows = Math.ceil(this.items.length / numCols), ri = 0;                     for(var i=0, len=this.items.length; i<len; i++){                         if(i>0 && i%rows==0){                             ri++;                         }                         if(this.items[i].fieldLabel){                             this.items[i].hideLabel = false;                         }                         cols[ri].items.push(this.items[i]);                     };                 }else{                     for(var i=0, len=this.items.length; i<len; i++){                         var ci = i % numCols;                         if(this.items[i].fieldLabel){                             this.items[i].hideLabel = false;                         }                         cols[ci].items.push(this.items[i]);                     };                 }                                  Ext.apply(panelCfg, {                     layoutConfig: {columns: numCols},                     items: cols                 });             }                          this.panel = new Ext.Panel(panelCfg);             this.panel.ownerCt = this;             this.el = this.panel.getEl();                          if(this.forId && this.itemCls){                 var l = this.el.up(this.itemCls).child('label', true);                 if(l){                     l.setAttribute('htmlFor', this.forId);                 }             }                          var fields = this.panel.findBy(function(c){                 return c.isFormField;             }, this);                          this.items = new Ext.util.MixedCollection();             this.items.addAll(fields);         }         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);     },          afterRender : function(){         Ext.form.CheckboxGroup.superclass.afterRender.call(this);         if(this.values){             this.setValue.apply(this, this.values);             delete this.values;         }         this.eachItem(function(item){             item.on('check', this.fireChecked, this);             item.inGroup = true;         });     },          // private     doLayout: function(){         //ugly method required to layout hidden items         if(this.rendered){             this.panel.forceLayout = this.ownerCt.forceLayout;             this.panel.doLayout();         }     },          // private     fireChecked: function(){         var arr = [];         this.eachItem(function(item){             if(item.checked){                 arr.push(item);             }         });         this.fireEvent('change', this, arr);     },          // private     validateValue : function(value){         if(!this.allowBlank){             var blank = true;             this.eachItem(function(f){                 if(f.checked){                     return (blank = false);                 }             });             if(blank){                 this.markInvalid(this.blankText);                 return false;             }         }         return true;     },          // private     onDisable : function(){         this.eachItem(function(item){             item.disable();         });     },     // private     onEnable : function(){         this.eachItem(function(item){             item.enable();         });     },          // private     doLayout: function(){         if(this.rendered){             this.panel.forceLayout = this.ownerCt.forceLayout;             this.panel.doLayout();         }     },          // private     onResize : function(w, h){         this.panel.setSize(w, h);         this.panel.doLayout();     },          // inherit docs from Field     reset : function(){         Ext.form.CheckboxGroup.superclass.reset.call(this);         this.eachItem(function(c){             if(c.reset){                 c.reset();             }         });     },          /**      * {@link Ext.form.Checkbox#setValue Set the value(s)} of an item or items      * in the group. Examples illustrating how this method may be called:      * <pre><code> // call with name and value myCheckboxGroup.setValue('cb-col-1', true); // call with an array of boolean values  myCheckboxGroup.setValue([true, false, false]); // call with an object literal specifying item:value pairs myCheckboxGroup.setValue({     'cb-col-2': false,     'cb-col-3': true }); // use comma separated string to set items with name to true (checked) myCheckboxGroup.setValue('cb-col-1,cb-col-3');      * </code></pre>      * See {@link Ext.form.Checkbox#setValue} for additional information.      * @param {Mixed} id The checkbox to check, or as described by example shown.      * @param {Boolean} value (optional) The value to set the item.      * @return {Ext.form.CheckboxGroup} this      */     setValue : function(id, value){         if(this.rendered){             if(arguments.length == 1){                 if(Ext.isArray(id)){                     //an array of boolean values                     Ext.each(id, function(val, idx){                         var item = this.items.itemAt(idx);                         if(item){                             item.setValue(val);                         }                     }, this);                 }else if(Ext.isObject(id)){                     //set of name/value pairs                     for(var i in id){                         var f = this.getBox(i);                         if(f){                             f.setValue(id[i]);                         }                     }                 }else{                     this.setValueForItem(id);                 }             }else{                 var f = this.getBox(id);                 if(f){                     f.setValue(value);                 }             }         }else{             this.values = arguments;         }         return this;     },          // private     onDestroy: function(){         Ext.destroy(this.panel);         Ext.form.CheckboxGroup.superclass.onDestroy.call(this);     },          setValueForItem : function(val){         val = String(val).split(',');         this.eachItem(function(item){             if(val.indexOf(item.inputValue)> -1){                 item.setValue(true);             }         });     },          // private     getBox : function(id){         var box = null;         this.eachItem(function(f){             if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){                 box = f;                 return false;             }         });         return box;     },          /**      * Gets an array of the selected {@link Ext.form.Checkbox} in the group.      * @return {Array} An array of the selected checkboxes.      */     getValue : function(){         var out = [];         this.eachItem(function(item){             if(item.checked){                 out.push(item);             }         });         return out;     },          // private     eachItem: function(fn){         if(this.items && this.items.each){             this.items.each(fn, this);         }     },          /**      * @cfg {String} name      * @hide      */     /**      * @method initValue      * @hide      */     initValue : Ext.emptyFn,     /**      * @method getValue      * @hide      */     getValue : Ext.emptyFn,     /**      * @method getRawValue      * @hide      */     getRawValue : Ext.emptyFn,          /**      * @method setRawValue      * @hide      */     setRawValue : Ext.emptyFn      }); Ext.reg('checkboxgroup', Ext.form.CheckboxGroup); /**  * @class Ext.form.Radio  * @extends Ext.form.Checkbox  * Single radio field.  Same as Checkbox, but provided as a convenience for automatically setting the input type.  * Radio grouping is handled automatically by the browser if you give each radio in a group the same name.  * @constructor  * Creates a new Radio  * @param {Object} config Configuration options  * @xtype radio  */ Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {     inputType: 'radio',     /**      * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide      * @method      */     markInvalid : Ext.emptyFn,     /**      * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide      * @method      */     clearInvalid : Ext.emptyFn,     /**      * If this radio is part of a group, it will return the selected value      * @return {String}      */     getGroupValue : function(){      var p = this.el.up('form') || Ext.getBody();         var c = p.child('input[name='+this.el.dom.name+']:checked', true);         return c ? c.value : null;     },     // private     onClick : function(){      if(this.el.dom.checked != this.checked){ var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']'); els.each(function(el){ if(el.dom.id == this.id){ this.setValue(true); }else{ Ext.getCmp(el.dom.id).setValue(false); } }, this); }     },     /**      * Sets either the checked/unchecked status of this Radio, or, if a string value      * is passed, checks a sibling Radio of the same name whose value is the value specified.      * @param value {String/Boolean} Checked value, or the value of the sibling radio button to check.      * @return {Ext.form.Field} this      */     setValue : function(v){      if (typeof v == 'boolean') {             Ext.form.Radio.superclass.setValue.call(this, v);         } else {             var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);             if(r){                 Ext.getCmp(r.id).setValue(true);             }         }         return this;     },          // private     getCheckEl: function(){         if(this.inGroup){             return this.el.up('.x-form-radio-group')         }         return this.el.up('form') || Ext.getBody();     } }); Ext.reg('radio', Ext.form.Radio); /**  * @class Ext.form.RadioGroup  * @extends Ext.form.CheckboxGroup  * A grouping container for {@link Ext.form.Radio} controls.  * @constructor  * Creates a new RadioGroup  * @param {Object} config Configuration options  * @xtype radiogroup  */ Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {     /**      * @cfg {Boolean} allowBlank True to allow every item in the group to be blank (defaults to true).      * If allowBlank = false and no items are selected at validation time, {@link @blankText} will      * be used as the error text.      */     allowBlank : true,     /**      * @cfg {String} blankText Error text to display if the {@link #allowBlank} validation fails      * (defaults to 'You must select one item in this group')      */     blankText : 'You must select one item in this group',          // private     defaultType : 'radio',          // private     groupCls : 'x-form-radio-group',          /**      * @event change      * Fires when the state of a child radio changes.      * @param {Ext.form.RadioGroup} this      * @param {Ext.form.Radio} checked The checked radio      */          /**      * Gets the selected {@link Ext.form.Radio} in the group, if it exists.      * @return {Ext.form.Radio} The selected radio.      */     getValue : function(){         var out = null;         this.eachItem(function(item){             if(item.checked){                 out = item;                 return false;             }         });         return out;     },          /**      * Sets the checked radio in the group.      * @param {String/Ext.form.Radio} id The radio to check.      * @param {Boolean} value The value to set the radio.      * @return {Ext.form.RadioGroup} this      */     setValue : function(id, value){         if(this.rendered){             if(arguments.length > 1){                 var f = this.getBox(id);                 if(f){                     f.setValue(value);                     if(f.checked){                         this.eachItem(function(item){                             if (item !== f){                                 item.setValue(false);                             }                         });                     }                 }             }else{                 this.setValueForItem(id);             }         }else{             this.values = arguments;         }         return this;     },          // private     fireChecked : function(){         if(!this.checkTask){             this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);         }         this.checkTask.delay(10);     },          // private     bufferChecked : function(){         var out = null;         this.eachItem(function(item){             if(item.checked){                 out = item;                 return false;             }         });         this.fireEvent('change', this, out);     },          onDestroy : function(){         if(this.checkTask){             this.checkTask.cancel();             this.checkTask = null;         }         Ext.form.RadioGroup.superclass.onDestroy.call(this);     } }); Ext.reg('radiogroup', Ext.form.RadioGroup); /**
  86.  * @class Ext.form.Hidden
  87.  * @extends Ext.form.Field
  88.  * A basic hidden field for storing hidden values in forms that need to be passed in the form submit.
  89.  * @constructor
  90.  * Create a new Hidden field.
  91.  * @param {Object} config Configuration options
  92.  * @xtype hidden
  93.  */
  94. Ext.form.Hidden = Ext.extend(Ext.form.Field, {
  95.     // private
  96.     inputType : 'hidden',
  97.     // private
  98.     onRender : function(){
  99.         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
  100.     },
  101.     // private
  102.     initEvents : function(){
  103.         this.originalValue = this.getValue();
  104.     },
  105.     // These are all private overrides
  106.     setSize : Ext.emptyFn,
  107.     setWidth : Ext.emptyFn,
  108.     setHeight : Ext.emptyFn,
  109.     setPosition : Ext.emptyFn,
  110.     setPagePosition : Ext.emptyFn,
  111.     markInvalid : Ext.emptyFn,
  112.     clearInvalid : Ext.emptyFn
  113. });
  114. Ext.reg('hidden', Ext.form.Hidden);/**  * @class Ext.form.BasicForm  * @extends Ext.util.Observable  * <p>Encapsulates the DOM &lt;form> element at the heart of the {@link Ext.form.FormPanel FormPanel} class, and provides  * input field management, validation, submission, and form loading services.</p>  * <p>By default, Ext Forms are submitted through Ajax, using an instance of {@link Ext.form.Action.Submit}.  * To enable normal browser submission of an Ext Form, use the {@link #standardSubmit} config option.</p>  * <p><b><u>File Uploads</u></b></p>  * <p>{@link #fileUpload File uploads} are not performed using Ajax submission, that  * is they are <b>not</b> performed using XMLHttpRequests. Instead the form is submitted in the standard  * manner with the DOM <tt>&lt;form></tt> element temporarily modified to have its  * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer  * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document  * but removed after the return data has been gathered.</p>  * <p>The server response is parsed by the browser to create the document for the IFRAME. If the  * server is using JSON to send the return object, then the  * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header  * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>  * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode  * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>  * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object  * is created containing a <tt>responseText</tt> property in order to conform to the  * requirements of event handlers and callbacks.</p>  * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>  * and some server technologies (notably JEE) may require some custom processing in order to  * retrieve parameter names and parameter values from the packet content.</p>  * @constructor  * @param {Mixed} el The form element or its id  * @param {Object} config Configuration options  */ Ext.form.BasicForm = function(el, config){     Ext.apply(this, config);     if(Ext.isString(this.paramOrder)){         this.paramOrder = this.paramOrder.split(/[s,|]/);     }     /*      * @property items      * A {@link Ext.util.MixedCollection MixedCollection) containing all the Ext.form.Fields in this form.      * @type MixedCollection      */     this.items = new Ext.util.MixedCollection(false, function(o){         return o.itemId || o.id || (o.id = Ext.id());     });     this.addEvents(         /**          * @event beforeaction          * Fires before any action is performed. Return false to cancel the action.          * @param {Form} this          * @param {Action} action The {@link Ext.form.Action} to be performed          */         'beforeaction',         /**          * @event actionfailed          * Fires when an action fails.          * @param {Form} this          * @param {Action} action The {@link Ext.form.Action} that failed          */         'actionfailed',         /**          * @event actioncomplete          * Fires when an action is completed.          * @param {Form} this          * @param {Action} action The {@link Ext.form.Action} that completed          */         'actioncomplete'     );     if(el){         this.initEl(el);     }     Ext.form.BasicForm.superclass.constructor.call(this); }; Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {     /**      * @cfg {String} method      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.      */     /**      * @cfg {DataReader} reader      * An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to read      * data when executing 'load' actions. This is optional as there is built-in      * support for processing JSON.  For additional information on using an XMLReader      * see the example provided in examples/form/xml-form.html.      */     /**      * @cfg {DataReader} errorReader      * <p>An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to      * read field error messages returned from 'submit' actions. This is optional      * as there is built-in support for processing JSON.</p>      * <p>The Records which provide messages for the invalid Fields must use the      * Field name (or id) as the Record ID, and must contain a field called 'msg'      * which contains the error message.</p>      * <p>The errorReader does not have to be a full-blown implementation of a      * DataReader. It simply needs to implement a <tt>read(xhr)</tt> function      * which returns an Array of Records in an object with the following      * structure:</p><pre><code> {     records: recordArray } </code></pre>      */     /**      * @cfg {String} url      * The URL to use for form actions if one isn't supplied in the      * <code>{@link #doAction doAction} options</code>.      */     /**      * @cfg {Boolean} fileUpload      * Set to true if this form is a file upload.      * <p>File uploads are not performed using normal 'Ajax' techniques, that is they are <b>not</b>      * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the      * DOM <tt>&lt;form></tt> element temporarily modified to have its      * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer      * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document      * but removed after the return data has been gathered.</p>      * <p>The server response is parsed by the browser to create the document for the IFRAME. If the      * server is using JSON to send the return object, then the      * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header      * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>      * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode      * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>      * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object      * is created containing a <tt>responseText</tt> property in order to conform to the      * requirements of event handlers and callbacks.</p>      * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>      * and some server technologies (notably JEE) may require some custom processing in order to      * retrieve parameter names and parameter values from the packet content.</p>      */     /**      * @cfg {Object} baseParams      * <p>Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.</p>      * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>      */     /**      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).      */     timeout: 30,     /**      * @cfg {Object} api (Optional) If specified load and submit actions will be handled      * with {@link Ext.form.Action.DirectLoad} and {@link Ext.form.Action.DirectSubmit}.      * Methods which have been imported by Ext.Direct can be specified here to load and submit      * forms.      * Such as the following:<pre><code> api: {     load: App.ss.MyProfile.load,     submit: App.ss.MyProfile.submit } </code></pre>      * <p>Load actions can use <code>{@link #paramOrder}</code> or <code>{@link #paramsAsHash}</code>      * to customize how the load method is invoked.      * Submit actions will always use a standard form submit. The formHandler configuration must      * be set on the associated server-side method which has been imported by Ext.Direct</p>      */     /**      * @cfg {Array/String} paramOrder <p>A list of params to be executed server side.      * Defaults to <tt>undefined</tt>. Only used for the <code>{@link #api}</code>      * <code>load</code> configuration.</p>      * <br><p>Specify the params in the order in which they must be executed on the      * server-side as either (1) an Array of String values, or (2) a String of params      * delimited by either whitespace, comma, or pipe. For example,      * any of the following would be acceptable:</p><pre><code> paramOrder: ['param1','param2','param3'] paramOrder: 'param1 param2 param3' paramOrder: 'param1,param2,param3' paramOrder: 'param1|param2|param'      </code></pre>      */     paramOrder: undefined,     /**      * @cfg {Boolean} paramsAsHash Only used for the <code>{@link #api}</code>      * <code>load</code> configuration. Send parameters as a collection of named      * arguments (defaults to <tt>false</tt>). Providing a      * <tt>{@link #paramOrder}</tt> nullifies this configuration.      */     paramsAsHash: false,     // private     activeAction : null,     /**      * @cfg {Boolean} trackResetOnLoad If set to <tt>true</tt>, {@link #reset}() resets to the last loaded      * or {@link #setValues}() data instead of when the form was first created.  Defaults to <tt>false</tt>.      */     trackResetOnLoad : false,     /**      * @cfg {Boolean} standardSubmit If set to true, standard HTML form submits are used instead of XHR (Ajax) style      * form submissions. (defaults to false)<br>      * <p><b>Note:</b> When using standardSubmit, the options to {@link #submit} are ignored because Ext's      * Ajax infrastracture is bypassed. To pass extra parameters (baseParams and params), you will need to      * create hidden fields within the form.</p>      * <p>The url config option is also bypassed, so set the action as well:</p>      * <pre><code> PANEL.getForm().getEl().dom.action = 'URL'      * </code></pre>      * An example encapsulating the above:      * <pre><code> new Ext.FormPanel({     standardSubmit: true,     baseParams: {         foo: 'bar'     },     url: 'myProcess.php',     items: [{         xtype: 'textfield',         name: 'userName'     }],     buttons: [{         text: 'Save',         handler: function(){             var O = this.ownerCt;             if (O.getForm().isValid()) {                 if (O.url)                     O.getForm().getEl().dom.action = O.url;                 if (O.baseParams) {                     for (i in O.baseParams) {                         O.add({                             xtype: 'hidden',                             name: i,                             value: O.baseParams[i]                         })                     }                     O.doLayout();                 }                 O.getForm().submit();             }         }     }] });      * </code></pre>      */     /**      * By default wait messages are displayed with Ext.MessageBox.wait. You can target a specific      * element by passing it or its id or mask the form itself by passing in true.      * @type Mixed      * @property waitMsgTarget      */     // private     initEl : function(el){         this.el = Ext.get(el);         this.id = this.el.id || Ext.id();         if(!this.standardSubmit){             this.el.on('submit', this.onSubmit, this);         }         this.el.addClass('x-form');     },     /**      * Get the HTML form Element      * @return Ext.Element      */     getEl: function(){         return this.el;     },     // private     onSubmit : function(e){         e.stopEvent();     },     // private     destroy: function() {         this.items.each(function(f){             Ext.destroy(f);         });         if(this.el){             this.el.removeAllListeners();             this.el.remove();         }         this.purgeListeners();     },     /**      * Returns true if client-side validation on the form is successful.      * @return Boolean      */     isValid : function(){         var valid = true;         this.items.each(function(f){            if(!f.validate()){                valid = false;            }         });         return valid;     },     /**      * <p>Returns true if any fields in this form have changed from their original values.</p>      * <p>Note that if this BasicForm was configured with {@link #trackResetOnLoad} then the      * Fields' <i>original values</i> are updated when the values are loaded by {@link #setValues}      * or {@link #loadRecord}.</p>      * @return Boolean      */     isDirty : function(){         var dirty = false;         this.items.each(function(f){            if(f.isDirty()){                dirty = true;                return false;            }         });         return dirty;     },     /**      * Performs a predefined action ({@link Ext.form.Action.Submit} or      * {@link Ext.form.Action.Load}) or a custom extension of {@link Ext.form.Action}      * to perform application-specific processing.      * @param {String/Object} actionName The name of the predefined action type,      * or instance of {@link Ext.form.Action} to perform.      * @param {Object} options (optional) The options to pass to the {@link Ext.form.Action}.      * All of the config options listed below are supported by both the      * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}      * actions unless otherwise noted (custom actions could also accept      * other config options):<ul>      *      * <li><b>url</b> : String<div class="sub-desc">The url for the action (defaults      * to the form's {@link #url}.)</div></li>      *      * <li><b>method</b> : String<div class="sub-desc">The form method to use (defaults      * to the form's method, or POST if not defined)</div></li>      *      * <li><b>params</b> : String/Object<div class="sub-desc"><p>The params to pass      * (defaults to the form's baseParams, or none if not defined)</p>      * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>      *      * <li><b>headers</b> : Object<div class="sub-desc">Request headers to set for the action      * (defaults to the form's default headers)</div></li>      *      * <li><b>success</b> : Function<div class="sub-desc">The callback that will      * be invoked after a successful response (see top of      * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}      * for a description of what constitutes a successful response).      * The function is passed the following parameters:<ul>      * <li><tt>form</tt> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>      * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.      * <div class="sub-desc">The action object contains these properties of interest:<ul>      * <li><tt>{@link Ext.form.Action#response response}</tt></li>      * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>      * <li><tt>{@link Ext.form.Action#type type}</tt></li>      * </ul></div></li></ul></div></li>      *      * <li><b>failure</b> : Function<div class="sub-desc">The callback that will be invoked after a      * failed transaction attempt. The function is passed the following parameters:<ul>      * <li><tt>form</tt> : The {@link Ext.form.BasicForm} that requested the action.</li>      * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.      * <div class="sub-desc">The action object contains these properties of interest:<ul>      * <li><tt>{@link Ext.form.Action#failureType failureType}</tt></li>      * <li><tt>{@link Ext.form.Action#response response}</tt></li>      * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>      * <li><tt>{@link Ext.form.Action#type type}</tt></li>      * </ul></div></li></ul></div></li>      *      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the      * callback functions (The <tt>this</tt> reference for the callback functions).</div></li>      *      * <li><b>clientValidation</b> : Boolean<div class="sub-desc">Submit Action only.      * Determines whether a Form's fields are validated in a final call to      * {@link Ext.form.BasicForm#isValid isValid} prior to submission. Set to <tt>false</tt>      * to prevent this. If undefined, pre-submission field validation is performed.</div></li></ul>      *      * @return {BasicForm} this      */     doAction : function(action, options){         if(Ext.isString(action)){             action = new Ext.form.Action.ACTION_TYPES[action](this, options);         }         if(this.fireEvent('beforeaction', this, action) !== false){             this.beforeAction(action);             action.run.defer(100, action);         }         return this;     },     /**      * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Submit submit action}.      * @param {Object} options The options to pass to the action (see {@link #doAction} for details).<br>      * <p><b>Note:</b> this is ignored when using the {@link #standardSubmit} option.</p>      * <p>The following code:</p><pre><code> myFormPanel.getForm().submit({     clientValidation: true,     url: 'updateConsignment.php',     params: {         newStatus: 'delivered'     },     success: function(form, action) {        Ext.Msg.alert('Success', action.result.msg);     },     failure: function(form, action) {         switch (action.failureType) {             case Ext.form.Action.CLIENT_INVALID:                 Ext.Msg.alert('Failure', 'Form fields may not be submitted with invalid values');                 break;             case Ext.form.Action.CONNECT_FAILURE:                 Ext.Msg.alert('Failure', 'Ajax communication failed');                 break;             case Ext.form.Action.SERVER_INVALID:                Ext.Msg.alert('Failure', action.result.msg);        }     } }); </code></pre>      * would process the following server response for a successful submission:<pre><code> {     "success":true, // note this is Boolean, not string     "msg":"Consignment updated" } </code></pre>      * and the following server response for a failed submission:<pre><code> {     "success":false, // note this is Boolean, not string     "msg":"You do not have permission to perform this operation" } </code></pre>      * @return {BasicForm} this      */     submit : function(options){         if(this.standardSubmit){             var v = this.isValid();             if(v){                 this.el.dom.submit();             }             return v;         }         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');         this.doAction(submitAction, options);         return this;     },     /**      * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Load load action}.      * @param {Object} options The options to pass to the action (see {@link #doAction} for details)      * @return {BasicForm} this      */     load : function(options){         var loadAction = String.format('{0}load', this.api ? 'direct' : '');         this.doAction(loadAction, options);         return this;     },     /**      * Persists the values in this form into the passed {@link Ext.data.Record} object in a beginEdit/endEdit block.      * @param {Record} record The record to edit      * @return {BasicForm} this      */     updateRecord : function(record){         record.beginEdit();         var fs = record.fields;         fs.each(function(f){             var field = this.findField(f.name);             if(field){                 record.set(f.name, field.getValue());             }         }, this);         record.endEdit();         return this;     },     /**      * Loads an {@link Ext.data.Record} into this form by calling {@link #setValues} with the      * {@link Ext.data.Record#data record data}.      * See also {@link #trackResetOnLoad}.      * @param {Record} record The record to load      * @return {BasicForm} this      */     loadRecord : function(record){         this.setValues(record.data);         return this;     },     // private     beforeAction : function(action){         var o = action.options;         if(o.waitMsg){             if(this.waitMsgTarget === true){                 this.el.mask(o.waitMsg, 'x-mask-loading');             }else if(this.waitMsgTarget){                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');             }else{                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');             }         }     },     // private     afterAction : function(action, success){         this.activeAction = null;         var o = action.options;         if(o.waitMsg){             if(this.waitMsgTarget === true){                 this.el.unmask();             }else if(this.waitMsgTarget){                 this.waitMsgTarget.unmask();             }else{                 Ext.MessageBox.updateProgress(1);                 Ext.MessageBox.hide();             }         }         if(success){             if(o.reset){                 this.reset();             }             Ext.callback(o.success, o.scope, [this, action]);             this.fireEvent('actioncomplete', this, action);         }else{             Ext.callback(o.failure, o.scope, [this, action]);             this.fireEvent('actionfailed', this, action);         }     },     /**      * Find a {@link Ext.form.Field} in this form.      * @param {String} id The value to search for (specify either a {@link Ext.Component#id id},      * {@link Ext.grid.Column#dataIndex dataIndex}, {@link Ext.form.Field#getName name or hiddenName}).      * @return Field      */     findField : function(id){         var field = this.items.get(id);         if(!Ext.isObject(field)){             this.items.each(function(f){                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){                     field = f;                     return false;                 }             });         }         return field || null;     },     /**      * Mark fields in this form invalid in bulk.      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}      * @return {BasicForm} this      */     markInvalid : function(errors){         if(Ext.isArray(errors)){             for(var i = 0, len = errors.length; i < len; i++){                 var fieldError = errors[i];                 var f = this.findField(fieldError.id);                 if(f){                     f.markInvalid(fieldError.msg);                 }             }         }else{             var field, id;             for(id in errors){                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){                     field.markInvalid(errors[id]);                 }             }         }         return this;     },     /**      * Set values for fields in this form in bulk.      * @param {Array/Object} values Either an array in the form:<pre><code> [{id:'clientName', value:'Fred. Olsen Lines'},  {id:'portOfLoading', value:'FXT'},  {id:'portOfDischarge', value:'OSL'} ]</code></pre>      * or an object hash of the form:<pre><code> {     clientName: 'Fred. Olsen Lines',     portOfLoading: 'FXT',     portOfDischarge: 'OSL' }</code></pre>      * @return {BasicForm} this      */     setValues : function(values){         if(Ext.isArray(values)){ // array of objects             for(var i = 0, len = values.length; i < len; i++){                 var v = values[i];                 var f = this.findField(v.id);                 if(f){                     f.setValue(v.value);                     if(this.trackResetOnLoad){                         f.originalValue = f.getValue();                     }                 }             }         }else{ // object hash             var field, id;             for(id in values){                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){                     field.setValue(values[id]);                     if(this.trackResetOnLoad){                         field.originalValue = field.getValue();                     }                 }             }         }         return this;     },     /**      * <p>Returns the fields in this form as an object with key/value pairs as they would be submitted using a standard form submit.      * If multiple fields exist with the same name they are returned as an array.</p>      * <p><b>Note:</b> The values are collected from all enabled HTML input elements within the form, <u>not</u> from      * the Ext Field objects. This means that all returned values are Strings (or Arrays of Strings) and that the      * value can potentially be the emptyText of a field.</p>      * @param {Boolean} asString (optional) Pass true to return the values as a string. (defaults to false, returning an Object)      * @return {String/Object}      */     getValues : function(asString){         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);         if(asString === true){             return fs;         }         return Ext.urlDecode(fs);     },     getFieldValues : function(){         var o = {};         this.items.each(function(f){            o[f.getName()] = f.getValue();         });         return o;     },     /**      * Clears all invalid messages in this form.      * @return {BasicForm} this      */     clearInvalid : function(){         this.items.each(function(f){            f.clearInvalid();         });         return this;     },     /**      * Resets this form.      * @return {BasicForm} this      */     reset : function(){         this.items.each(function(f){             f.reset();         });         return this;     },     /**      * Add Ext.form Components to this form's Collection. This does not result in rendering of      * the passed Component, it just enables the form to validate Fields, and distribute values to      * Fields.      * <p><b>You will not usually call this function. In order to be rendered, a Field must be added      * to a {@link Ext.Container Container}, usually an {@link Ext.form.FormPanel FormPanel}.      * The FormPanel to which the field is added takes care of adding the Field to the BasicForm's      * collection.</b></p>      * @param {Field} field1      * @param {Field} field2 (optional)      * @param {Field} etc (optional)      * @return {BasicForm} this      */     add : function(){         this.items.addAll(Array.prototype.slice.call(arguments, 0));         return this;     },     /**      * Removes a field from the items collection (does NOT remove its markup).      * @param {Field} field      * @return {BasicForm} this      */     remove : function(field){         this.items.remove(field);         return this;     },     /**      * Iterates through the {@link Ext.form.Field Field}s which have been {@link #add add}ed to this BasicForm,      * checks them for an id attribute, and calls {@link Ext.form.Field#applyToMarkup} on the existing dom element with that id.      * @return {BasicForm} this      */     render : function(){         this.items.each(function(f){             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists                 f.applyToMarkup(f.id);             }         });         return this;     },     /**      * Calls {@link Ext#apply} for all fields in this form with the passed object.      * @param {Object} values      * @return {BasicForm} this      */     applyToFields : function(o){         this.items.each(function(f){            Ext.apply(f, o);         });         return this;     },     /**      * Calls {@link Ext#applyIf} for all field in this form with the passed object.      * @param {Object} values      * @return {BasicForm} this      */     applyIfToFields : function(o){         this.items.each(function(f){            Ext.applyIf(f, o);         });         return this;     },     callFieldMethod : function(fnName, args){         args = args || [];         this.items.each(function(f){             if(Ext.isFunction(f[fnName])){                 f[fnName].apply(f, args);             }         });         return this;     } }); // back compat Ext.BasicForm = Ext.form.BasicForm;/**  * @class Ext.form.FormPanel  * @extends Ext.Panel  * <p>Standard form container.</p>  *   * <p><b><u>Layout</u></b></p>  * <p>By default, FormPanel is configured with <tt>layout:'form'</tt> to use an {@link Ext.layout.FormLayout}  * layout manager, which styles and renders fields and labels correctly. When nesting additional Containers  * within a FormPanel, you should ensure that any descendant Containers which host input Fields use the  * {@link Ext.layout.FormLayout} layout manager.</p>  *   * <p><b><u>BasicForm</u></b></p>  * <p>Although <b>not listed</b> as configuration options of FormPanel, the FormPanel class accepts all  * of the config options required to configure its internal {@link Ext.form.BasicForm} for:  * <div class="mdetail-params"><ul>  * <li>{@link Ext.form.BasicForm#fileUpload file uploads}</li>  * <li>functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form</li>  * </ul></div>  *    * <p><b>Note</b>: If subclassing FormPanel, any configuration options for the BasicForm must be applied to  * the <tt><b>initialConfig</b></tt> property of the FormPanel. Applying {@link Ext.form.BasicForm BasicForm}  * configuration settings to <b><tt>this</tt></b> will <b>not</b> affect the BasicForm's configuration.</p>  *   * <p><b><u>Form Validation</u></b></p>  * <p>For information on form validation see the following:</p>  * <div class="mdetail-params"><ul>  * <li>{@link Ext.form.TextField}</li>  * <li>{@link Ext.form.VTypes}</li>  * <li>{@link Ext.form.BasicForm#doAction BasicForm.doAction <b>clientValidation</b> notes}</li>  * <li><tt>{@link Ext.form.FormPanel#monitorValid monitorValid}</tt></li>  * </ul></div>  *   * <p><b><u>Form Submission</u></b></p>  * <p>By default, Ext Forms are submitted through Ajax, using {@link Ext.form.Action}. To enable normal browser  * submission of the {@link Ext.form.BasicForm BasicForm} contained in this FormPanel, see the  * <tt><b>{@link Ext.form.BasicForm#standardSubmit standardSubmit}</b></tt> option.</p>  *   * @constructor  * @param {Object} config Configuration options  * @xtype form  */ Ext.FormPanel = Ext.extend(Ext.Panel, { /**  * @cfg {String} formId (optional) The id of the FORM tag (defaults to an auto-generated id).  */     /**      * @cfg {Boolean} hideLabels      * <p><tt>true</tt> to hide field labels by default (sets <tt>display:none</tt>). Defaults to      * <tt>false</tt>.</p>      * <p>Also see {@link Ext.Component}.<tt>{@link Ext.Component#hideLabel hideLabel}</tt>.      */     /**      * @cfg {Number} labelPad      * The default padding in pixels for field labels (defaults to <tt>5</tt>). <tt>labelPad</tt> only      * applies if <tt>{@link #labelWidth}</tt> is also specified, otherwise it will be ignored.      */     /**      * @cfg {String} labelSeparator      * See {@link Ext.Component}.<tt>{@link Ext.Component#labelSeparator labelSeparator}</tt>      */     /**      * @cfg {Number} labelWidth The width of labels in pixels. This property cascades to child containers      * and can be overridden on any child container (e.g., a fieldset can specify a different <tt>labelWidth</tt>      * for its fields) (defaults to <tt>100</tt>).      */     /**      * @cfg {String} itemCls A css class to apply to the x-form-item of fields. This property cascades to child containers.      */     /**      * @cfg {Array} buttons      * An array of {@link Ext.Button}s or {@link Ext.Button} configs used to add buttons to the footer of this FormPanel.<br>      * <p>Buttons in the footer of a FormPanel may be configured with the option <tt>formBind: true</tt>. This causes      * the form's {@link #monitorValid valid state monitor task} to enable/disable those Buttons depending on      * the form's valid/invalid state.</p>      */     /**      * @cfg {Number} minButtonWidth Minimum width of all buttons in pixels (defaults to <tt>75</tt>).      */     minButtonWidth : 75,     /**      * @cfg {String} labelAlign The label alignment value used for the <tt>text-align</tt> specification      * for the <b>container</b>. Valid values are <tt>"left</tt>", <tt>"top"</tt> or <tt>"right"</tt>      * (defaults to <tt>"left"</tt>). This property cascades to child <b>containers</b> and can be      * overridden on any child <b>container</b> (e.g., a fieldset can specify a different <tt>labelAlign</tt>      * for its fields).      */     labelAlign : 'left',     /**      * @cfg {Boolean} monitorValid If <tt>true</tt>, the form monitors its valid state <b>client-side</b> and      * regularly fires the {@link #clientvalidation} event passing that state.<br>      * <p>When monitoring valid state, the FormPanel enables/disables any of its configured      * {@link #buttons} which have been configured with <code>formBind: true</code> depending      * on whether the {@link Ext.form.BasicForm#isValid form is valid} or not. Defaults to <tt>false</tt></p>      */     monitorValid : false,     /**      * @cfg {Number} monitorPoll The milliseconds to poll valid state, ignored if monitorValid is not true (defaults to 200)      */     monitorPoll : 200,     /**      * @cfg {String} layout Defaults to <tt>'form'</tt>.  Normally this configuration property should not be altered.       * For additional details see {@link Ext.layout.FormLayout} and {@link Ext.Container#layout Ext.Container.layout}.      */     layout : 'form',     // private     initComponent : function(){         this.form = this.createForm();         Ext.FormPanel.superclass.initComponent.call(this);         this.bodyCfg = {             tag: 'form',             cls: this.baseCls + '-body',             method : this.method || 'POST',             id : this.formId || Ext.id()         };         if(this.fileUpload) {             this.bodyCfg.enctype = 'multipart/form-data';         }         this.initItems();                  this.addEvents(             /**              * @event clientvalidation              * If the monitorValid config option is true, this event fires repetitively to notify of valid state              * @param {Ext.form.FormPanel} this              * @param {Boolean} valid true if the form has passed client-side validation              */             'clientvalidation'         );         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);     },     // private     createForm : function(){         var config = Ext.applyIf({listeners: {}}, this.initialConfig);         return new Ext.form.BasicForm(null, config);     },     // private     initFields : function(){         var f = this.form;         var formPanel = this;         var fn = function(c){             if(formPanel.isField(c)){                 f.add(c);             }if(c.isFieldWrap){                 Ext.applyIf(c, {                     labelAlign: c.ownerCt.labelAlign,                     labelWidth: c.ownerCt.labelWidth,                     itemCls: c.ownerCt.itemCls                 });                 f.add(c.field);             }else if(c.doLayout && c != formPanel){                 Ext.applyIf(c, {                     labelAlign: c.ownerCt.labelAlign,                     labelWidth: c.ownerCt.labelWidth,                     itemCls: c.ownerCt.itemCls                 });                 //each check required for check/radio groups.                 if(c.items && c.items.each){                     c.items.each(fn, this);                 }             }         };         this.items.each(fn, this);     },     // private     getLayoutTarget : function(){         return this.form.el;     },     /**      * Provides access to the {@link Ext.form.BasicForm Form} which this Panel contains.      * @return {Ext.form.BasicForm} The {@link Ext.form.BasicForm Form} which this Panel contains.      */     getForm : function(){         return this.form;     },     // private     onRender : function(ct, position){         this.initFields();         Ext.FormPanel.superclass.onRender.call(this, ct, position);         this.form.initEl(this.body);     },          // private     beforeDestroy : function(){         this.stopMonitoring();         Ext.FormPanel.superclass.beforeDestroy.call(this);         /*          * Clear the items here to prevent them being destroyed again.          * Don't move this behaviour to BasicForm because it can be used          * on it's own.          */         this.form.items.clear();         Ext.destroy(this.form);     }, // Determine if a Component is usable as a form Field.     isField : function(c) {         return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;     },     // private     initEvents : function(){         Ext.FormPanel.superclass.initEvents.call(this);         this.on('remove', this.onRemove, this);         this.on('add', this.onAdd, this);         if(this.monitorValid){ // initialize after render             this.startMonitoring();         }     },          // private     onAdd : function(ct, c) { // If a single form Field, add it         if (this.isField(c)) {             this.form.add(c); // If a Container, add any Fields it might contain         } else if (c.findBy) {             Ext.applyIf(c, {                 labelAlign: c.ownerCt.labelAlign,                 labelWidth: c.ownerCt.labelWidth,                 itemCls: c.ownerCt.itemCls             });             this.form.add.apply(this.form, c.findBy(this.isField));         }     },     // private     onRemove : function(ct, c) { // If a single form Field, remove it         if (this.isField(c)) {             Ext.destroy(c.container.up('.x-form-item'));          this.form.remove(c); // If a Container, remove any Fields it might contain         } else if (c.findByType) {             Ext.each(c.findBy(this.isField), this.form.remove, this.form);         }     },     /**      * Starts monitoring of the valid state of this form. Usually this is done by passing the config      * option "monitorValid"      */     startMonitoring : function(){         if(!this.validTask){             this.validTask = new Ext.util.TaskRunner();             this.validTask.start({                 run : this.bindHandler,                 interval : this.monitorPoll || 200,                 scope: this             });         }     },     /**      * Stops monitoring of the valid state of this form      */     stopMonitoring : function(){         if(this.validTask){             this.validTask.stopAll();             this.validTask = null;         }     },     /**      * This is a proxy for the underlying BasicForm's {@link Ext.form.BasicForm#load} call.      * @param {Object} options The options to pass to the action (see {@link Ext.form.BasicForm#doAction} for details)      */     load : function(){         this.form.load.apply(this.form, arguments);       },     // private     onDisable : function(){         Ext.FormPanel.superclass.onDisable.call(this);         if(this.form){             this.form.items.each(function(){                  this.disable();             });         }     },     // private     onEnable : function(){         Ext.FormPanel.superclass.onEnable.call(this);         if(this.form){             this.form.items.each(function(){                  this.enable();             });         }     },     // private     bindHandler : function(){         var valid = true;         this.form.items.each(function(f){             if(!f.isValid(true)){                 valid = false;                 return false;             }         });         if(this.fbar){             var fitems = this.fbar.items.items;             for(var i = 0, len = fitems.length; i < len; i++){                 var btn = fitems[i];                 if(btn.formBind === true && btn.disabled === valid){                     btn.setDisabled(!valid);                 }             }         }         this.fireEvent('clientvalidation', this, valid);     } }); Ext.reg('form', Ext.FormPanel); Ext.form.FormPanel = Ext.FormPanel; /**
  115.  * @class Ext.form.FieldSet
  116.  * @extends Ext.Panel
  117.  * Standard container used for grouping items within a {@link Ext.form.FormPanel form}.
  118.  * <pre><code>
  119. var form = new Ext.FormPanel({
  120.     title: 'Simple Form with FieldSets',
  121.     labelWidth: 75, // label settings here cascade unless overridden
  122.     url: 'save-form.php',
  123.     frame:true,
  124.     bodyStyle:'padding:5px 5px 0',
  125.     width: 700,
  126.     renderTo: document.body,
  127.     layout:'column', // arrange items in columns
  128.     defaults: {      // defaults applied to items
  129.         layout: 'form',
  130.         border: false,
  131.         bodyStyle: 'padding:4px'
  132.     },
  133.     items: [{
  134.         // Fieldset in Column 1
  135.         xtype:'fieldset',
  136.         columnWidth: 0.5,
  137.         title: 'Fieldset 1',
  138.         collapsible: true,
  139.         autoHeight:true,
  140.         defaults: {
  141.             anchor: '-20' // leave room for error icon
  142.         },
  143.         defaultType: 'textfield',
  144.         items :[{
  145.                 fieldLabel: 'Field 1'
  146.             }, {
  147.                 fieldLabel: 'Field 2'
  148.             }, {
  149.                 fieldLabel: 'Field 3'
  150.             }
  151.         ]
  152.     },{
  153.         // Fieldset in Column 2 - Panel inside
  154.         xtype:'fieldset',
  155.         title: 'Show Panel', // title, header, or checkboxToggle creates fieldset header
  156.         autoHeight:true,
  157.         columnWidth: 0.5,
  158.         checkboxToggle: true,
  159.         collapsed: true, // fieldset initially collapsed
  160.         layout:'anchor',
  161.         items :[{
  162.             xtype: 'panel',
  163.             anchor: '100%',
  164.             title: 'Panel inside a fieldset',
  165.             frame: true,
  166.             height: 100
  167.         }]
  168.     }]
  169. });
  170.  * </code></pre>
  171.  * @constructor
  172.  * @param {Object} config Configuration options
  173.  * @xtype fieldset
  174.  */
  175. Ext.form.FieldSet = Ext.extend(Ext.Panel, {
  176.     /**
  177.      * @cfg {Mixed} checkboxToggle <tt>true</tt> to render a checkbox into the fieldset frame just
  178.      * in front of the legend to expand/collapse the fieldset when the checkbox is toggled. (defaults
  179.      * to <tt>false</tt>).
  180.      * <p>A {@link Ext.DomHelper DomHelper} element spec may also be specified to create the checkbox.
  181.      * If <tt>true</tt> is specified, the default DomHelper config object used to create the element
  182.      * is:</p><pre><code>
  183.      * {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'}
  184.      * </code></pre>   
  185.      */
  186.     /**
  187.      * @cfg {String} checkboxName The name to assign to the fieldset's checkbox if <tt>{@link #checkboxToggle} = true</tt>
  188.      * (defaults to <tt>'[checkbox id]-checkbox'</tt>).
  189.      */
  190.     /**
  191.      * @cfg {Boolean} collapsible
  192.      * <tt>true</tt> to make the fieldset collapsible and have the expand/collapse toggle button automatically
  193.      * rendered into the legend element, <tt>false</tt> to keep the fieldset statically sized with no collapse
  194.      * button (defaults to <tt>false</tt>). Another option is to configure <tt>{@link #checkboxToggle}</tt>.
  195.      */
  196.     /**
  197.      * @cfg {Number} labelWidth The width of labels. This property cascades to child containers.
  198.      */
  199.     /**
  200.      * @cfg {String} itemCls A css class to apply to the <tt>x-form-item</tt> of fields (see 
  201.      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} for details).
  202.      * This property cascades to child containers.
  203.      */
  204.     /**
  205.      * @cfg {String} baseCls The base CSS class applied to the fieldset (defaults to <tt>'x-fieldset'</tt>).
  206.      */
  207.     baseCls : 'x-fieldset',
  208.     /**
  209.      * @cfg {String} layout The {@link Ext.Container#layout} to use inside the fieldset (defaults to <tt>'form'</tt>).
  210.      */
  211.     layout : 'form',
  212.     /**
  213.      * @cfg {Boolean} animCollapse
  214.      * <tt>true</tt> to animate the transition when the panel is collapsed, <tt>false</tt> to skip the
  215.      * animation (defaults to <tt>false</tt>).
  216.      */
  217.     animCollapse : false,
  218.     // private
  219.     onRender : function(ct, position){
  220.         if(!this.el){
  221.             this.el = document.createElement('fieldset');
  222.             this.el.id = this.id;
  223.             if (this.title || this.header || this.checkboxToggle) {
  224.                 this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';
  225.             }
  226.         }
  227.         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
  228.         if(this.checkboxToggle){
  229.             var o = typeof this.checkboxToggle == 'object' ?
  230.                     this.checkboxToggle :
  231.                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
  232.             this.checkbox = this.header.insertFirst(o);
  233.             this.checkbox.dom.checked = !this.collapsed;
  234.             this.mon(this.checkbox, 'click', this.onCheckClick, this);
  235.         }
  236.     },
  237.     // private
  238.     onCollapse : function(doAnim, animArg){
  239.         if(this.checkbox){
  240.             this.checkbox.dom.checked = false;
  241.         }
  242.         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
  243.     },
  244.     // private
  245.     onExpand : function(doAnim, animArg){
  246.         if(this.checkbox){
  247.             this.checkbox.dom.checked = true;
  248.         }
  249.         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
  250.     },
  251.     /**
  252.      * This function is called by the fieldset's checkbox when it is toggled (only applies when
  253.      * checkboxToggle = true).  This method should never be called externally, but can be
  254.      * overridden to provide custom behavior when the checkbox is toggled if needed.
  255.      */
  256.     onCheckClick : function(){
  257.         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
  258.     }
  259.     /**
  260.      * @cfg {String/Number} activeItem
  261.      * @hide
  262.      */
  263.     /**
  264.      * @cfg {Mixed} applyTo
  265.      * @hide
  266.      */
  267.     /**
  268.      * @cfg {Boolean} bodyBorder
  269.      * @hide
  270.      */
  271.     /**
  272.      * @cfg {Boolean} border
  273.      * @hide
  274.      */
  275.     /**
  276.      * @cfg {Boolean/Number} bufferResize
  277.      * @hide
  278.      */
  279.     /**
  280.      * @cfg {Boolean} collapseFirst
  281.      * @hide
  282.      */
  283.     /**
  284.      * @cfg {String} defaultType
  285.      * @hide
  286.      */
  287.     /**
  288.      * @cfg {String} disabledClass
  289.      * @hide
  290.      */
  291.     /**
  292.      * @cfg {String} elements
  293.      * @hide
  294.      */
  295.     /**
  296.      * @cfg {Boolean} floating
  297.      * @hide
  298.      */
  299.     /**
  300.      * @cfg {Boolean} footer
  301.      * @hide
  302.      */
  303.     /**
  304.      * @cfg {Boolean} frame
  305.      * @hide
  306.      */
  307.     /**
  308.      * @cfg {Boolean} header
  309.      * @hide
  310.      */
  311.     /**
  312.      * @cfg {Boolean} headerAsText
  313.      * @hide
  314.      */
  315.     /**
  316.      * @cfg {Boolean} hideCollapseTool
  317.      * @hide
  318.      */
  319.     /**
  320.      * @cfg {String} iconCls
  321.      * @hide
  322.      */
  323.     /**
  324.      * @cfg {Boolean/String} shadow
  325.      * @hide
  326.      */
  327.     /**
  328.      * @cfg {Number} shadowOffset
  329.      * @hide
  330.      */
  331.     /**
  332.      * @cfg {Boolean} shim
  333.      * @hide
  334.      */
  335.     /**
  336.      * @cfg {Object/Array} tbar
  337.      * @hide
  338.      */
  339.     /**
  340.      * @cfg {String} tabTip
  341.      * @hide
  342.      */
  343.     /**
  344.      * @cfg {Boolean} titleCollapse
  345.      * @hide
  346.      */
  347.     /**
  348.      * @cfg {Array} tools
  349.      * @hide
  350.      */
  351.     /**
  352.      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
  353.      * @hide
  354.      */
  355.     /**
  356.      * @cfg {String} xtype
  357.      * @hide
  358.      */
  359.     /**
  360.      * @property header
  361.      * @hide
  362.      */
  363.     /**
  364.      * @property footer
  365.      * @hide
  366.      */
  367.     /**
  368.      * @method focus
  369.      * @hide
  370.      */
  371.     /**
  372.      * @method getBottomToolbar
  373.      * @hide
  374.      */
  375.     /**
  376.      * @method getTopToolbar
  377.      * @hide
  378.      */
  379.     /**
  380.      * @method setIconClass
  381.      * @hide
  382.      */
  383.     /**
  384.      * @event activate
  385.      * @hide
  386.      */
  387.     /**
  388.      * @event beforeclose
  389.      * @hide
  390.      */
  391.     /**
  392.      * @event bodyresize
  393.      * @hide
  394.      */
  395.     /**
  396.      * @event close
  397.      * @hide
  398.      */
  399.     /**
  400.      * @event deactivate
  401.      * @hide
  402.      */
  403. });
  404. Ext.reg('fieldset', Ext.form.FieldSet);
  405. /**
  406.  * @class Ext.form.HtmlEditor
  407.  * @extends Ext.form.Field
  408.  * Provides a lightweight HTML Editor component. Some toolbar features are not supported by Safari and will be 
  409.  * automatically hidden when needed.  These are noted in the config options where appropriate.
  410.  * <br><br>The editor's toolbar buttons have tooltips defined in the {@link #buttonTips} property, but they are not 
  411.  * enabled by default unless the global {@link Ext.QuickTips} singleton is {@link Ext.QuickTips#init initialized}.
  412.  * <br><br><b>Note: The focus/blur and validation marking functionality inherited from Ext.form.Field is NOT
  413.  * supported by this editor.</b>
  414.  * <br><br>An Editor is a sensitive component that can't be used in all spots standard fields can be used. Putting an Editor within
  415.  * any element that has display set to 'none' can cause problems in Safari and Firefox due to their default iframe reloading bugs.
  416.  * <br><br>Example usage:
  417.  * <pre><code>
  418. // Simple example rendered with default options:
  419. Ext.QuickTips.init();  // enable tooltips
  420. new Ext.form.HtmlEditor({
  421.     renderTo: Ext.getBody(),
  422.     width: 800,
  423.     height: 300
  424. });
  425. // Passed via xtype into a container and with custom options:
  426. Ext.QuickTips.init();  // enable tooltips
  427. new Ext.Panel({
  428.     title: 'HTML Editor',
  429.     renderTo: Ext.getBody(),
  430.     width: 600,
  431.     height: 300,
  432.     frame: true,
  433.     layout: 'fit',
  434.     items: {
  435.         xtype: 'htmleditor',
  436.         enableColors: false,
  437.         enableAlignments: false
  438.     }
  439. });
  440. </code></pre>
  441.  * @constructor
  442.  * Create a new HtmlEditor
  443.  * @param {Object} config
  444.  * @xtype htmleditor
  445.  */
  446. Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
  447.     /**
  448.      * @cfg {Boolean} enableFormat Enable the bold, italic and underline buttons (defaults to true)
  449.      */
  450.     enableFormat : true,
  451.     /**
  452.      * @cfg {Boolean} enableFontSize Enable the increase/decrease font size buttons (defaults to true)
  453.      */
  454.     enableFontSize : true,
  455.     /**
  456.      * @cfg {Boolean} enableColors Enable the fore/highlight color buttons (defaults to true)
  457.      */
  458.     enableColors : true,
  459.     /**
  460.      * @cfg {Boolean} enableAlignments Enable the left, center, right alignment buttons (defaults to true)
  461.      */
  462.     enableAlignments : true,
  463.     /**
  464.      * @cfg {Boolean} enableLists Enable the bullet and numbered list buttons. Not available in Safari. (defaults to true)
  465.      */
  466.     enableLists : true,
  467.     /**
  468.      * @cfg {Boolean} enableSourceEdit Enable the switch to source edit button. Not available in Safari. (defaults to true)
  469.      */
  470.     enableSourceEdit : true,
  471.     /**
  472.      * @cfg {Boolean} enableLinks Enable the create link button. Not available in Safari. (defaults to true)
  473.      */
  474.     enableLinks : true,
  475.     /**
  476.      * @cfg {Boolean} enableFont Enable font selection. Not available in Safari. (defaults to true)
  477.      */
  478.     enableFont : true,
  479.     /**
  480.      * @cfg {String} createLinkText The default text for the create link prompt
  481.      */
  482.     createLinkText : 'Please enter the URL for the link:',
  483.     /**
  484.      * @cfg {String} defaultLinkValue The default value for the create link prompt (defaults to http:/ /)
  485.      */
  486.     defaultLinkValue : 'http:/'+'/',
  487.     /**
  488.      * @cfg {Array} fontFamilies An array of available font families
  489.      */
  490.     fontFamilies : [
  491.         'Arial',
  492.         'Courier New',
  493.         'Tahoma',
  494.         'Times New Roman',
  495.         'Verdana'
  496.     ],
  497.     defaultFont: 'tahoma',
  498.     /**
  499.      * @cfg {String} defaultValue A default value to be put into the editor to resolve focus issues (defaults to &#8203; (Zero-width space), &nbsp; (Non-breaking space) in Opera and IE6).
  500.      */
  501.     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&nbsp;' : '&#8203;',
  502.     // private properties
  503.     actionMode: 'wrap',
  504.     validationEvent : false,
  505.     deferHeight: true,
  506.     initialized : false,
  507.     activated : false,
  508.     sourceEditMode : false,
  509.     onFocus : Ext.emptyFn,
  510.     iframePad:3,
  511.     hideMode:'offsets',
  512.     defaultAutoCreate : {
  513.         tag: "textarea",
  514.         style:"width:500px;height:300px;",
  515.         autocomplete: "off"
  516.     },
  517.     // private
  518.     initComponent : function(){
  519.         this.addEvents(
  520.             /**
  521.              * @event initialize
  522.              * Fires when the editor is fully initialized (including the iframe)
  523.              * @param {HtmlEditor} this
  524.              */
  525.             'initialize',
  526.             /**
  527.              * @event activate
  528.              * Fires when the editor is first receives the focus. Any insertion must wait
  529.              * until after this event.
  530.              * @param {HtmlEditor} this
  531.              */
  532.             'activate',
  533.              /**
  534.              * @event beforesync
  535.              * Fires before the textarea is updated with content from the editor iframe. Return false
  536.              * to cancel the sync.
  537.              * @param {HtmlEditor} this
  538.              * @param {String} html
  539.              */
  540.             'beforesync',
  541.              /**
  542.              * @event beforepush
  543.              * Fires before the iframe editor is updated with content from the textarea. Return false
  544.              * to cancel the push.
  545.              * @param {HtmlEditor} this
  546.              * @param {String} html
  547.              */
  548.             'beforepush',
  549.              /**
  550.              * @event sync
  551.              * Fires when the textarea is updated with content from the editor iframe.
  552.              * @param {HtmlEditor} this
  553.              * @param {String} html
  554.              */
  555.             'sync',
  556.              /**