/**
* Parse number submodule.
*
* @module datatype-number
* @submodule datatype-number-parse
* @for Number
*/
var safe = Y.Escape.regex,
SPACES = '\\s*';
Y.mix(Y.namespace("Number"), {
/**
* Returns a parsing function for the given configuration.
* It uses `Y.cached` so it expects the format spec separated into
* individual values.
* The method further uses closure to put together and save the
* regular expresssion just once in the outer function.
*
* @method _buildParser
* @param [prefix] {String} Prefix string to be stripped out.
* @param [suffix] {String} Suffix string to be stripped out.
* @param [separator] {String} Thousands separator to be stripped out.
* @param [decimal] {String} Decimal separator to be replaced by a dot.
* @return {Function} Parsing function.
* @private
*/
_buildParser: Y.cached(function (prefix, suffix, separator, decimal) {
var regexBits = [],
regex;
if (prefix) {
regexBits.push('^' + SPACES + safe(prefix) + SPACES);
}
if (suffix) {
regexBits.push(SPACES + safe(suffix) + SPACES + '$');
}
if (separator) {
regexBits.push(safe(separator) + '(?=\\d)');
}
regex = new RegExp('(?:' + regexBits.join('|') + ')', 'g');
if (decimal === '.') {
decimal = null;
}
return function (val) {
val = val.replace(regex, '');
return decimal ? val.replace(decimal, '.') : val;
};
}),
/**
* Converts data to type Number.
* If a `config` argument is used, it will strip the `data` of the prefix,
* the suffix and the thousands separator, if any of them are found,
* replace the decimal separator by a dot and parse the resulting string.
* Extra whitespace around the prefix and suffix will be ignored.
*
* @method parse
* @param data {String | Number | Boolean} Data to convert. The following
* values return as null: null, undefined, NaN, "".
* @param [config] {Object} Optional configuration values, same as for [Y.Date.format](#method_format).
* @param [config.prefix] {String} String to be removed from the start, like a currency designator "$"
* @param [config.decimalPlaces] {Number} Ignored, it is accepted only for compatibility with [Y.Date.format](#method_format).
* @param [config.decimalSeparator] {String} Decimal separator.
* @param [config.thousandsSeparator] {String} Thousands separator.
* @param [config.suffix] {String} String to be removed from the end of the number, like " items".
* @return {Number} A number, or null.
*/
parse: function(data, config) {
var parser;
if (config && typeof data === 'string') {
parser = this._buildParser(config.prefix, config.suffix, config.thousandsSeparator, config.decimalSeparator);
data = parser(data);
}
if (typeof data === 'string' && Y.Lang.trim(data) !== '') {
data = +data;
}
// catch NaN and ±Infinity
if (typeof data !== 'number' || !isFinite(data)) {
data = null;
}
// on the same line to get stripped for raw/min.js by build system
if (data === null) { Y.log("Could not parse data to type Number", "warn", "number"); }
return data;
}
});
// Add Parsers shortcut
Y.namespace("Parsers").number = Y.Number.parse;
Y.namespace("DataType");
Y.DataType.Number = Y.Number;