/**
 * The Number field creates an HTML5 number input and is usually created inside a form. Because it creates an HTML
 * number input field, most browsers will show a specialized virtual keyboard for entering numbers. The Number field
 * only accepts numerical input and also provides additional spinner UI that increases or decreases the current value
 * by a configured {@link #stepValue step value}. Here's how we might use one in a form:
 *
 *     @example
 *     Ext.create('Ext.form.Panel', {
 *         fullscreen: true,
 *         items: [
 *             {
 *                 xtype: 'fieldset',
 *                 title: 'How old are you?',
 *                 items: [
 *                     {
 *                         xtype: 'numberfield',
 *                         label: 'Age',
 *                         minValue: 18,
 *                         maxValue: 150,
 *                         name: 'age'
 *                     }
 *                 ]
 *             }
 *         ]
 *     });
 *
 * Or on its own, outside of a form:
 *
 *     Ext.create('Ext.field.Number', {
 *         label: 'Age',
 *         value: '26'
 *     });
 *
 * ## minValue, maxValue and stepValue
 *
 * The {@link #minValue} and {@link #maxValue} configurations are self-explanatory and simply constrain the value
 * entered to the range specified by the configured min and max values. The other option exposed by this component
 * is {@link #stepValue}, which enables you to set how much the value changes every time the up and down spinners
 * are tapped on. For example, to create a salary field that ticks up and down by $1,000 each tap we can do this:
 *
 *     @example
 *     Ext.create('Ext.form.Panel', {
 *         fullscreen: true,
 *         items: [
 *             {
 *                 xtype: 'fieldset',
 *                 title: 'Are you rich yet?',
 *                 items: [
 *                     {
 *                         xtype: 'numberfield',
 *                         label: 'Salary',
 *                         value: 30000,
 *                         minValue: 25000,
 *                         maxValue: 50000,
 *                         stepValue: 1000
 *                     }
 *                 ]
 *             }
 *         ]
 *     });
 *
 * This creates a field that starts with a value of $30,000, steps up and down in $1,000 increments and will not go
 * beneath $25,000 or above $50,000.
 *
 * Because number field inherits from {@link Ext.field.Text textfield} it gains all of the functionality that text
 * fields provide, including getting and setting the value at runtime, validations and various events that are fired as
 * the user interacts with the component. Check out the {@link Ext.field.Text} docs to see the additional functionality
 * available.
 */
Ext.define('Ext.field.Number', {
    extend: 'Ext.field.Text',
    xtype: 'numberfield',
    alternateClassName: 'Ext.form.Number',
 
    config: {
        /**
         * @cfg {Number} [minValue=undefined] The minimum value that this Number field can accept (defaults to `undefined`, e.g. no minimum).
         * @accessor
         */
        minValue: null,
 
        /**
         * @cfg {Number} [maxValue=undefined] The maximum value that this Number field can accept (defaults to `undefined`, e.g. no maximum).
         * @accessor
         */
        maxValue: null,
 
        /**
         * @cfg {Number} [stepValue=undefined] The amount by which the field is incremented or decremented each time the spinner is tapped.
         * Defaults to `undefined`, which means that the field goes up or down by 1 each time the spinner is tapped.
         * @accessor
         */
        stepValue: null,
        
        /**
         * @cfg {Number} [decimals=2]
         * The maximum precision to display after the decimal separator.
         * @locale
         */
        decimals: 2
    },
 
    classCls: Ext.baseCSSPrefix + 'numberfield',
    inputType: 'number',
 
    /**
     * Updates the `min` attribute with the {@link #minValue} configuration.
     * @private
     */
    updateMinValue: function(newMinValue) {
        this.setInputAttribute('min', newMinValue);
    },
 
    /**
     * Updates the `max` attribute with the {@link #maxValue} configuration.
     * @private
     */
    updateMaxValue: function(newMaxValue) {
        this.setInputAttribute('max', newMaxValue);
    },
 
    /**
     * Updates the `step` attribute with the {@link #stepValue} configuration
     * @private
     */
    updateStepValue: function(newStepValue) {
        this.setInputAttribute('step', newStepValue);
    },
 
    applyValue: function(value, oldValue) {
        var me = this,
            minValue = me.getMinValue(),
            maxValue = me.getMaxValue(),
            precision = me.getDecimals();
 
        if (this.isConfiguring) {
            this.originalValue = value;
        }
 
        if (Ext.isNumber(minValue) && Ext.isNumber(value)) {
            value = Math.max(value, minValue);
        }
 
        if (Ext.isNumber(maxValue) && Ext.isNumber(value)) {
            value = Math.min(value, maxValue);
        }
 
        value = parseFloat(value);
        
        if (isNaN(value)) {
            return '';
        }
        
        if (precision != null) {
            value = Ext.Number.roundToPrecision(value, precision);
        }
 
        if (value === oldValue) {
 
            // If the old value is the same as the current value 
            // because maxValue or minValue changed the value 
            // that was passed in, we need to make sure 
            // updateInputValue is executed so the <input> 
            // is properly updated and in sync with the value. 
            this.updateInputValue(value);
        }
 
        return (isNaN(value)) ? '' : value;
    },
 
    getValue: function() {
        var value = parseFloat(this.callParent(), 10);
        return (isNaN(value)) ? null : value;
    }
});