Reputation: 1585
I'm using the following JavaScript + Regex to auto add commas to a user input as they type:
$('input.number').keyup(function(event) {
// skip for arrow keys
if(event.which >= 37 && event.which <= 40) return;
// format number
$(this).val(function(index, value) {
return value
.replace(/[^-\d.]/g, "")
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
;
});
});
This works great, but it does not work for decimals. It adds commas to the decimals, which I don't want.
I could update the code to do a check to see if there are commas after the decimal. However, I think there may be a more elegant solution with Regex.
$('input.number').keyup(function(event) {
// skip for arrow keys
if(event.which >= 37 && event.which <= 40) return;
// format number
$(this).val(function(index, value) {
var num = value
.replace(/[^-\d.]/g, "")
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
var numSplit = num.split('.');
if(numSplit.length > 1){
num = numSplit[0] + '.' + numSplit[1].replace(/,/g, "");
}
return num;
});
});
I've tried adding a check to first see if a .
exists. But I did not write it correctly.
\B(?=[^.](\d{3})+(?!\d))
Is there a better way to do this with regex?
https://codepen.io/anon/pen/gNOgMm
Upvotes: 1
Views: 156
Reputation: 20039
Apply Regex only to the whole number
$('input.number').keyup(function(event) {
// skip for arrow keys
if (event.which >= 37 && event.which <= 40) return;
// format number
$(this).val(function(index, value) {
var num = value
.replace(/[^-\d.]/g, "")
var numSplit = num.split('.');
if (numSplit.length > 1) {
num = numSplit[0]
.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '.' + numSplit[1].replace(/,/, "");
} else {
num = num.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}
return num;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<input class="number">
Shorter Version
$('input.number').keyup(function(event) {
// skip for arrow keys
if (event.which >= 37 && event.which <= 40) return;
// format number
$(this).val(function(index, value) {
var num = value
.replace(/[^-\d.]/g, "")
.replace(/^\.+/g, "")
.replace(/\./, "x").replace(/\./g, "").replace(/x/, ".")
return (/^\d+\.\d+$/.test(num))
? num.replace(/(\d)(?=(\d{3})+(?:\.\d+)$)/g, "$1,")
: num.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<input class="number">
Upvotes: 1
Reputation:
So, with a simple replace callback you can match the decimal part
then just return it, or match the assertion for a thousands place
then return ,
.
No need to split, it just makes it more complicated.
Since you're using regex, do it all with regex.
The regex expanded:
( \. \d* ) # (1), Decimal part
| # or,
\B # Thousands part
(?=
(?: \d{3} )+
(?! \d )
)
var input = "122341234.188874";
input = input.replace (/[^-\d.]/g, "" );
input = input.replace (/(\.\d*)|\B(?=(?:\d{3})+(?!\d))/g,
function( m, g1 ) // match, group 1
{
if ( g1 > "" )
return g1;
else
return ",";
}
);
console.log(input);
Another thing you may want to consider is to validate the
form after stripping invalid characters.
I believe you could do that with a
replace (/^(?:.*?(-?(?:\d+(?:\.\d*)?|\.\d+))|).*$/g, "$1" );
Upvotes: 0