3

This is simplified of my code:

$("#annual_sales").on('keyup', function () {
    $(this).val( $(this).val().replace(/(\d{3})/g, "$1,") );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />

I'm trying to add a comma after every 3 digits.

The patterns works well here, but as you can see (in the code snippet above) it doesn't work in the JS. Any idea what's wrong?

Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
Shafizadeh
  • 9,960
  • 12
  • 52
  • 89

7 Answers7

2

Doesn't work here since the event fire multiple time, then you need to remove the previous added comma's first every time the event fired and add new ones in the desired positions :

$(this).val().replace(/,/g,'').replace(/(\d{3})/g, "$1,")

** NOTE:** I suggest the use of input event instead since it's more efficient when tracking the use inputs, also you could adjust the regex so the comma will not be added at the end of the line :

/(\d{3}(?!$))/g

$("#annual_sales").on('input', function() {
  $(this).val($(this).val().replace(/,/g, '').replace(/(\d{3}(?!$))/g, "$1,"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />
Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
  • 1
    Glad I could help. – Zakaria Acharki Jun 26 '18 at 14:13
  • 1
    You could also add another negative lookahead to prevent it from adding a comma at the end `/(\d{3}(?!$))/g` – TiiJ7 Jun 26 '18 at 14:50
  • Thanks, @TiiJ7 that is helpful and give us the ability to use `input` event that is more efficient when tracking user inputs... updated my post. – Zakaria Acharki Jun 26 '18 at 14:53
  • If you insert a number anywhere other than at the end, the commas get messed up. I got `112,345,6` when I ran the snippet. – Damian T. Jun 26 '18 at 18:31
  • The question was _I'm trying to add a comma after every 3 digits._ ... So I'm not sure what you mean but `112,345,6` is a valid result and the snippet works fine if you type number in any position... – Zakaria Acharki Jun 27 '18 at 09:10
2

In your current pattern (\d{3}) you add a comma after matching 3 digits and also when there is already a comma following the 3 digits.

What you might do is match 3 digits using a negative lookahead (?!,) to assert what follows is not a comma:

(\d{3}(?!,))

$("#annual_sales").on('keyup', function() {
  $(this).val($(this).val().replace(/(\d{3}(?!,))/g, "$1,"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />

If you don't want the comma at the end of the line you could use an alternation in the negative lookahead that asserts what follows is neither a comma or the end of the line (\d{3}(?!,|$))

$("#annual_sales").on('keyup', function() {
  $(this).val($(this).val().replace(/(\d{3}(?!,|$))/g, "$1,"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
2

Presumably, you want these commas added from the right as a US-style number separator. This code will do that by reversing before and after adding the commas.

var addCommas = s => s.split('').reverse().join('')
    .replace(/(\d{3})/g, '$1,').replace(/\,$/, '')
    .split('').reverse().join('')  // Really want String.prototype.revese!

$("#annual_sales").on('keyup', function () {
    $(this).val( addCommas($(this).val().replace(/\,/g, '')) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />

(Doing the reverses by converting to an array really makes me want a String.prototype.reverse method.)

If you have to support numbers with more than two decimal places, there would have to be additional work on this function.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
1

You need to strip the previously added "," from the value on beforehand like below.

$("#annual_sales").on('keyup', function () {
    $(this).val($(this).val().replace(new RegExp(",", "g"), ""));
    $(this).val( $(this).val().replace(/(\d{3})/g, "$1,") );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />
Discobarry
  • 64
  • 3
  • I ran your snippet and after every three characters it appends a comma, so if you enter `123` you get `123,` and if you enter `123456` you get `123,456,`. – Damian T. Jun 26 '18 at 18:33
0

Honestly, I think the best and most straightforward way to accomplish this is not to rely on directly using regex substitution to add a comma. Because regular expressions run from left to right, and in this case we want to parse from right to left, there's really no easy way to do this.

Instead, I would recommend using javascript to do the heavy lifting:

$("#annual_sales").on('keyup', function () {
    var value = $(this).val();
    var match = value.match(/[0-9,.$]+/);    // Match any chars seen in currency
    var new_value = "";
    if (match) {
        var digits = match[0].match(/\d/g);  // Match single digits into an array
        if (digits.length > 3) {
            for (var i = digits.length - 3; i > 0; i = i - 3) {
                // Start at 3 less than the length,
                // continue until we reach the beginning,
                // step down at intervals of 3

                digits.splice(i, 0, ",");    // Insert a comma
            }
            new_value = digits.join("");
            $(this).val(new_value);
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="annual_sales" type="text" />

With this function, you could expand its handling of currency values, such as prepending the value with a dollar sign, or also splitting on a decimal point and forcing two digits following it.

Edit: Scott's answer is a much shorter version of what I am suggesting here (very nice, by the way).

Damian T.
  • 321
  • 1
  • 10
  • Your snippet doesn't work as expected when I type `1123456` I get `1,123,456` when the question says _I'm trying to add a comma after every 3 digits._ – Zakaria Acharki Jun 27 '18 at 09:14
  • Unless I understood wrong and read too much into what was asked, the "add a comma after every three digits" actually means "comma separator for large numbers". In some countries such as the US, to make large numbers easier to read, a comma is inserted to separate the digits into groups of three, however this is done starting from the least significant place and proceeds to the most significant place. In this case, expected output would be, `123` then `1,234` then `12,345` then `123,456` then `1,234,567`. – Damian T. Jun 27 '18 at 12:52
0

Well, you coul've just use this simple trick :

tooltips: {
    callbacks: {
        label: function(tooltipItem, data) {
            let label = data.labels[tooltipItem.index];
            let value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
            return ' ' + label + ' : ' + value.replace(/(.)(?=(.{3})+$)/g,"$1,");
        }
    }
}
0
$("#digits_to_update").on('keyup', function() {
  $(this).val($(this).val().replace(/(\d{3}(?!,))/g, "$1,"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="digits_to_update" type="text" />`enter code here`
here  '/(\d{3}(?!,))/g, "$1,") ' change the 3 to 4 or 5 it will seperate the number by 4 or 5 too.
behza_d
  • 15
  • 3