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