我想用JavaScript格式化价格。我想要一个函数,它将浮点作为参数,并返回如下格式的字符串:
"$ 2,500.00"
我该怎么做?
我想用JavaScript格式化价格。我想要一个函数,它将浮点作为参数,并返回如下格式的字符串:
"$ 2,500.00"
我该怎么做?
当前回答
请在下面的代码中找到我为支持国际化而开发的内容。
它将给定的数值格式化为特定于语言的格式。在给定的示例中,我使用了“en”,同时测试了“es”、“fr”和其他格式不同的国家。它不仅可以阻止用户键入字符,还可以格式化制表符上的值。
我已经为数字和十进制格式创建了组件。除此之外,我还创建了parseNumber(value,locale)和parseDecimal(value,locale)函数,这些函数将解析格式化数据以用于任何其他业务目的。所述函数将接受格式化数据并返回非格式化值。我在下面的共享代码中使用了jQuery验证器插件。
HTML格式:
<tr>
<td>
<label class="control-label">
Number Field:
</label>
<div class="inner-addon right-addon">
<input type="text" id="numberField"
name="numberField"
class="form-control"
autocomplete="off"
maxlength="17"
data-rule-required="true"
data-msg-required="Cannot be blank."
data-msg-maxlength="Exceeding the maximum limit of 13 digits. Example: 1234567890123"
data-rule-numberExceedsMaxLimit="en"
data-msg-numberExceedsMaxLimit="Exceeding the maximum limit of 13 digits. Example: 1234567890123"
onkeydown="return isNumber(event, 'en')"
onkeyup="return updateField(this)"
onblur="numberFormatter(this,
'en',
'Invalid character(s) found. Please enter valid characters.')">
</div>
</td>
</tr>
<tr>
<td>
<label class="control-label">
Decimal Field:
</label>
<div class="inner-addon right-addon">
<input type="text" id="decimalField"
name="decimalField"
class="form-control"
autocomplete="off"
maxlength="20"
data-rule-required="true"
data-msg-required="Cannot be blank."
data-msg-maxlength="Exceeding the maximum limit of 16 digits. Example: 1234567890123.00"
data-rule-decimalExceedsMaxLimit="en"
data-msg-decimalExceedsMaxLimit="Exceeding the maximum limit of 16 digits. Example: 1234567890123.00"
onkeydown="return isDecimal(event, 'en')"
onkeyup="return updateField(this)"
onblur="decimalFormatter(this,
'en',
'Invalid character(s) found. Please enter valid characters.')">
</div>
</td>
</tr>
JavaScript:
/*
* @author: dinesh.lomte
*/
/* Holds the maximum limit of digits to be entered in number field. */
var numericMaxLimit = 13;
/* Holds the maximum limit of digits to be entered in decimal field. */
var decimalMaxLimit = 16;
/**
*
* @param {type} value
* @param {type} locale
* @returns {Boolean}
*/
parseDecimal = function(value, locale) {
value = value.trim();
if (isNull(value)) {
return 0.00;
}
if (isNull(locale)) {
return value;
}
if (getNumberFormat(locale)[0] === '.') {
value = value.replace(/\./g, '');
} else {
value = value.replace(
new RegExp(getNumberFormat(locale)[0], 'g'), '');
}
if (getNumberFormat(locale)[1] === ',') {
value = value.replace(
new RegExp(getNumberFormat(locale)[1], 'g'), '.');
}
return value;
};
/**
*
* @param {type} element
* @param {type} locale
* @param {type} nanMessage
* @returns {Boolean}
*/
decimalFormatter = function (element, locale, nanMessage) {
showErrorMessage(element.id, false, null);
if (isNull(element.id) || isNull(element.value) || isNull(locale)) {
return true;
}
var value = element.value.trim();
value = value.replace(/\s/g, '');
value = parseDecimal(value, locale);
var numberFormatObj = new Intl.NumberFormat(locale,
{ minimumFractionDigits: 2,
maximumFractionDigits: 2
}
);
if (numberFormatObj.format(value) === 'NaN') {
showErrorMessage(element.id, true, nanMessage);
setFocus(element.id);
return false;
}
element.value = numberFormatObj.format(value);
return true;
};
/**
*
* @param {type} element
* @param {type} locale
* @param {type} nanMessage
* @returns {Boolean}
*/
numberFormatter = function (element, locale, nanMessage) {
showErrorMessage(element.id, false, null);
if (isNull(element.id) || isNull(element.value) || isNull(locale)) {
return true;
}
var value = element.value.trim();
var format = getNumberFormat(locale);
if (hasDecimal(value, format[1])) {
showErrorMessage(element.id, true, nanMessage);
setFocus(element.id);
return false;
}
value = value.replace(/\s/g, '');
value = parseNumber(value, locale);
var numberFormatObj = new Intl.NumberFormat(locale,
{ minimumFractionDigits: 0,
maximumFractionDigits: 0
}
);
if (numberFormatObj.format(value) === 'NaN') {
showErrorMessage(element.id, true, nanMessage);
setFocus(element.id);
return false;
}
element.value =
numberFormatObj.format(value);
return true;
};
/**
*
* @param {type} id
* @param {type} flag
* @param {type} message
* @returns {undefined}
*/
showErrorMessage = function(id, flag, message) {
if (flag) {
// only add if not added
if ($('#'+id).parent().next('.app-error-message').length === 0) {
var errorTag = '<div class=\'app-error-message\'>' + message + '</div>';
$('#'+id).parent().after(errorTag);
}
} else {
// remove it
$('#'+id).parent().next(".app-error-message").remove();
}
};
/**
*
* @param {type} id
* @returns
*/
setFocus = function(id) {
id = id.trim();
if (isNull(id)) {
return;
}
setTimeout(function() {
document.getElementById(id).focus();
}, 10);
};
/**
*
* @param {type} value
* @param {type} locale
* @returns {Array}
*/
parseNumber = function(value, locale) {
value = value.trim();
if (isNull(value)) {
return 0;
}
if (isNull(locale)) {
return value;
}
if (getNumberFormat(locale)[0] === '.') {
return value.replace(/\./g, '');
}
return value.replace(
new RegExp(getNumberFormat(locale)[0], 'g'), '');
};
/**
*
* @param {type} locale
* @returns {Array}
*/
getNumberFormat = function(locale) {
var format = [];
var numberFormatObj = new Intl.NumberFormat(locale,
{ minimumFractionDigits: 2,
maximumFractionDigits: 2
}
);
var value = numberFormatObj.format('132617.07');
format[0] = value.charAt(3);
format[1] = value.charAt(7);
return format;
};
/**
*
* @param {type} value
* @param {type} fractionFormat
* @returns {Boolean}
*/
hasDecimal = function(value, fractionFormat) {
value = value.trim();
if (isNull(value) || isNull(fractionFormat)) {
return false;
}
if (value.indexOf(fractionFormat) >= 1) {
return true;
}
};
/**
*
* @param {type} event
* @param {type} locale
* @returns {Boolean}
*/
isNumber = function(event, locale) {
var keyCode = event.which ? event.which : event.keyCode;
// Validating if user has pressed shift character
if (keyCode === 16) {
return false;
}
if (isNumberKey(keyCode)) {
return true;
}
var numberFormatter = [32, 110, 188, 190];
if (keyCode === 32
&& isNull(getNumberFormat(locale)[0]) === isNull(getFormat(keyCode))) {
return true;
}
if (numberFormatter.indexOf(keyCode) >= 0
&& getNumberFormat(locale)[0] === getFormat(keyCode)) {
return true;
}
return false;
};
/**
*
* @param {type} event
* @param {type} locale
* @returns {Boolean}
*/
isDecimal = function(event, locale) {
var keyCode = event.which ? event.which : event.keyCode;
// Validating if user has pressed shift character
if (keyCode === 16) {
return false;
}
if (isNumberKey(keyCode)) {
return true;
}
var numberFormatter = [32, 110, 188, 190];
if (keyCode === 32
&& isNull(getNumberFormat(locale)[0]) === isNull(getFormat(keyCode))) {
return true;
}
if (numberFormatter.indexOf(keyCode) >= 0
&& (getNumberFormat(locale)[0] === getFormat(keyCode)
|| getNumberFormat(locale)[1] === getFormat(keyCode))) {
return true;
}
return false;
};
/**
*
* @param {type} keyCode
* @returns {Boolean}
*/
isNumberKey = function(keyCode) {
if ((keyCode >= 48 && keyCode <= 57) ||
(keyCode >= 96 && keyCode <= 105)) {
return true;
}
var keys = [8, 9, 13, 35, 36, 37, 39, 45, 46, 109, 144, 173, 189];
if (keys.indexOf(keyCode) !== -1) {
return true;
}
return false;
};
/**
*
* @param {type} keyCode
* @returns {JSON@call;parse.numberFormatter.value|String}
*/
getFormat = function(keyCode) {
var jsonString = '{"numberFormatter" : [{"key":"32", "value":" ", "description":"space"}, {"key":"188", "value":",", "description":"comma"}, {"key":"190", "value":".", "description":"dot"}, {"key":"110", "value":".", "description":"dot"}]}';
var jsonObject = JSON.parse(jsonString);
for (var key in jsonObject.numberFormatter) {
if (jsonObject.numberFormatter.hasOwnProperty(key)
&& keyCode === parseInt(jsonObject.numberFormatter[key].key)) {
return jsonObject.numberFormatter[key].value;
}
}
return '';
};
/**
*
* @type String
*/
var jsonString = '{"shiftCharacterNumberMap" : [{"char":")", "number":"0"}, {"char":"!", "number":"1"}, {"char":"@", "number":"2"}, {"char":"#", "number":"3"}, {"char":"$", "number":"4"}, {"char":"%", "number":"5"}, {"char":"^", "number":"6"}, {"char":"&", "number":"7"}, {"char":"*", "number":"8"}, {"char":"(", "number":"9"}]}';
/**
*
* @param {type} value
* @returns {JSON@call;parse.shiftCharacterNumberMap.number|String}
*/
getShiftCharSpecificNumber = function(value) {
var jsonObject = JSON.parse(jsonString);
for (var key in jsonObject.shiftCharacterNumberMap) {
if (jsonObject.shiftCharacterNumberMap.hasOwnProperty(key)
&& value === jsonObject.shiftCharacterNumberMap[key].char) {
return jsonObject.shiftCharacterNumberMap[key].number;
}
}
return '';
};
/**
*
* @param {type} value
* @returns {Boolean}
*/
isShiftSpecificChar = function(value) {
var jsonObject = JSON.parse(jsonString);
for (var key in jsonObject.shiftCharacterNumberMap) {
if (jsonObject.shiftCharacterNumberMap.hasOwnProperty(key)
&& value === jsonObject.shiftCharacterNumberMap[key].char) {
return true;
}
}
return false;
};
/**
*
* @param {type} element
* @returns {undefined}
*/
updateField = function(element) {
var value = element.value;
for (var index = 0; index < value.length; index++) {
if (!isShiftSpecificChar(value.charAt(index))) {
continue;
}
element.value = value.replace(
value.charAt(index),
getShiftCharSpecificNumber(value.charAt(index)));
}
};
/**
*
* @param {type} value
* @param {type} element
* @param {type} params
*/
jQuery.validator.addMethod('numberExceedsMaxLimit', function(value, element, params) {
value = parseInt(parseNumber(value, params));
if (value.toString().length > numericMaxLimit) {
showErrorMessage(element.id, false, null);
setFocus(element.id);
return false;
}
return true;
}, 'Exceeding the maximum limit of 13 digits. Example: 1234567890123.');
/**
*
* @param {type} value
* @param {type} element
* @param {type} params
*/
jQuery.validator.addMethod('decimalExceedsMaxLimit', function(value, element, params) {
value = parseFloat(parseDecimal(value, params)).toFixed(2);
if (value.toString().substring(
0, value.toString().lastIndexOf('.')).length > numericMaxLimit
|| value.toString().length > decimalMaxLimit) {
showErrorMessage(element.id, false, null);
setFocus(element.id);
return false;
}
return true;
}, 'Exceeding the maximum limit of 16 digits. Example: 1234567890123.00.');
/**
* @param {type} id
* @param {type} locale
* @returns {boolean}
*/
isNumberExceedMaxLimit = function(id, locale) {
var value = parseInt(parseNumber(
document.getElementById(id).value, locale));
if (value.toString().length > numericMaxLimit) {
setFocus(id);
return true;
}
return false;
};
/**
* @param {type} id
* @param {type} locale
* @returns {boolean}
*/
isDecimalExceedsMaxLimit = function(id, locale) {
var value = parseFloat(parseDecimal(
document.getElementById(id).value, locale)).toFixed(2);
if (value.toString().substring(
0, value.toString().lastIndexOf('.')).length > numericMaxLimit
|| value.toString().length > decimalMaxLimit) {
setFocus(id);
return true;
}
return false;
};
其他回答
这可能有点晚了,但这是我刚刚为同事准备的一个方法,可以为所有数字添加一个支持区域设置的.toCurrencyString()函数。内部化仅用于数字分组,而不是货币符号-如果您输出美元,请使用提供的“$”,因为日本或中国的123 4567美元与美国的1234567美元相同。如果您输出欧元等,请将货币符号从“$”改为“$”。
在HTML<head>部分的任何地方或在需要使用它之前的任何地方声明:
Number.prototype.toCurrencyString = function(prefix, suffix) {
if (typeof prefix === 'undefined') { prefix = '$'; }
if (typeof suffix === 'undefined') { suffix = ''; }
var _localeBug = new RegExp((1).toLocaleString().replace(/^1/, '').replace(/\./, '\\.') + "$");
return prefix + (~~this).toLocaleString().replace(_localeBug, '') + (this % 1).toFixed(2).toLocaleString().replace(/^[+-]?0+/,'') + suffix;
}
那你就完了!在需要将数字输出为货币的任何位置使用(number).toCurrencyString()。
var MyNumber = 123456789.125;
alert(MyNumber.toCurrencyString()); // alerts "$123,456,789.13"
MyNumber = -123.567;
alert(MyNumber.toCurrencyString()); // alerts "$-123.57"
http://code.google.com/p/javascript-number-formatter/:
短、快、灵活但独立。只有75行,包括MIT许可证信息、空白行和注释。接受标准数字格式,如#、##0.00或带否定的-000.####。接受任何国家/地区格式,如###0,00,#,###.##,#‘###.##或任何类型的非编号符号。接受任意数字分组。#、##、#0.000或#、####0.##均有效。接受任何冗余/防傻瓜格式。##、###、##。#或0#、#00####0#都正常。自动数字舍入。简单的界面,只需提供如下掩码和值:格式(“0.0000”,3.141592)
UPDATE这是我自己开发的应用程序,用于最常见的任务:
var NumUtil = {};
/**
Petty print 'num' wth exactly 'signif' digits.
pp(123.45, 2) == "120"
pp(0.012343, 3) == "0.0123"
pp(1.2, 3) == "1.20"
*/
NumUtil.pp = function(num, signif) {
if (typeof(num) !== "number")
throw 'NumUtil.pp: num is not a number!';
if (isNaN(num))
throw 'NumUtil.pp: num is NaN!';
if (num < 1e-15 || num > 1e15)
return num;
var r = Math.log(num)/Math.LN10;
var dot = Math.floor(r) - (signif-1);
r = r - Math.floor(r) + (signif-1);
r = Math.round(Math.exp(r * Math.LN10)).toString();
if (dot >= 0) {
for (; dot > 0; dot -= 1)
r += "0";
return r;
} else if (-dot >= r.length) {
var p = "0.";
for (; -dot > r.length; dot += 1) {
p += "0";
}
return p+r;
} else {
return r.substring(0, r.length + dot) + "." + r.substring(r.length + dot);
}
}
/** Append leading zeros up to 2 digits. */
NumUtil.align2 = function(v) {
if (v < 10)
return "0"+v;
return ""+v;
}
/** Append leading zeros up to 3 digits. */
NumUtil.align3 = function(v) {
if (v < 10)
return "00"+v;
else if (v < 100)
return "0"+v;
return ""+v;
}
NumUtil.integer = {};
/** Round to integer and group by 3 digits. */
NumUtil.integer.pp = function(num) {
if (typeof(num) !== "number") {
console.log("%s", new Error().stack);
throw 'NumUtil.integer.pp: num is not a number!';
}
if (isNaN(num))
throw 'NumUtil.integer.pp: num is NaN!';
if (num > 1e15)
return num;
if (num < 0)
throw 'Negative num!';
num = Math.round(num);
var group = num % 1000;
var integ = Math.floor(num / 1000);
if (integ === 0) {
return group;
}
num = NumUtil.align3(group);
while (true) {
group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0)
return group + " " + num;
num = NumUtil.align3(group) + " " + num;
}
return num;
}
NumUtil.currency = {};
/** Round to coins and group by 3 digits. */
NumUtil.currency.pp = function(amount) {
if (typeof(amount) !== "number")
throw 'NumUtil.currency.pp: amount is not a number!';
if (isNaN(amount))
throw 'NumUtil.currency.pp: amount is NaN!';
if (amount > 1e15)
return amount;
if (amount < 0)
throw 'Negative amount!';
if (amount < 1e-2)
return 0;
var v = Math.round(amount*100);
var integ = Math.floor(v / 100);
var frac = NumUtil.align2(v % 100);
var group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0) {
return group + "." + frac;
}
amount = NumUtil.align3(group);
while (true) {
group = integ % 1000;
integ = Math.floor(integ / 1000);
if (integ === 0)
return group + " " + amount + "." + frac;
amount = NumUtil.align3(group) + " " + amount;
}
return amount;
}
function CurrencyFormatted(amount)
{
var i = parseFloat(amount);
if(isNaN(i)) { i = 0.00; }
var minus = '';
if(i < 0) { minus = '-'; }
i = Math.abs(i);
i = parseInt((i + .005) * 100);
i = i / 100;
s = new String(i);
if(s.indexOf('.') < 0) { s += '.00'; }
if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
s = minus + s;
return s;
}
来自WillMaster。
快速快捷的解决方案(适用于任何地方!)
(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); // 12,345.67
此解决方案背后的思想是用第一个匹配和逗号替换匹配的部分,即“$&,”。匹配是使用前瞻方法完成的。您可以将表达式读为“匹配一个数字,如果它后面跟着三个数字集(一个或多个)和一个点的序列”。
测验:
1 --> "1.00"
12 --> "12.00"
123 --> "123.00"
1234 --> "1,234.00"
12345 --> "12,345.00"
123456 --> "123,456.00"
1234567 --> "1,234,567.00"
12345.67 --> "12,345.67"
演示:http://jsfiddle.net/hAfMM/9571/
扩展短解决方案
您还可以扩展Number对象的原型,以添加对任意数量的小数[0..n]和数字组大小[0..x]的额外支持:
/**
* Number.prototype.format(n, x)
*
* @param integer n: length of decimal
* @param integer x: length of sections
*/
Number.prototype.format = function(n, x) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};
1234..format(); // "1,234"
12345..format(2); // "12,345.00"
123456.7.format(3, 2); // "12,34,56.700"
123456.789.format(2, 4); // "12,3456.79"
演示/测试:http://jsfiddle.net/hAfMM/435/
超扩展短解决方案
在此超级扩展版本中,您可以设置不同的分隔符类型:
/**
* Number.prototype.format(n, x, s, c)
*
* @param integer n: length of decimal
* @param integer x: length of whole part
* @param mixed s: sections delimiter
* @param mixed c: decimal delimiter
*/
Number.prototype.format = function(n, x, s, c) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
num = this.toFixed(Math.max(0, ~~n));
return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};
12345678.9.format(2, 3, '.', ','); // "12.345.678,90"
123456.789.format(4, 4, ' ', ':'); // "12 3456:7890"
12345678.9.format(0, 3, '-'); // "12-345-679"
演示/测试:http://jsfiddle.net/hAfMM/612/
String.prototype.toPrice = function () {
var v;
if (/^\d+(,\d+)$/.test(this))
v = this.replace(/,/, '.');
else if (/^\d+((,\d{3})*(\.\d+)?)?$/.test(this))
v = this.replace(/,/g, "");
else if (/^\d+((.\d{3})*(,\d+)?)?$/.test(this))
v = this.replace(/\./g, "").replace(/,/, ".");
var x = parseFloat(v).toFixed(2).toString().split("."),
x1 = x[0],
x2 = ((x.length == 2) ? "." + x[1] : ".00"),
exp = /^([0-9]+)(\d{3})/;
while (exp.test(x1))
x1 = x1.replace(exp, "$1" + "," + "$2");
return x1 + x2;
}
alert("123123".toPrice()); //123,123.00
alert("123123,316".toPrice()); //123,123.32
alert("12,312,313.33213".toPrice()); //12,312,313.33
alert("123.312.321,32132".toPrice()); //123,312,321.32