I have an issue with number inputting. The user usually enters a large number with many zeros,
and often they are missing one or two zero as it is difficult to accurately count them.
I think javascript can work this out by showing the user the number they have inducted, formatted with commas.
eg:
input: | 1230000000000 |
Result: 1,230,000,000,000
How could this be accomplished?
Use the following function in javascript
function addCommas(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
example
addCommas('9999999.00')
// 9,999,999.00
This is an old question but still without a correct answer so, this is my dynamic solution, it takes the same addCommas function to reformat the output but add a keyup event to clean the current value ( remove ',' ) and reformat again the new value.
$('.datainto').keyup(function () {
var value = $(this).val().replace(/,/g,'');
$(this).val(addCommas(value));
});
Check the working solution here:
http://jsfiddle.net/darorck/371zrjet/
In modern browsers, you can simply achieve this with toLocaleString()
console.log((1230000000000).toLocaleString());
console.log((12300000000).toLocaleString());
console.log((1230000.152).toLocaleString());
I know I'm very late for giving the answer, But still, I post this answer because this question is coming in the search result of How to add a dynamic comma in number in javascript, So I thought I need to add an answer which is shorter and better for upcoming developers.
Related
I recently came up with this code while answering another StackOverflow question. Basically, on blur, this code will properly comma separate by thousands and leave the decimal at two digits (like how USD is written [7,745.56]).
I was wondering if there is more concise way of using regex to , separate and cut off excessive decimal places. I recently updated this post with my most recent attempt. Is there a better way of doing this with regex?
Input -> Target Output
7456 -> 7,456
45345 -> 45,345
25.23523534 -> 25.23
3333.239 -> 3,333.23
234.99 -> 234.99
2300.99 -> 2,300.99
23123123123.22 -> 23,123,123,123.22
Current Regex
var result;
var str = []
reg = new RegExp(/(\d*(\d{2}\.)|\d{1,3})/, "gi");
reversed = "9515321312.2323432".split("").reverse().join("")
while (result = reg.exec(reversed)) {
str.push(result[2] ? result[2] : result[0])
}
console.log(str.join(",").split("").reverse().join("").replace(",.","."))
As an alternative to the Regex, you could use the following approach
Number(num.toFixed(2)).toLocaleString('en-US')
or
num.toLocaleString('en-US', {maximumFractionDigits: 2})
You would still have the toFixed(2), but it's quite clean. toFixed(2) though won't floor the number like you want. Same with {maximumFractionDigits: 2} as the second parameter to toLocaleString as well.
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums)
console.log(num, '->', Number(num.toFixed(2)).toLocaleString('en-US') )
Flooring the number like you showed is a bit tricky. Doing something like (num * 100 | 0) / 100 does not work. The calculation loses precision (e.g. .99 will become .98 in certain situations). (also |0 wouldn't work with larger numbers but even Math.floor() has the precision problem).
The solution would be to treat the numbers like strings.
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums) console.log(num, '->', format(num))
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
(when changing to another format than 'en-US' pay attention to the . in numbers as some languages use a , as fractal separator)
For Compatibility, according to CanIUse toLocaleString('en-US') is
supported in effectively all browsers (since IE6+, Firefox 2+, Chrome
1+ etc)
If you really insist on doing this purely in regex (and truncate instead of round the fractional digits), the only solution I can think of is to use a replacement function as the second argument to .replace():
('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
This makes all your test cases pass:
function format(num){
return ('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
}
test(7456, "7,456");
test(45345, "45,345");
test(25.23523534, "25.23"); //truncated, not rounded
test(3333.239, "3,333.23"); //truncated, not rounded
test(234.99, "234.99");
test(2300.99, "2,300.99");
test(23123123123.22, "23,123,123,123.22");
function test(num, expected){
var actual = format(num);
console.log(num + ' -> ' + expected + ' => ' + actual + ': ' +
(actual === expected ? 'passed' : 'failed')
);
}
I added another layer where regex that drops the unwanted decimals below hundredths on top of your regex comma adding logic;
val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,")
doIt("7456");
doIt("45345");
doIt("25.23523534");
doIt("3333.239");
doIt("234.99");
doIt("2300.99");
doIt("23123123123.22");
doIt("5812090285.2817481974897");
function doIt(val) {
console.log(val + " -> " + val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,"));
}
If multiple calls of regex replace is OK, this answer should satisfy you, since it is only has regex replace logic and nothing else.
Try:
var n = 5812090285.2817481974897;
n = n.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
console.log(n);
Outputs:
5,812,090,285.28
Note: .toFixed(2) returns a string. So in order to simplify this further you must add a way to turn n into a string before executing your regex. For example:
n.toString.replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); //ofc with the additional regex
Although you would think it wouldn't matter in javascript, it apparently does in this situation. So I dont know how much 'less' messy it would be to not use.
Here is a way to do it without a regular expression:
value.toLocaleString("en-US", { maximumFractionDigits: 2 })
function formatValue() {
var source = document.getElementById("source");
var output = document.getElementById("output");
var value = parseFloat(source.value);
output.innerText = value.toLocaleString("en-US", { maximumFractionDigits: 2 });
}
<input id="source" type="text" />
<button onclick="formatValue()">Format</button>
<div id="output"></div>
RegEx to rescue again!
My solution has two parts :
.toFixed : Used to limit the decimal limit
/(\d)(?=(\d\d\d)+(?!\d))/g : It makes use of back reference with three digits at a time
Here's everything put together :
// .toFixed((/\./g.test(num)) ? 2 : 0) it tests if the input number has any decimal places, if so limits it to 2 digits and if not, get's rid of it altogether by setting it to 0
num.toFixed((/\./g.test(num)) ? 2 : 0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
You can see it in action here :
var input = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
input.forEach(function(num) {
$('div')
.append(
$('<p>').text(num + ' => ' +
num.toFixed( (/\./g.test(num))?2:0 ).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> </div>
NOTE: I've only used jQuery to append the results
You can do like this
(parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
Here just convert number to formatted number with rounded down to 2 decimal places and then remove the .00 if exist.
This can be one approach you can use.
var format = function (num) {
return (parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
}
$(function () {
$("#principalAmtOut").blur(function (e) {
$(this).val(format($(this).val()));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="principalAmtOut" type="text" />
You can use Intl.NumberFormat with style set to "decimal" and maximumFractionDigits set to 2 at options object passed at second parameter
const nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22];
const formatOptions = {style:"decimal", maximumFractionDigits:2};
const formatter = new Intl.NumberFormat("en-US", formatOptions);
const formatNums = num => formatter.format(num);
let formattedNums = nums.map(formatNums);
console.log(formattedNums);
I found a solution based on #Pierre's answer without using of toFixed:
function format(n) {
n = +n;
var d = Math.round(n * 100) % 100;
return (Math.floor(n) + '').replace(/(\d)(?=(\d{3})+$)/g, '$1,') + (d > 9 ? '.' + d : d > 0 ? '.0' + d : '');
}
console.log(format(7456));
console.log(format(7456.0));
console.log(format(7456.1));
console.log(format(7456.01));
console.log(format(7456.001));
console.log(format(45345));
console.log(format(25.23523534));
console.log(format(3333.239));
console.log(format(234.99));
console.log(format(2300.99));
console.log(format(23123123123.22));
console.log(format('23123123123.22'));
Sorry if duplicated, but I really confused with these javascript.
Please help me, if willing.
I have this javascript function that already worked, this function will add thousands separator with commas :
function addCommas(x) {
//remove commas
retVal = x ? parseFloat(x.replace(/,/g, '')) : 0;
//apply formatting
return retVal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
And I call this function in the textbox, like this :
Number Format <asp:TextBox ID="txtPrice" runat="server" onkeyup="this.value=addCommas(this.value);"></asp:TextBox>
The output, looked like this (the separator using commas):
60,000,234
BUT I want the output, looked like this (the separator using period) :
60.000.234
Give me a solution still using these Javascript function, please. Thanks
I notice what was wrong in my code in comment.
Try this, I used it long time ago.
function addCommas(x) {
var retVal=x.toString().replace(/[^\d]/g,'');
while(/(\d+)(\d{3})/.test(retVal)) {
retVal=retVal.replace(/(\d+)(\d{3})/,'$1'+'.'+'$2');
}
return retVal;
}
Number <input type="text" onkeypress="this.value=addCommas(this.value);" onkeyup="this.value=addCommas(this.value);" />
I hope so this will help You.
function addCommas(x) {
x = '' + x;
//remove commas
retVal = x ? parseFloat(x.replace(/,/g, '')) : 0;
//apply formatting
return retVal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
It's still your function, but the variable x is converted into a string first.
This question already has answers here:
Javascript Thousand Separator / string format [duplicate]
(15 answers)
How to format a number with commas as thousands separators?
(50 answers)
Closed 7 years ago.
I have written a code to calculate number of votes. I am getting the output as 138405, 150000 etc.
I want these figures to be formatted like this 138,405.
How do I achieve this using pure javascript?
Depending on your browser targets you could use Number.prototype.toLocaleString() which will format your numbers based on locale which you can specify. Examples are on the linked page below.
See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
For example:
var number = 123456.789;
console.log(number.toLocaleString('en-US'));
// → 123,456.789
If no locale is specified the users browser locale will be used.
You need to decide what the convention is first. Do you want your commas to separate two digits, or three?
Let's imagine that it's 3, as per the usual convention.
1000 should become 1, 000
10000 should become 10,000
100000 should become 100,000
1000000 should become 1,000,000
The code to make that happen can be as trivial as:
function formatWithComma(interval, num) {
const digits = String(num).split('').reverse();
const output = [];
digits.forEach(function (digit, index, digits) {
output.push(digit);
if ((index + 1) % interval === 0 && (index + 1) < digits.length) {
output.push(',');
}
});
return output.reverse().join('');
}
This function expects to be called with an interval at which commas will be inserted and a number, from which to build a formatted string.
formatWithComma(3, 12345) === "12,345"
formatWithComma(2, 12345) === "1,23,45"
You could take this one step further and use Javascript's partial application mechanism to create a format function with the first argument preloaded.
var format = formatWithComma.bind(this, 3);
After that, any calls to format will insert commas at every 3rd digit.
I came up with this function. It works fine for me.
function addCommas(nStr) {
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
sorry i couldn't think of better title ! plus my english sucks
her is my first plugin (basically i repackaged some js code as a plugin )
it adds a comma , separator to value every 3 digit , when someone types something inside textfield
(function($){
$.fn.num = function(userop){
var options = $.extend( {seperator:','} , userop );
$(this).keyup(function(e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace( /\,/g, "");
var x = nStr.split( '.' );
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while ( rgx.test(x1) ) {
x1 = x1.replace( rgx, '$1' + options.seperator + '$2' );
}
$(this).val( x1 + x2 );
})
}
})(jQuery);
$('.number_input').num();
but problem is if i put 123456 in my textfield
var n = $('.number_input').val();
console.log(n);
will return 123,456
which is fine but it suppose to be a numeric value and each time user has to extract commas manually
by running it trough something like
n = Number($.trim(n.replace(/\,/g,'')));
is there any way to add this line to my plugin so it gets executed when someone runs .val() on textfild ?
basically i want to write comma remover once not every single time that i get each effected textfield value
If you change the default .val() method with the combination of the .data(), you'll be able the do what you want. Note that change .val() can have undesired effect (mostly when user try to override .val() aswell...)
Anyway, the first thing to do is give a data to every element that are active number. So in you init, add this code :
this.data('__numered', true);
Now we can detect if the element as a formatting.
Then here come the tricky part : overriding.
You'll have to save the old .val() method :
$.fn.__val = $.fn.val;
Then recreate .val() but check if its a numbered item :
$.fn.val = function(set){
if(typeof set === 'undefined'){
if(this.first().data('__numered'))
return Number($.trim(this.first().__val().replace(/\,/g,'')));
else
return this.first().__val();
}else
return this.__val(set)
}
Fiddle : http://jsfiddle.net/Tw77J/1/
First of all
I think I'm suggesting a better way to do what you are asking, instead of directly answering.
If you use, my solution, your plugin gives the users the option of getting what they want. (You cant predict what users need)
My Solution:
You can add this simple code:
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
So your plugin would become:
(function ($) {
$.fn.num = function (userop) {
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
var options = $.extend({
seperator: ','
}, userop);
$(this).keyup(function (e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace(/\,/g, "");
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + options.seperator + '$2');
}
$(this).val(x1 + x2);
});
};
})(jQuery);
Remember, you are the creator of the plugin, and you can impose some rules for the developers using your plugin.
That said, ask your users to use $('selector').num('val'); to get the value without commas, and $('selector').val(), if they want it with comma.
So to brush up:
Use $('selector').num('val'); // with comma
Use $('selector').val(); // without comma
Put that in readme file or any document file.
Live demo!
Also, don't forget me to add me as a contributor to the plugin, If my answer helped you ;)
How would it be a nice way of handling this?
I already thought on removing the comma and then parsing to float.
Do you know a better/cleaner way?
Thanks
parseFloat( theString.replace(/,/g,'') );
I don't know why no one has suggested this expression-
parseFloat( theString.replace(/[^\d\.]/g,'') );
Removes any non-numeric characters except for periods. You don't need custom functions/loops for this either, that's just overkill.
Nope. Remove the comma.
You can use the string replace method, but not in a one liner as a regexp allows.
while(str.indexOf(',')!=-1)str= str.replace(',','');
parseFloat(str);
Or to make a single expression without a regexp=
return parseFloat(str.split(',').join(''));
I'd use the regexp.
I don't have enough reputation to add a comment, but for anyone wondering on the performance for regex vs split/join, here's a quick fiddle: https://jsfiddle.net/uh3mmgru/
var test = "1,123,214.19";
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var a = parseFloat(test.replace(/,/g,''));
}
var t1 = performance.now();
document.write('Regex took: ' + (t1 - t0) + ' ms');
document.write('<br>')
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var b = parseFloat(test.split(',').join(''));
}
var t1 = performance.now();
document.write('Split/join took: ' + (t1 - t0) + ' ms');
The results I get are (for 1 million loops each):
Regex: 263.335 ms
Split/join: 1035.875 ms
So I think its safe to say that regex is the way to go in this scenario
Building on the idea from #kennebec, if you want to make sure that the commas are correct, and you don't want to replace commas, you could try something like this:
function myParse(num) {
var n2 = num.split(",")
out = 0
for(var i = 0; i < n2.length; i++) {
out *= 1000;
out += parseFloat(n2[i])
}
return out
}
alert(myParse("1,432,85"));
// Returns 1432085, as the comma is misplaced.
It may not be as fast, but you wanted alternatives :)
What about a simple function to solve most of the common problems?
function getValue(obj) {
Value = parseFloat( $(obj).val().replace(/,/g,'') ).toFixed(2);
return +Value;
}
The above function gets values from fields (using jQuery) assuming the entered values are numeric (I rather validate fields while user is entering data, so I know for sure field content is numeric).
In case of floating point values, if well formatted in the field, the function will return a float point value correctly.
This function is far from complete, but it quickly fix the "," (comma) issue for values entered as 1,234.56 or 1,234,567. It will return valid number as far the content is numeric.
The + (plus) sign in front of the variable Value in the return command is a "dirty trick" used in JavaScript to assure the variable content returned will be numeric.
it is easy to modify the function to other purposes, such as (for instance), convert strings to numeric values taking care of the "," (comma) issue:
function parseValue(str) {
Value = parseFloat( str.replace(/,/g,'') ).toFixed(2);
return +Value;
}
Both operations can even be combined in one function. I.e.:
function parseNumber(item,isField=false) {
Value = (isField) ? parseFloat( $(item).val().replace(/,/g,'') ).toFixed(2) : parseFloat( item.replace(/,/g,'') ).toFixed(2)
return +Value;
}
In such case, if function is called result = parseNumber('12,092.98'); it will parse the value as it is a String. But if called as result = parseNumber('#MyField', true); it will try to obtain the value from '#MyField'.
As I said before, such functions are far from complete, and can be expanded in many ways. One idea is to check the first character of the given parameter (string) and decide based on the string format where to obtain the value to be parsed (if 1st character is = '#' then it is an ID from a DOM object, otherwise, if it begins with a number, it must be a string to be parsed).
Try it... Happy coding.