-1

I am trying to make a quick function for currency masking without the use of a jquery plugin. The environment I am in is using requirejs and any attempt to add plugins typically results in this problem:

MISMATCHED ANONYMOUS DEFINE() MODULES

Regardless, here is my code below, I am trying to get rid of the 3rd digit after the decimal so that there is only 2 digits after the decimal but for the life me can't figure out why nothing I'm doing is making it go away.

currencyMask("#test");

function currencyMask(fieldID) {
  $(fieldID).on('keypress click', function() {
    if (this.value != '') {
      if (this.value.length == 1) {
        this.value = '0' + this.value
      }
      
      this.value = parseFloat(this.value.replace(/[^\d]/g, '').replace(/(\d\d?)$/, '.$1')).toFixed(2).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,').replace(/(\d{2})(\d$)/, '$1');
    }
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id='test'>
Josh Whitlow
  • 481
  • 6
  • 25
  • so, uhm.. what's this mask supposed to actually do? – Kevin B Aug 21 '19 at 18:58
  • Its supposed to mask a typed number as currency. So that when you start typing 100000, it will automatically format the number as you type to 1,000.00 – Josh Whitlow Aug 21 '19 at 18:59
  • 1
    use keyup instead. – Kevin B Aug 21 '19 at 19:02
  • What makes the whole thing weird is that you're typing at the last position the moment your code does anything to the input because you're entirely replacing the value. – Kevin B Aug 21 '19 at 19:03
  • @KevinB, I modified it so that it starts from the beginning instead of the end. `if (this.value != '' && this.value.length >= 3) { this.value = this.value.replace(/[^\d]/g, '').replace(/(\d{2}$)/, '.$1').replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,'); }` Is that a bit more intelligible? Also, your 'keyup' comment resolved the issue, although I'm not totally sure why. – Josh Whitlow Aug 21 '19 at 19:26
  • My second comment, alludes more to the action of modifying the number after the fact. Regardless of how you change the value, if you're changing it at all while the input is still focused, it impacts the usability of the input because it will change the insertion point in one way or another. I prefer changing it after the fact rather than live as to not interfere with the user's input. for example, on blur. – Kevin B Aug 21 '19 at 19:34
  • I suspect keyup works due to timing related to when the value changes relative to the event occuring. (i'm not entirely sure, which is why i didn't post an answer. Feel free to do so once you've done the research!) – Kevin B Aug 21 '19 at 19:35
  • why not use a simple line: this.value = ParseFloat(\`00${this.value.replace(/[^\d]/g, '')}\`)/100; – Hero Qu Aug 21 '19 at 19:40
  • or... `(+this.value).toFixed(2)`, if you're looking for simple. – Kevin B Aug 21 '19 at 19:43
  • Yes, Kevin B is right. I would edit my suggestion to result in a string: this.value = (ParseFloat('00' + this.value.replace(/[^\d]/g, ''))/100).toFixed(2); ( Get rid of back ticks as they get swallowed in a comment somehow...) – Hero Qu Aug 21 '19 at 19:45

1 Answers1

0

After some discussion, some testing, and a bit of research. I changed my code a bit and resolved the issue as mentioned by Kevin B about keyup vs keypress.

After some research it appears the keypress triggers when "The key is pressed down" while keyup is triggered when "The key is released". -W3 Schools

Because of that, I opted for keyup instead.

In addition, Kevin B said:

What makes the whole thing weird is that you're typing at the last position the moment your code does anything to the input because you're entirely replacing the value.

So I changed the code so that the user is typing at the beginning instead of the end. He also mentioned:

Regardless of how you change the value, if you're changing it at all while the input is still focused, it impacts the usability of the input because it will change the insertion point in one way or another. I prefer changing it after the fact rather than live as to not interfere with the user's input. for example, on blur.

This part here is definitely preference. I brought an admin over to my desk just now and asked which one they liked more. Most of them don't like ones that change after the fact. They find it confusing and to them, the whole point of the currency mask is to clearly see what they are typing as they are typing it.

To be clear, there isn't a 'wrong' way to do it. You can do .blur instead and that works too. This is more about what our specific users prefer.

Here is my updated code below:

currencyMask("#test");

function currencyMask(fieldID) {
  $(fieldID).keyup(function() {
    if (this.value != '' && this.value.length >= 3) {
     this.value = this.value.replace(/[^\d]/g, '').replace(/(\d{2}$)/, '.$1').replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
    }
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id='test'>
Josh Whitlow
  • 481
  • 6
  • 25