Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / form / field / TextArea.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @docauthor Robert Dougan <rob@sencha.com>
17  *
18  * This class creates a multiline text field, which can be used as a direct replacement for traditional
19  * textarea fields. In addition, it supports automatically {@link #grow growing} the height of the textarea to
20  * fit its content.
21  *
22  * All of the configuration options from {@link Ext.form.field.Text} can be used on TextArea.
23  *
24  * Example usage:
25  *
26  *     @example
27  *     Ext.create('Ext.form.FormPanel', {
28  *         title      : 'Sample TextArea',
29  *         width      : 400,
30  *         bodyPadding: 10,
31  *         renderTo   : Ext.getBody(),
32  *         items: [{
33  *             xtype     : 'textareafield',
34  *             grow      : true,
35  *             name      : 'message',
36  *             fieldLabel: 'Message',
37  *             anchor    : '100%'
38  *         }]
39  *     });
40  *
41  * Some other useful configuration options when using {@link #grow} are {@link #growMin} and {@link #growMax}.
42  * These allow you to set the minimum and maximum grow heights for the textarea.
43  */
44 Ext.define('Ext.form.field.TextArea', {
45     extend:'Ext.form.field.Text',
46     alias: ['widget.textareafield', 'widget.textarea'],
47     alternateClassName: 'Ext.form.TextArea',
48     requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
49
50     fieldSubTpl: [
51         '<textarea id="{id}" ',
52             '<tpl if="name">name="{name}" </tpl>',
53             '<tpl if="rows">rows="{rows}" </tpl>',
54             '<tpl if="cols">cols="{cols}" </tpl>',
55             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
56             'class="{fieldCls} {typeCls}" ',
57             'autocomplete="off">',
58         '</textarea>',
59         {
60             compiled: true,
61             disableFormats: true
62         }
63     ],
64
65     /**
66      * @cfg {Number} growMin
67      * The minimum height to allow when {@link #grow}=true
68      */
69     growMin: 60,
70
71     /**
72      * @cfg {Number} growMax
73      * The maximum height to allow when {@link #grow}=true
74      */
75     growMax: 1000,
76
77     /**
78      * @cfg {String} growAppend
79      * A string that will be appended to the field's current value for the purposes of calculating the target field
80      * size. Only used when the {@link #grow} config is true. Defaults to a newline for TextArea to ensure there is
81      * always a space below the current line.
82      */
83     growAppend: '\n-',
84
85     /**
86      * @cfg {Number} cols
87      * An initial value for the 'cols' attribute on the textarea element. This is only used if the component has no
88      * configured {@link #width} and is not given a width by its container's layout.
89      */
90     cols: 20,
91
92     /**
93      * @cfg {Number} cols
94      * An initial value for the 'cols' attribute on the textarea element. This is only used if the component has no
95      * configured {@link #width} and is not given a width by its container's layout.
96      */
97     rows: 4,
98
99     /**
100      * @cfg {Boolean} enterIsSpecial
101      * True if you want the enter key to be classed as a special key. Special keys are generally navigation keys
102      * (arrows, space, enter). Setting the config property to true would mean that you could not insert returns into the
103      * textarea.
104      */
105     enterIsSpecial: false,
106
107     /**
108      * @cfg {Boolean} preventScrollbars
109      * true to prevent scrollbars from appearing regardless of how much text is in the field. This option is only
110      * relevant when {@link #grow} is true. Equivalent to setting overflow: hidden.
111      */
112     preventScrollbars: false,
113
114     // private
115     componentLayout: 'textareafield',
116
117     // private
118     onRender: function(ct, position) {
119         var me = this;
120         Ext.applyIf(me.subTplData, {
121             cols: me.cols,
122             rows: me.rows
123         });
124
125         me.callParent(arguments);
126     },
127
128     // private
129     afterRender: function(){
130         var me = this;
131
132         me.callParent(arguments);
133
134         if (me.grow) {
135             if (me.preventScrollbars) {
136                 me.inputEl.setStyle('overflow', 'hidden');
137             }
138             me.inputEl.setHeight(me.growMin);
139         }
140     },
141
142     // private
143     fireKey: function(e) {
144         if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
145             this.fireEvent('specialkey', this, e);
146         }
147     },
148
149     /**
150      * Automatically grows the field to accomodate the height of the text up to the maximum field height allowed. This
151      * only takes effect if {@link #grow} = true, and fires the {@link #autosize} event if the height changes.
152      */
153     autoSize: function() {
154         var me = this,
155             height;
156
157         if (me.grow && me.rendered) {
158             me.doComponentLayout();
159             height = me.inputEl.getHeight();
160             if (height !== me.lastInputHeight) {
161                 me.fireEvent('autosize', height);
162                 me.lastInputHeight = height;
163             }
164         }
165     },
166
167     // private
168     initAria: function() {
169         this.callParent(arguments);
170         this.getActionEl().dom.setAttribute('aria-multiline', true);
171     },
172
173     /**
174      * To get the natural width of the textarea element, we do a simple calculation based on the 'cols' config.
175      * We use hard-coded numbers to approximate what browsers do natively, to avoid having to read any styles which
176      * would hurt performance. Overrides Labelable method.
177      * @protected
178      */
179     getBodyNaturalWidth: function() {
180         return Math.round(this.cols * 6.5) + 20;
181     }
182
183 });
184
185