Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Base.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-form-field-Base'>/**
19 </span> * @docauthor Jason Johnston &lt;jason@sencha.com&gt;
20  *
21  * Base class for form fields that provides default event handling, rendering, and other common functionality
22  * needed by all form field types. Utilizes the {@link Ext.form.field.Field} mixin for value handling and validation,
23  * and the {@link Ext.form.Labelable} mixin to provide label and error message display.
24  *
25  * In most cases you will want to use a subclass, such as {@link Ext.form.field.Text} or {@link Ext.form.field.Checkbox},
26  * rather than creating instances of this class directly. However if you are implementing a custom form field,
27  * using this as the parent class is recommended.
28  *
29  * # Values and Conversions
30  *
31  * Because BaseField implements the Field mixin, it has a main value that can be initialized with the
32  * {@link #value} config and manipulated via the {@link #getValue} and {@link #setValue} methods. This main
33  * value can be one of many data types appropriate to the current field, for instance a {@link Ext.form.field.Date Date}
34  * field would use a JavaScript Date object as its value type. However, because the field is rendered as a HTML
35  * input, this value data type can not always be directly used in the rendered field.
36  *
37  * Therefore BaseField introduces the concept of a &quot;raw value&quot;. This is the value of the rendered HTML input field,
38  * and is normally a String. The {@link #getRawValue} and {@link #setRawValue} methods can be used to directly
39  * work with the raw value, though it is recommended to use getValue and setValue in most cases.
40  *
41  * Conversion back and forth between the main value and the raw value is handled by the {@link #valueToRaw} and
42  * {@link #rawToValue} methods. If you are implementing a subclass that uses a non-String value data type, you
43  * should override these methods to handle the conversion.
44  *
45  * # Rendering
46  *
47  * The content of the field body is defined by the {@link #fieldSubTpl} XTemplate, with its argument data
48  * created by the {@link #getSubTplData} method. Override this template and/or method to create custom
49  * field renderings.
50  *
51  * # Example usage:
52  *
53  *     @example
54  *     // A simple subclass of BaseField that creates a HTML5 search field. Redirects to the
55  *     // searchUrl when the Enter key is pressed.222
56  *     Ext.define('Ext.form.SearchField', {
57  *         extend: 'Ext.form.field.Base',
58  *         alias: 'widget.searchfield',
59  *     
60  *         inputType: 'search',
61  *     
62  *         // Config defining the search URL
63  *         searchUrl: 'http://www.google.com/search?q={0}',
64  *     
65  *         // Add specialkey listener
66  *         initComponent: function() {
67  *             this.callParent();
68  *             this.on('specialkey', this.checkEnterKey, this);
69  *         },
70  *     
71  *         // Handle enter key presses, execute the search if the field has a value
72  *         checkEnterKey: function(field, e) {
73  *             var value = this.getValue();
74  *             if (e.getKey() === e.ENTER &amp;&amp; !Ext.isEmpty(value)) {
75  *                 location.href = Ext.String.format(this.searchUrl, value);
76  *             }
77  *         }
78  *     });
79  *     
80  *     Ext.create('Ext.form.Panel', {
81  *         title: 'BaseField Example',
82  *         bodyPadding: 5,
83  *         width: 250,
84  *     
85  *         // Fields will be arranged vertically, stretched to full width
86  *         layout: 'anchor',
87  *         defaults: {
88  *             anchor: '100%'
89  *         },
90  *         items: [{
91  *             xtype: 'searchfield',
92  *             fieldLabel: 'Search',
93  *             name: 'query'
94  *         }],
95  *         renderTo: Ext.getBody()
96  *     });
97  */
98 Ext.define('Ext.form.field.Base', {
99     extend: 'Ext.Component',
100     mixins: {
101         labelable: 'Ext.form.Labelable',
102         field: 'Ext.form.field.Field'
103     },
104     alias: 'widget.field',
105     alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'],
106     requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
107
108 <span id='Ext-form-field-Base-cfg-fieldSubTpl'>    /**
109 </span>     * @cfg {Ext.XTemplate} fieldSubTpl
110      * The content of the field body is defined by this config option.
111      */
112     fieldSubTpl: [ // note: {id} here is really {inputId}, but {cmpId} is available
113         '&lt;input id=&quot;{id}&quot; type=&quot;{type}&quot; ',
114         '&lt;tpl if=&quot;name&quot;&gt;name=&quot;{name}&quot; &lt;/tpl&gt;',
115         '&lt;tpl if=&quot;size&quot;&gt;size=&quot;{size}&quot; &lt;/tpl&gt;',
116         '&lt;tpl if=&quot;tabIdx&quot;&gt;tabIndex=&quot;{tabIdx}&quot; &lt;/tpl&gt;',
117         'class=&quot;{fieldCls} {typeCls}&quot; autocomplete=&quot;off&quot; /&gt;',
118         {
119             compiled: true,
120             disableFormats: true
121         }
122     ],
123
124 <span id='Ext-form-field-Base-cfg-name'>    /**
125 </span>     * @cfg {String} name
126      * The name of the field. This is used as the parameter name when including the field value
127      * in a {@link Ext.form.Basic#submit form submit()}. If no name is configured, it falls back to the {@link #inputId}.
128      * To prevent the field from being included in the form submit, set {@link #submitValue} to false.
129      */
130
131 <span id='Ext-form-field-Base-cfg-inputType'>    /**
132 </span>     * @cfg {String} inputType
133      * The type attribute for input fields -- e.g. radio, text, password, file. The extended types
134      * supported by HTML5 inputs (url, email, etc.) may also be used, though using them will cause older browsers to
135      * fall back to 'text'.
136      *
137      * The type 'password' must be used to render that field type currently -- there is no separate Ext component for
138      * that. You can use {@link Ext.form.field.File} which creates a custom-rendered file upload field, but if you want
139      * a plain unstyled file input you can use a BaseField with inputType:'file'.
140      */
141     inputType: 'text',
142
143 <span id='Ext-form-field-Base-cfg-tabIndex'>    /**
144 </span>     * @cfg {Number} tabIndex
145      * The tabIndex for this field. Note this only applies to fields that are rendered, not those which are built via
146      * applyTo
147      */
148
149 <span id='Ext-form-field-Base-cfg-invalidText'>    /**
150 </span>     * @cfg {String} invalidText
151      * The error text to use when marking a field invalid and no message is provided
152      */
153     invalidText : 'The value in this field is invalid',
154
155 <span id='Ext-form-field-Base-cfg-fieldCls'>    /**
156 </span>     * @cfg {String} [fieldCls='x-form-field']
157      * The default CSS class for the field input
158      */
159     fieldCls : Ext.baseCSSPrefix + 'form-field',
160
161 <span id='Ext-form-field-Base-cfg-fieldStyle'>    /**
162 </span>     * @cfg {String} fieldStyle
163      * Optional CSS style(s) to be applied to the {@link #inputEl field input element}. Should be a valid argument to
164      * {@link Ext.Element#applyStyles}. Defaults to undefined. See also the {@link #setFieldStyle} method for changing
165      * the style after initialization.
166      */
167
168 <span id='Ext-form-field-Base-cfg-focusCls'>    /**
169 </span>     * @cfg {String} [focusCls='x-form-focus']
170      * The CSS class to use when the field receives focus
171      */
172     focusCls : Ext.baseCSSPrefix + 'form-focus',
173
174 <span id='Ext-form-field-Base-cfg-dirtyCls'>    /**
175 </span>     * @cfg {String} dirtyCls
176      * The CSS class to use when the field value {@link #isDirty is dirty}.
177      */
178     dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
179
180 <span id='Ext-form-field-Base-cfg-checkChangeEvents'>    /**
181 </span>     * @cfg {String[]} checkChangeEvents
182      * A list of event names that will be listened for on the field's {@link #inputEl input element}, which will cause
183      * the field's value to be checked for changes. If a change is detected, the {@link #change change event} will be
184      * fired, followed by validation if the {@link #validateOnChange} option is enabled.
185      *
186      * Defaults to ['change', 'propertychange'] in Internet Explorer, and ['change', 'input', 'textInput', 'keyup',
187      * 'dragdrop'] in other browsers. This catches all the ways that field values can be changed in most supported
188      * browsers; the only known exceptions at the time of writing are:
189      *
190      *   - Safari 3.2 and older: cut/paste in textareas via the context menu, and dragging text into textareas
191      *   - Opera 10 and 11: dragging text into text fields and textareas, and cut via the context menu in text fields
192      *     and textareas
193      *   - Opera 9: Same as Opera 10 and 11, plus paste from context menu in text fields and textareas
194      *
195      * If you need to guarantee on-the-fly change notifications including these edge cases, you can call the
196      * {@link #checkChange} method on a repeating interval, e.g. using {@link Ext.TaskManager}, or if the field is within
197      * a {@link Ext.form.Panel}, you can use the FormPanel's {@link Ext.form.Panel#pollForChanges} configuration to set up
198      * such a task automatically.
199      */
200     checkChangeEvents: Ext.isIE &amp;&amp; (!document.documentMode || document.documentMode &lt; 9) ?
201                         ['change', 'propertychange'] :
202                         ['change', 'input', 'textInput', 'keyup', 'dragdrop'],
203
204 <span id='Ext-form-field-Base-cfg-checkChangeBuffer'>    /**
205 </span>     * @cfg {Number} checkChangeBuffer
206      * Defines a timeout in milliseconds for buffering {@link #checkChangeEvents} that fire in rapid succession.
207      * Defaults to 50 milliseconds.
208      */
209     checkChangeBuffer: 50,
210
211     componentLayout: 'field',
212
213 <span id='Ext-form-field-Base-cfg-readOnly'>    /**
214 </span>     * @cfg {Boolean} readOnly
215      * true to mark the field as readOnly in HTML.
216      *
217      * **Note**: this only sets the element's readOnly DOM attribute. Setting `readOnly=true`, for example, will not
218      * disable triggering a ComboBox or Date; it gives you the option of forcing the user to choose via the trigger
219      * without typing in the text box. To hide the trigger use `{@link Ext.form.field.Trigger#hideTrigger hideTrigger}`.
220      */
221     readOnly : false,
222
223 <span id='Ext-form-field-Base-cfg-readOnlyCls'>    /**
224 </span>     * @cfg {String} readOnlyCls
225      * The CSS class applied to the component's main element when it is {@link #readOnly}.
226      */
227     readOnlyCls: Ext.baseCSSPrefix + 'form-readonly',
228
229 <span id='Ext-form-field-Base-cfg-inputId'>    /**
230 </span>     * @cfg {String} inputId
231      * The id that will be given to the generated input DOM element. Defaults to an automatically generated id. If you
232      * configure this manually, you must make sure it is unique in the document.
233      */
234
235 <span id='Ext-form-field-Base-cfg-validateOnBlur'>    /**
236 </span>     * @cfg {Boolean} validateOnBlur
237      * Whether the field should validate when it loses focus. This will cause fields to be validated
238      * as the user steps through the fields in the form regardless of whether they are making changes to those fields
239      * along the way. See also {@link #validateOnChange}.
240      */
241     validateOnBlur: true,
242
243     // private
244     hasFocus : false,
245
246     baseCls: Ext.baseCSSPrefix + 'field',
247
248     maskOnDisable: false,
249
250     // private
251     initComponent : function() {
252         var me = this;
253
254         me.callParent();
255
256         me.subTplData = me.subTplData || {};
257
258         me.addEvents(
259 <span id='Ext-form-field-Base-event-focus'>            /**
260 </span>             * @event focus
261              * Fires when this field receives input focus.
262              * @param {Ext.form.field.Base} this
263              */
264             'focus',
265 <span id='Ext-form-field-Base-event-blur'>            /**
266 </span>             * @event blur
267              * Fires when this field loses input focus.
268              * @param {Ext.form.field.Base} this
269              */
270             'blur',
271 <span id='Ext-form-field-Base-event-specialkey'>            /**
272 </span>             * @event specialkey
273              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. To handle other keys
274              * see {@link Ext.util.KeyMap}. You can check {@link Ext.EventObject#getKey} to determine which key was
275              * pressed. For example:
276              *
277              *     var form = new Ext.form.Panel({
278              *         ...
279              *         items: [{
280              *                 fieldLabel: 'Field 1',
281              *                 name: 'field1',
282              *                 allowBlank: false
283              *             },{
284              *                 fieldLabel: 'Field 2',
285              *                 name: 'field2',
286              *                 listeners: {
287              *                     specialkey: function(field, e){
288              *                         // e.HOME, e.END, e.PAGE_UP, e.PAGE_DOWN,
289              *                         // e.TAB, e.ESC, arrow keys: e.LEFT, e.RIGHT, e.UP, e.DOWN
290              *                         if (e.{@link Ext.EventObject#getKey getKey()} == e.ENTER) {
291              *                             var form = field.up('form').getForm();
292              *                             form.submit();
293              *                         }
294              *                     }
295              *                 }
296              *             }
297              *         ],
298              *         ...
299              *     });
300              *
301              * @param {Ext.form.field.Base} this
302              * @param {Ext.EventObject} e The event object
303              */
304             'specialkey'
305         );
306
307         // Init mixins
308         me.initLabelable();
309         me.initField();
310
311         // Default name to inputId
312         if (!me.name) {
313             me.name = me.getInputId();
314         }
315     },
316
317 <span id='Ext-form-field-Base-method-getInputId'>    /**
318 </span>     * Returns the input id for this field. If none was specified via the {@link #inputId} config, then an id will be
319      * automatically generated.
320      */
321     getInputId: function() {
322         return this.inputId || (this.inputId = Ext.id());
323     },
324
325 <span id='Ext-form-field-Base-method-getSubTplData'>    /**
326 </span>     * Creates and returns the data object to be used when rendering the {@link #fieldSubTpl}.
327      * @return {Object} The template data
328      * @template
329      */
330     getSubTplData: function() {
331         var me = this,
332             type = me.inputType,
333             inputId = me.getInputId();
334
335         return Ext.applyIf(me.subTplData, {
336             id: inputId,
337             cmpId: me.id,
338             name: me.name || inputId,
339             type: type,
340             size: me.size || 20,
341             cls: me.cls,
342             fieldCls: me.fieldCls,
343             tabIdx: me.tabIndex,
344             typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
345         });
346     },
347
348     afterRender: function() {
349         this.callParent();
350         
351         if (this.inputEl) {
352             this.inputEl.selectable();
353         }
354     },
355
356 <span id='Ext-form-field-Base-method-getSubTplMarkup'>    /**
357 </span>     * Gets the markup to be inserted into the outer template's bodyEl. For fields this is the actual input element.
358      */
359     getSubTplMarkup: function() {
360         return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
361     },
362
363     initRenderTpl: function() {
364         var me = this;
365         if (!me.hasOwnProperty('renderTpl')) {
366             me.renderTpl = me.getTpl('labelableRenderTpl');
367         }
368         return me.callParent();
369     },
370
371     initRenderData: function() {
372         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
373     },
374
375 <span id='Ext-form-field-Base-method-setFieldStyle'>    /**
376 </span>     * Set the {@link #fieldStyle CSS style} of the {@link #inputEl field input element}.
377      * @param {String/Object/Function} style The style(s) to apply. Should be a valid argument to {@link
378      * Ext.Element#applyStyles}.
379      */
380     setFieldStyle: function(style) {
381         var me = this,
382             inputEl = me.inputEl;
383         if (inputEl) {
384             inputEl.applyStyles(style);
385         }
386         me.fieldStyle = style;
387     },
388
389     // private
390     onRender : function() {
391         var me = this,
392             fieldStyle = me.fieldStyle;
393
394         me.onLabelableRender();
395
396 <span id='Ext-form-field-Base-property-inputEl'>        /**
397 </span>         * @property {Ext.Element} inputEl
398          * The input Element for this Field. Only available after the field has been rendered.
399          */
400         me.addChildEls({ name: 'inputEl', id: me.getInputId() });
401
402         me.callParent(arguments);
403
404         // Make the stored rawValue get set as the input element's value
405         me.setRawValue(me.rawValue);
406
407         if (me.readOnly) {
408             me.setReadOnly(true);
409         }
410         if (me.disabled) {
411             me.disable();
412         }
413         if (fieldStyle) {
414             me.setFieldStyle(fieldStyle);
415         }
416
417         me.renderActiveError();
418     },
419
420     initAria: function() {
421         var me = this;
422         me.callParent();
423
424         // Associate the field to the error message element
425         me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
426     },
427
428     getFocusEl: function() {
429         return this.inputEl;
430     },
431
432     isFileUpload: function() {
433         return this.inputType === 'file';
434     },
435
436     extractFileInput: function() {
437         var me = this,
438             fileInput = me.isFileUpload() ? me.inputEl.dom : null,
439             clone;
440         if (fileInput) {
441             clone = fileInput.cloneNode(true);
442             fileInput.parentNode.replaceChild(clone, fileInput);
443             me.inputEl = Ext.get(clone);
444         }
445         return fileInput;
446     },
447
448     // private override to use getSubmitValue() as a convenience
449     getSubmitData: function() {
450         var me = this,
451             data = null,
452             val;
453         if (!me.disabled &amp;&amp; me.submitValue &amp;&amp; !me.isFileUpload()) {
454             val = me.getSubmitValue();
455             if (val !== null) {
456                 data = {};
457                 data[me.getName()] = val;
458             }
459         }
460         return data;
461     },
462
463 <span id='Ext-form-field-Base-method-getSubmitValue'>    /**
464 </span>     * Returns the value that would be included in a standard form submit for this field. This will be combined with the
465      * field's name to form a name=value pair in the {@link #getSubmitData submitted parameters}. If an empty string is
466      * returned then just the name= will be submitted; if null is returned then nothing will be submitted.
467      *
468      * Note that the value returned will have been {@link #processRawValue processed} but may or may not have been
469      * successfully {@link #validate validated}.
470      *
471      * @return {String} The value to be submitted, or null.
472      */
473     getSubmitValue: function() {
474         return this.processRawValue(this.getRawValue());
475     },
476
477 <span id='Ext-form-field-Base-method-getRawValue'>    /**
478 </span>     * Returns the raw value of the field, without performing any normalization, conversion, or validation. To get a
479      * normalized and converted value see {@link #getValue}.
480      * @return {String} value The raw String value of the field
481      */
482     getRawValue: function() {
483         var me = this,
484             v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, ''));
485         me.rawValue = v;
486         return v;
487     },
488
489 <span id='Ext-form-field-Base-method-setRawValue'>    /**
490 </span>     * Sets the field's raw value directly, bypassing {@link #valueToRaw value conversion}, change detection, and
491      * validation. To set the value with these additional inspections see {@link #setValue}.
492      * @param {Object} value The value to set
493      * @return {Object} value The field value that is set
494      */
495     setRawValue: function(value) {
496         var me = this;
497         value = Ext.value(value, '');
498         me.rawValue = value;
499
500         // Some Field subclasses may not render an inputEl
501         if (me.inputEl) {
502             me.inputEl.dom.value = value;
503         }
504         return value;
505     },
506
507 <span id='Ext-form-field-Base-method-valueToRaw'>    /**
508 </span>     * Converts a mixed-type value to a raw representation suitable for displaying in the field. This allows controlling
509      * how value objects passed to {@link #setValue} are shown to the user, including localization. For instance, for a
510      * {@link Ext.form.field.Date}, this would control how a Date object passed to {@link #setValue} would be converted
511      * to a String for display in the field.
512      *
513      * See {@link #rawToValue} for the opposite conversion.
514      *
515      * The base implementation simply does a standard toString conversion, and converts {@link Ext#isEmpty empty values}
516      * to an empty string.
517      *
518      * @param {Object} value The mixed-type value to convert to the raw representation.
519      * @return {Object} The converted raw value.
520      */
521     valueToRaw: function(value) {
522         return '' + Ext.value(value, '');
523     },
524
525 <span id='Ext-form-field-Base-method-rawToValue'>    /**
526 </span>     * Converts a raw input field value into a mixed-type value that is suitable for this particular field type. This
527      * allows controlling the normalization and conversion of user-entered values into field-type-appropriate values,
528      * e.g. a Date object for {@link Ext.form.field.Date}, and is invoked by {@link #getValue}.
529      *
530      * It is up to individual implementations to decide how to handle raw values that cannot be successfully converted
531      * to the desired object type.
532      *
533      * See {@link #valueToRaw} for the opposite conversion.
534      *
535      * The base implementation does no conversion, returning the raw value untouched.
536      *
537      * @param {Object} rawValue
538      * @return {Object} The converted value.
539      */
540     rawToValue: function(rawValue) {
541         return rawValue;
542     },
543
544 <span id='Ext-form-field-Base-method-processRawValue'>    /**
545 </span>     * Performs any necessary manipulation of a raw field value to prepare it for {@link #rawToValue conversion} and/or
546      * {@link #validate validation}, for instance stripping out ignored characters. In the base implementation it does
547      * nothing; individual subclasses may override this as needed.
548      *
549      * @param {Object} value The unprocessed string value
550      * @return {Object} The processed string value
551      */
552     processRawValue: function(value) {
553         return value;
554     },
555
556 <span id='Ext-form-field-Base-method-getValue'>    /**
557 </span>     * Returns the current data value of the field. The type of value returned is particular to the type of the
558      * particular field (e.g. a Date object for {@link Ext.form.field.Date}), as the result of calling {@link #rawToValue} on
559      * the field's {@link #processRawValue processed} String value. To return the raw String value, see {@link #getRawValue}.
560      * @return {Object} value The field value
561      */
562     getValue: function() {
563         var me = this,
564             val = me.rawToValue(me.processRawValue(me.getRawValue()));
565         me.value = val;
566         return val;
567     },
568
569 <span id='Ext-form-field-Base-method-setValue'>    /**
570 </span>     * Sets a data value into the field and runs the change detection and validation. To set the value directly
571      * without these inspections see {@link #setRawValue}.
572      * @param {Object} value The value to set
573      * @return {Ext.form.field.Field} this
574      */
575     setValue: function(value) {
576         var me = this;
577         me.setRawValue(me.valueToRaw(value));
578         return me.mixins.field.setValue.call(me, value);
579     },
580
581
582     //private
583     onDisable: function() {
584         var me = this,
585             inputEl = me.inputEl;
586         me.callParent();
587         if (inputEl) {
588             inputEl.dom.disabled = true;
589         }
590     },
591
592     //private
593     onEnable: function() {
594         var me = this,
595             inputEl = me.inputEl;
596         me.callParent();
597         if (inputEl) {
598             inputEl.dom.disabled = false;
599         }
600     },
601
602 <span id='Ext-form-field-Base-method-setReadOnly'>    /**
603 </span>     * Sets the read only state of this field.
604      * @param {Boolean} readOnly Whether the field should be read only.
605      */
606     setReadOnly: function(readOnly) {
607         var me = this,
608             inputEl = me.inputEl;
609         if (inputEl) {
610             inputEl.dom.readOnly = readOnly;
611             inputEl.dom.setAttribute('aria-readonly', readOnly);
612         }
613         me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
614         me.readOnly = readOnly;
615     },
616
617     // private
618     fireKey: function(e){
619         if(e.isSpecialKey()){
620             this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
621         }
622     },
623
624     // private
625     initEvents : function(){
626         var me = this,
627             inputEl = me.inputEl,
628             onChangeTask,
629             onChangeEvent;
630         if (inputEl) {
631             me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey,  me);
632             me.mon(inputEl, 'focus', me.onFocus, me);
633
634             // standardise buffer across all browsers + OS-es for consistent event order.
635             // (the 10ms buffer for Editors fixes a weird FF/Win editor issue when changing OS window focus)
636             me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
637
638             // listen for immediate value changes
639             onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
640             me.onChangeEvent = onChangeEvent = function() {
641                 onChangeTask.delay(me.checkChangeBuffer);
642             };
643             Ext.each(me.checkChangeEvents, function(eventName) {
644                 if (eventName === 'propertychange') {
645                     me.usesPropertychange = true;
646                 }
647                 me.mon(inputEl, eventName, onChangeEvent);
648             }, me);
649         }
650         me.callParent();
651     },
652
653     doComponentLayout: function() {
654         var me = this,
655             inputEl = me.inputEl,
656             usesPropertychange = me.usesPropertychange,
657             ename = 'propertychange',
658             onChangeEvent = me.onChangeEvent;
659
660         // In IE if propertychange is one of the checkChangeEvents, we need to remove
661         // the listener prior to layout and re-add it after, to prevent it from firing
662         // needlessly for attribute and style changes applied to the inputEl.
663         if (usesPropertychange) {
664             me.mun(inputEl, ename, onChangeEvent);
665         }
666         me.callParent(arguments);
667         if (usesPropertychange) {
668             me.mon(inputEl, ename, onChangeEvent);
669         }
670     },
671
672     // private
673     preFocus: Ext.emptyFn,
674
675     // private
676     onFocus: function() {
677         var me = this,
678             focusCls = me.focusCls,
679             inputEl = me.inputEl;
680         me.preFocus();
681         if (focusCls &amp;&amp; inputEl) {
682             inputEl.addCls(focusCls);
683         }
684         if (!me.hasFocus) {
685             me.hasFocus = true;
686             me.componentLayout.onFocus();
687             me.fireEvent('focus', me);
688         }
689     },
690
691     // private
692     beforeBlur : Ext.emptyFn,
693
694     // private
695     onBlur : function(){
696         var me = this,
697             focusCls = me.focusCls,
698             inputEl = me.inputEl;
699
700         if (me.destroying) {
701             return;
702         }
703
704         me.beforeBlur();
705         if (focusCls &amp;&amp; inputEl) {
706             inputEl.removeCls(focusCls);
707         }
708         if (me.validateOnBlur) {
709             me.validate();
710         }
711         me.hasFocus = false;
712         me.fireEvent('blur', me);
713         me.postBlur();
714     },
715
716     // private
717     postBlur : Ext.emptyFn,
718
719
720 <span id='Ext-form-field-Base-method-onDirtyChange'>    /**
721 </span>     * @private Called when the field's dirty state changes. Adds/removes the {@link #dirtyCls} on the main element.
722      * @param {Boolean} isDirty
723      */
724     onDirtyChange: function(isDirty) {
725         this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
726     },
727
728
729 <span id='Ext-form-field-Base-method-isValid'>    /**
730 </span>     * Returns whether or not the field value is currently valid by {@link #getErrors validating} the
731      * {@link #processRawValue processed raw value} of the field. **Note**: {@link #disabled} fields are
732      * always treated as valid.
733      *
734      * @return {Boolean} True if the value is valid, else false
735      */
736     isValid : function() {
737         var me = this;
738         return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
739     },
740
741
742 <span id='Ext-form-field-Base-method-validateValue'>    /**
743 </span>     * Uses {@link #getErrors} to build an array of validation errors. If any errors are found, they are passed to
744      * {@link #markInvalid} and false is returned, otherwise true is returned.
745      *
746      * Previously, subclasses were invited to provide an implementation of this to process validations - from 3.2
747      * onwards {@link #getErrors} should be overridden instead.
748      *
749      * @param {Object} value The value to validate
750      * @return {Boolean} True if all validations passed, false if one or more failed
751      */
752     validateValue: function(value) {
753         var me = this,
754             errors = me.getErrors(value),
755             isValid = Ext.isEmpty(errors);
756         if (!me.preventMark) {
757             if (isValid) {
758                 me.clearInvalid();
759             } else {
760                 me.markInvalid(errors);
761             }
762         }
763
764         return isValid;
765     },
766
767 <span id='Ext-form-field-Base-method-markInvalid'>    /**
768 </span>     * Display one or more error messages associated with this field, using {@link #msgTarget} to determine how to
769      * display the messages and applying {@link #invalidCls} to the field's UI element.
770      *
771      * **Note**: this method does not cause the Field's {@link #validate} or {@link #isValid} methods to return `false`
772      * if the value does _pass_ validation. So simply marking a Field as invalid will not prevent submission of forms
773      * submitted with the {@link Ext.form.action.Submit#clientValidation} option set.
774      *
775      * @param {String/String[]} errors The validation message(s) to display.
776      */
777     markInvalid : function(errors) {
778         // Save the message and fire the 'invalid' event
779         var me = this,
780             oldMsg = me.getActiveError();
781         me.setActiveErrors(Ext.Array.from(errors));
782         if (oldMsg !== me.getActiveError()) {
783             me.doComponentLayout();
784         }
785     },
786
787 <span id='Ext-form-field-Base-method-clearInvalid'>    /**
788 </span>     * Clear any invalid styles/messages for this field.
789      *
790      * **Note**: this method does not cause the Field's {@link #validate} or {@link #isValid} methods to return `true`
791      * if the value does not _pass_ validation. So simply clearing a field's errors will not necessarily allow
792      * submission of forms submitted with the {@link Ext.form.action.Submit#clientValidation} option set.
793      */
794     clearInvalid : function() {
795         // Clear the message and fire the 'valid' event
796         var me = this,
797             hadError = me.hasActiveError();
798         me.unsetActiveError();
799         if (hadError) {
800             me.doComponentLayout();
801         }
802     },
803
804 <span id='Ext-form-field-Base-method-renderActiveError'>    /**
805 </span>     * @private Overrides the method from the Ext.form.Labelable mixin to also add the invalidCls to the inputEl,
806      * as that is required for proper styling in IE with nested fields (due to lack of child selector)
807      */
808     renderActiveError: function() {
809         var me = this,
810             hasError = me.hasActiveError();
811         if (me.inputEl) {
812             // Add/remove invalid class
813             me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field');
814         }
815         me.mixins.labelable.renderActiveError.call(me);
816     },
817
818
819     getActionEl: function() {
820         return this.inputEl || this.el;
821     }
822
823 });
824 </pre>
825 </body>
826 </html>