]> git.proxmox.com Git - extjs.git/blame - extjs/modern/modern/src/field/Text.js
add extjs 6.0.1 sources
[extjs.git] / extjs / modern / modern / src / field / Text.js
CommitLineData
6527f429
DM
1/**\r
2 * The text field is the basis for most of the input fields. It provides a baseline of shared\r
3 * functionality such as input validation, standard events, state management and look and feel. Typically we create\r
4 * text fields inside a form, like this:\r
5 *\r
6 * @example\r
7 * Ext.create('Ext.form.Panel', {\r
8 * fullscreen: true,\r
9 * items: [\r
10 * {\r
11 * xtype: 'fieldset',\r
12 * title: 'Enter your name',\r
13 * items: [\r
14 * {\r
15 * xtype: 'textfield',\r
16 * label: 'First Name',\r
17 * name: 'firstName'\r
18 * },\r
19 * {\r
20 * xtype: 'textfield',\r
21 * label: 'Last Name',\r
22 * name: 'lastName'\r
23 * }\r
24 * ]\r
25 * }\r
26 * ]\r
27 * });\r
28 *\r
29 * This creates two text fields inside a form. Text Fields can also be created outside of a Form, like this:\r
30 *\r
31 * Ext.create('Ext.field.Text', {\r
32 * label: 'Your Name',\r
33 * value: 'Ed Spencer'\r
34 * });\r
35 *\r
36 * ## Configuring\r
37 *\r
38 * Text field offers several configuration options, including {@link #placeHolder}, {@link #maxLength},\r
39 * {@link #autoComplete}, {@link #autoCapitalize} and {@link #autoCorrect}. For example, here is how we would configure\r
40 * a text field to have a maximum length of 10 characters, with placeholder text that disappears when the field is\r
41 * focused:\r
42 *\r
43 * Ext.create('Ext.field.Text', {\r
44 * label: 'Username',\r
45 * maxLength: 10,\r
46 * placeHolder: 'Enter your username'\r
47 * });\r
48 *\r
49 * The autoComplete, autoCapitalize and autoCorrect configs simply set those attributes on the text field and allow the\r
50 * native browser to provide those capabilities. For example, to enable auto complete and auto correct, simply\r
51 * configure your text field like this:\r
52 *\r
53 * Ext.create('Ext.field.Text', {\r
54 * label: 'Username',\r
55 * autoComplete: true,\r
56 * autoCorrect: true\r
57 * });\r
58 *\r
59 * These configurations will be picked up by the native browser, which will enable the options at the OS level.\r
60 *\r
61 * Text field inherits from {@link Ext.field.Field}, which is the base class for all fields and provides\r
62 * a lot of shared functionality for all fields, including setting values, clearing and basic validation. See the\r
63 * {@link Ext.field.Field} documentation to see how to leverage its capabilities.\r
64 */\r
65Ext.define('Ext.field.Text', {\r
66 extend: 'Ext.field.Field',\r
67 xtype: 'textfield',\r
68 alternateClassName: 'Ext.form.Text',\r
69\r
70 /**\r
71 * @event focus\r
72 * Fires when this field receives input focus\r
73 * @param {Ext.field.Text} this This field\r
74 * @param {Ext.event.Event} e\r
75 */\r
76\r
77 /**\r
78 * @event blur\r
79 * Fires when this field loses input focus\r
80 * @param {Ext.field.Text} this This field\r
81 * @param {Ext.event.Event} e\r
82 */\r
83\r
84 /**\r
85 * @event paste\r
86 * Fires when this field is pasted.\r
87 * @param {Ext.field.Text} this This field\r
88 * @param {Ext.event.Event} e\r
89 */\r
90\r
91 /**\r
92 * @event mousedown\r
93 * Fires when this field receives a mousedown\r
94 * @param {Ext.field.Text} this This field\r
95 * @param {Ext.event.Event} e\r
96 */\r
97\r
98 /**\r
99 * @event keyup\r
100 * @preventable\r
101 * Fires when a key is released on the input element\r
102 * @param {Ext.field.Text} this This field\r
103 * @param {Ext.event.Event} e\r
104 */\r
105\r
106 /**\r
107 * @event clearicontap\r
108 * @preventable\r
109 * Fires when the clear icon is tapped\r
110 * @param {Ext.field.Text} this This field\r
111 * @param {Ext.field.Input} input The field's input component.\r
112 * @param {Ext.event.Event} e\r
113 */\r
114\r
115 /**\r
116 * @event change\r
117 * Fires when the value has changed.\r
118 * @param {Ext.field.Text} this This field\r
119 * @param {String} newValue The new value\r
120 * @param {String} oldValue The original value\r
121 */\r
122\r
123 /**\r
124 * @event action\r
125 * @preventable\r
126 * Fires whenever the return key or go is pressed. FormPanel listeners\r
127 * for this event, and submits itself whenever it fires. Also note\r
128 * that this event bubbles up to parent containers.\r
129 * @param {Ext.field.Text} this This field\r
130 * @param {Mixed} e The key event object\r
131 */\r
132\r
133 config: {\r
134 /**\r
135 * @cfg\r
136 * @inheritdoc\r
137 */\r
138 ui: 'text',\r
139\r
140 /**\r
141 * @cfg\r
142 * @inheritdoc\r
143 */\r
144 clearIcon: true,\r
145\r
146 /**\r
147 * @cfg {String} placeHolder A string value displayed in the input (if supported) when the control is empty.\r
148 * @accessor\r
149 */\r
150 placeHolder: null,\r
151\r
152 /**\r
153 * @cfg {Number} maxLength The maximum number of permitted input characters.\r
154 * @accessor\r
155 */\r
156 maxLength: null,\r
157\r
158 /**\r
159 * True to set the field's DOM element autocomplete attribute to "on", false to set to "off".\r
160 * @cfg {Boolean} autoComplete\r
161 * @accessor\r
162 */\r
163 autoComplete: null,\r
164\r
165 /**\r
166 * True to set the field's DOM element autocapitalize attribute to "on", false to set to "off".\r
167 * @cfg {Boolean} autoCapitalize\r
168 * @accessor\r
169 */\r
170 autoCapitalize: null,\r
171\r
172 /**\r
173 * True to set the field DOM element autocorrect attribute to "on", false to set to "off".\r
174 * @cfg {Boolean} autoCorrect\r
175 * @accessor\r
176 */\r
177 autoCorrect: null,\r
178\r
179 /**\r
180 * True to set the field DOM element readonly attribute to true.\r
181 * @cfg {Boolean} readOnly\r
182 * @accessor\r
183 */\r
184 readOnly: null,\r
185\r
186 /**\r
187 * @cfg {Object} component The inner component for this field, which defaults to an input text.\r
188 * @accessor\r
189 */\r
190 component: {\r
191 xtype: 'input',\r
192 type: 'text',\r
193 fastFocus: false\r
194 },\r
195\r
196 bubbleEvents: ['action']\r
197 },\r
198\r
199 defaultBindProperty: 'value',\r
200 twoWayBindable: {\r
201 value: 1\r
202 },\r
203 \r
204 publishes: {\r
205 value: 1\r
206 },\r
207\r
208 focusedCls: Ext.baseCSSPrefix + 'field-focused',\r
209 clearableCls: Ext.baseCSSPrefix + 'field-clearable',\r
210 emptyCls: Ext.baseCSSPrefix + 'empty',\r
211\r
212 /**\r
213 * @private\r
214 */\r
215 initialize: function() {\r
216 var me = this;\r
217\r
218 me.callParent();\r
219\r
220 me.getComponent().on({\r
221 scope: this,\r
222\r
223 keyup : 'onKeyUp',\r
224 input : 'onInput',\r
225 focus : 'onFocus',\r
226 blur : 'onBlur',\r
227 paste : 'onPaste',\r
228 mousedown : 'onMouseDown',\r
229 clearicontap: 'onClearIconTap'\r
230 });\r
231\r
232 // set the originalValue of the textfield, if one exists\r
233 me.originalValue = me.getValue() || "";\r
234 me.getComponent().originalValue = me.originalValue;\r
235\r
236 me.syncEmptyCls();\r
237 },\r
238\r
239 syncEmptyCls: function() {\r
240 var val = this._value,\r
241 empty = val ? val.length : false;\r
242\r
243 this.toggleCls(this.emptyCls, !empty);\r
244 },\r
245\r
246 applyValue: function(value) {\r
247 return Ext.isEmpty(value) ? '' : value;\r
248 },\r
249\r
250 /**\r
251 * @private\r
252 */\r
253 updateValue: function(value, oldValue) {\r
254 var me = this,\r
255 component = me.getComponent(),\r
256 // allows value to be zero but not undefined or null (other falsey values)\r
257 valueValid = value !== undefined && value !== null && value !== '';\r
258\r
259 if (component) {\r
260 component.setValue(value);\r
261 }\r
262\r
263 me.toggleClearIcon(valueValid && me.isDirty())\r
264\r
265 me.syncEmptyCls();\r
266\r
267 if (me.initialized) {\r
268 me.fireEvent('change', me, value, oldValue);\r
269 }\r
270 },\r
271\r
272 /**\r
273 * @private\r
274 */\r
275 updatePlaceHolder: function(newPlaceHolder) {\r
276 this.getComponent().setPlaceHolder(newPlaceHolder);\r
277 },\r
278\r
279 /**\r
280 * @private\r
281 */\r
282 updateMaxLength: function(newMaxLength) {\r
283 this.getComponent().setMaxLength(newMaxLength);\r
284 },\r
285\r
286 /**\r
287 * @private\r
288 */\r
289 updateAutoComplete: function(newAutoComplete) {\r
290 this.getComponent().setAutoComplete(newAutoComplete);\r
291 },\r
292\r
293 /**\r
294 * @private\r
295 */\r
296 updateAutoCapitalize: function(newAutoCapitalize) {\r
297 this.getComponent().setAutoCapitalize(newAutoCapitalize);\r
298 },\r
299\r
300 /**\r
301 * @private\r
302 */\r
303 updateAutoCorrect: function(newAutoCorrect) {\r
304 this.getComponent().setAutoCorrect(newAutoCorrect);\r
305 },\r
306\r
307 /**\r
308 * @private\r
309 */\r
310 updateReadOnly: function(newReadOnly) {\r
311 this.toggleClearIcon(!newReadOnly);\r
312 this.getComponent().setReadOnly(newReadOnly);\r
313 },\r
314\r
315 /**\r
316 * @private\r
317 */\r
318 updateInputType: function(newInputType) {\r
319 var component = this.getComponent();\r
320 if (component) {\r
321 component.setType(newInputType);\r
322 }\r
323 },\r
324\r
325 /**\r
326 * @private\r
327 */\r
328 updateName: function(newName) {\r
329 var component = this.getComponent();\r
330 if (component) {\r
331 component.setName(newName);\r
332 }\r
333 },\r
334\r
335 /**\r
336 * @private\r
337 */\r
338 updateTabIndex: function(newTabIndex) {\r
339 var component = this.getComponent();\r
340 if (component) {\r
341 component.setTabIndex(newTabIndex);\r
342 }\r
343 },\r
344\r
345 /**\r
346 * Updates the {@link #inputCls} configuration on this fields {@link #component}\r
347 * @private\r
348 */\r
349 updateInputCls: function(newInputCls, oldInputCls) {\r
350 var component = this.getComponent();\r
351 if (component) {\r
352 component.replaceCls(oldInputCls, newInputCls);\r
353 }\r
354 },\r
355\r
356 updateDisabled: function(disabled, oldDisabled) {\r
357 this.callParent([disabled, oldDisabled]);\r
358\r
359 var component = this.getComponent();\r
360 if (component) {\r
361 component.setDisabled(disabled);\r
362 }\r
363\r
364 this.toggleClearIcon(!disabled);\r
365 },\r
366\r
367 /**\r
368 * @private\r
369 */\r
370 showClearIcon: function() {\r
371 var me = this,\r
372 value = me.getValue(),\r
373 // allows value to be zero but not undefined or null (other falsey values)\r
374 valueValid = value !== undefined && value !== null && value !== "";\r
375\r
376 if (me.getClearIcon() && !me.getDisabled() && !me.getReadOnly() && valueValid) {\r
377 me.element.addCls(me.clearableCls);\r
378 }\r
379\r
380 return me;\r
381 },\r
382\r
383 /**\r
384 * @private\r
385 */\r
386 hideClearIcon: function() {\r
387 if (this.getClearIcon()) {\r
388 this.element.removeCls(this.clearableCls);\r
389 }\r
390 },\r
391\r
392 onKeyUp: function(e) {\r
393 this.fireAction('keyup', [this, e], 'doKeyUp');\r
394 },\r
395\r
396 /**\r
397 * Called when a key has been pressed in the `<input>`\r
398 * @private\r
399 */\r
400 doKeyUp: function(me, e) {\r
401 // getValue to ensure that we are in sync with the dom\r
402 var value = me.getValue(),\r
403 // allows value to be zero but not undefined or null (other falsey values)\r
404 valueValid = value !== undefined && value !== null && value !== '';\r
405\r
406 me.toggleClearIcon(valueValid);\r
407\r
408 if (e.browserEvent.keyCode === 13) {\r
409 me.fireAction('action', [me, e], 'doAction');\r
410 }\r
411 },\r
412\r
413 doAction: function() {\r
414 this.blur();\r
415 },\r
416\r
417 onClearIconTap: function(input, e) {\r
418 this.fireAction('clearicontap', [this, input, e], 'doClearIconTap');\r
419 },\r
420\r
421 /**\r
422 * @private\r
423 */\r
424 doClearIconTap: function(me, e) {\r
425 me.setValue('');\r
426 },\r
427\r
428 onInput: function(component, value) {\r
429 this.setValue(value);\r
430 },\r
431\r
432 onFocus: function(e) {\r
433 var me = this;\r
434\r
435 me.addCls(me.focusedCls);\r
436 me.isFocused = true;\r
437 me.fireEvent('focus', me, e);\r
438 },\r
439\r
440 onBlur: function(e) {\r
441 var me = this;\r
442\r
443 me.removeCls(me.focusedCls);\r
444 me.isFocused = false;\r
445\r
446 me.fireEvent('blur', me, e);\r
447\r
448 Ext.defer(function() {\r
449 me.isFocused = false;\r
450 }, 50);\r
451 },\r
452\r
453 onPaste: function(e) {\r
454 this.fireEvent('paste', this, e);\r
455 },\r
456\r
457 onMouseDown: function(e) {\r
458 this.fireEvent('mousedown', this, e);\r
459 },\r
460\r
461 /**\r
462 * Attempts to set the field as the active input focus.\r
463 * @return {Ext.field.Text} This field\r
464 */\r
465 focus: function() {\r
466 this.getComponent().focus();\r
467 return this;\r
468 },\r
469\r
470 /**\r
471 * Attempts to forcefully blur input focus for the field.\r
472 * @return {Ext.field.Text} This field\r
473 */\r
474 blur: function() {\r
475 this.getComponent().blur();\r
476 return this;\r
477 },\r
478\r
479 /**\r
480 * Attempts to forcefully select all the contents of the input field.\r
481 * @return {Ext.field.Text} this\r
482 */\r
483 select: function() {\r
484 this.getComponent().select();\r
485 return this;\r
486 },\r
487\r
488 resetOriginalValue: function() {\r
489 var me = this,\r
490 comp;\r
491\r
492 me.callParent();\r
493 component = me.getComponent();\r
494 if(component && component.hasOwnProperty("originalValue")) {\r
495 me.getComponent().originalValue = me.originalValue;\r
496 }\r
497 me.reset();\r
498 },\r
499\r
500 reset: function() {\r
501 var me = this;\r
502 me.getComponent().reset();\r
503\r
504 //we need to call this to sync the input with this field\r
505 me.getValue();\r
506\r
507 me.toggleClearIcon(me.isDirty());\r
508 },\r
509\r
510 isDirty: function() {\r
511 var component = this.getComponent();\r
512 if (component) {\r
513 return component.isDirty();\r
514 }\r
515 return false;\r
516 },\r
517\r
518 privates: {\r
519 toggleClearIcon: function(state) {\r
520 if (state) {\r
521 this.showClearIcon();\r
522 } else {\r
523 this.hideClearIcon();\r
524 }\r
525 }\r
526 }\r
527});\r
528\r