3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
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.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.form.field.Number
17 * @extends Ext.form.field.Spinner
19 A numeric text field that provides automatic keystroke filtering to disallow non-numeric characters,
20 and numeric validation to limit the value to a range of valid numbers. The range of acceptable number
21 values can be controlled by setting the {@link #minValue} and {@link #maxValue} configs, and fractional
22 decimals can be disallowed by setting {@link #allowDecimals} to `false`.
24 By default, the number field is also rendered with a set of up/down spinner buttons and has
25 up/down arrow key and mouse wheel event listeners attached for incrementing/decrementing the value by the
26 {@link #step} value. To hide the spinner buttons set `{@link #hideTrigger hideTrigger}:true`; to disable the arrow key
27 and mouse wheel handlers set `{@link #keyNavEnabled keyNavEnabled}:false` and
28 `{@link #mouseWheelEnabled mouseWheelEnabled}:false`. See the example below.
31 {@img Ext.form.Number/Ext.form.Number1.png Ext.form.Number component}
32 Ext.create('Ext.form.Panel', {
36 renderTo: Ext.getBody(),
41 fieldLabel: 'Bottles of Beer',
47 text: 'Take one down, pass it around',
49 this.up('form').down('[name=bottles]').spinDown();
54 #Removing UI Enhancements#
55 {@img Ext.form.Number/Ext.form.Number2.png Ext.form.Number component}
56 Ext.create('Ext.form.Panel', {
57 title: 'Personal Info',
60 renderTo: Ext.getBody(),
66 minValue: 0, //prevents negative numbers
68 // Remove spinner buttons, and arrow key and mouse wheel listeners
71 mouseWheelEnabled: false
76 Ext.create('Ext.form.Panel', {
77 renderTo: Ext.getBody(),
85 fieldLabel: 'Even Numbers',
87 // Set step so it skips every other number
91 // Add change handler to force user-entered numbers to evens
93 change: function(field, value) {
94 value = parseInt(value, 10);
95 field.setValue(value + value % 2);
104 * @docauthor Jason Johnston <jason@sencha.com>
106 Ext.define('Ext.form.field.Number', {
107 extend:'Ext.form.field.Spinner',
108 alias: 'widget.numberfield',
109 alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
112 * @cfg {RegExp} stripCharsRe @hide
115 * @cfg {RegExp} maskRe @hide
119 * @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)
121 allowDecimals : true,
124 * @cfg {String} decimalSeparator Character(s) to allow as the decimal separator (defaults to '.')
126 decimalSeparator : '.',
129 * @cfg {Number} decimalPrecision The maximum precision to display after the decimal separator (defaults to 2)
131 decimalPrecision : 2,
134 * @cfg {Number} minValue The minimum allowed value (defaults to Number.NEGATIVE_INFINITY). Will be used by
135 * the field's validation logic, and for
136 * {@link Ext.form.field.Spinner#setSpinUpEnabled enabling/disabling the down spinner button}.
138 minValue: Number.NEGATIVE_INFINITY,
141 * @cfg {Number} maxValue The maximum allowed value (defaults to Number.MAX_VALUE). Will be used by
142 * the field's validation logic, and for
143 * {@link Ext.form.field.Spinner#setSpinUpEnabled enabling/disabling the up spinner button}.
145 maxValue: Number.MAX_VALUE,
148 * @cfg {Number} step Specifies a numeric interval by which the field's value will be incremented or
149 * decremented when the user invokes the spinner. Defaults to <tt>1</tt>.
154 * @cfg {String} minText Error text to display if the minimum value validation fails (defaults to 'The minimum
155 * value for this field is {minValue}')
157 minText : 'The minimum value for this field is {0}',
160 * @cfg {String} maxText Error text to display if the maximum value validation fails (defaults to 'The maximum
161 * value for this field is {maxValue}')
163 maxText : 'The maximum value for this field is {0}',
166 * @cfg {String} nanText Error text to display if the value is not a valid number. For example, this can happen
167 * if a valid character like '.' or '-' is left in the field with no number (defaults to '{value} is not a valid number')
169 nanText : '{0} is not a valid number',
172 * @cfg {String} negativeText Error text to display if the value is negative and {@link #minValue} is set to
173 * <tt>0</tt>. This is used instead of the {@link #minText} in that circumstance only.
175 negativeText : 'The value cannot be negative',
178 * @cfg {String} baseChars The base set of characters to evaluate as valid numbers (defaults to '0123456789').
180 baseChars : '0123456789',
183 * @cfg {Boolean} autoStripChars True to automatically strip not allowed characters from the field. Defaults to <tt>false</tt>
185 autoStripChars: false,
187 initComponent: function() {
193 me.setMinValue(me.minValue);
194 me.setMaxValue(me.maxValue);
196 // Build regexes for masking and stripping based on the configured options
197 if (me.disableKeyFilter !== true) {
198 allowed = me.baseChars + '';
199 if (me.allowDecimals) {
200 allowed += me.decimalSeparator;
202 if (me.minValue < 0) {
205 allowed = Ext.String.escapeRegex(allowed);
206 me.maskRe = new RegExp('[' + allowed + ']');
207 if (me.autoStripChars) {
208 me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
214 * Runs all of Number's validations and returns an array of any errors. Note that this first
215 * runs Text's validations, so the returned array is an amalgamation of all field errors.
216 * The additional validations run test that the value is a number, and that it is within the
217 * configured min and max values.
218 * @param {Mixed} value The value to get errors for (defaults to the current field value)
219 * @return {Array} All validation errors for this field
221 getErrors: function(value) {
223 errors = me.callParent(arguments),
224 format = Ext.String.format,
227 value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
229 if (value.length < 1) { // if it's blank and textfield didn't flag it then it's valid
233 value = String(value).replace(me.decimalSeparator, '.');
236 errors.push(format(me.nanText, value));
239 num = me.parseValue(value);
241 if (me.minValue === 0 && num < 0) {
242 errors.push(this.negativeText);
244 else if (num < me.minValue) {
245 errors.push(format(me.minText, me.minValue));
248 if (num > me.maxValue) {
249 errors.push(format(me.maxText, me.maxValue));
256 rawToValue: function(rawValue) {
257 var value = this.fixPrecision(this.parseValue(rawValue));
258 if (value === null) {
259 value = rawValue || null;
264 valueToRaw: function(value) {
266 decimalSeparator = me.decimalSeparator;
267 value = me.parseValue(value);
268 value = me.fixPrecision(value);
269 value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
270 value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
274 onChange: function() {
276 value = me.getValue(),
277 valueIsNull = value === null;
279 me.callParent(arguments);
281 // Update the spinner buttons
282 me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
283 me.setSpinDownEnabled(valueIsNull || value > me.minValue);
287 * Replaces any existing {@link #minValue} with the new value.
288 * @param {Number} value The minimum value
290 setMinValue : function(value) {
291 this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
295 * Replaces any existing {@link #maxValue} with the new value.
296 * @param {Number} value The maximum value
298 setMaxValue: function(value) {
299 this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
303 parseValue : function(value) {
304 value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
305 return isNaN(value) ? null : value;
312 fixPrecision : function(value) {
315 precision = me.decimalPrecision;
318 return nan ? '' : value;
319 } else if (!me.allowDecimals || precision <= 0) {
323 return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
326 beforeBlur : function() {
328 v = me.parseValue(me.getRawValue());
330 if (!Ext.isEmpty(v)) {
335 onSpinUp: function() {
338 me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
342 onSpinDown: function() {
345 me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));