maska icon indicating copy to clipboard operation
maska copied to clipboard

masked method work incorrectly with unmasked results

Open le0pard opened this issue 1 year ago • 16 comments

Describe the bug

All inputs have activated number mask with local pt-BR. Last input calculate sum for all other inputs and have mask too:

const mask = new Mask({ number: { locale: 'pt-BR', fraction: 2 } })
const totalAmount = Array.rom(document.querySelectorAll('.inputs')).reduce((agg, target) => {
  const value = target.value ? parseFloat(mask.unmasked(target.value.toString())) : 0

  return agg + (isNaN(value) ? 0 : value)
}, 0)
document.querySelector('.totalInput').value = totalAmount.toString()
document.querySelector('.totalInput').dispatchEvent(new Event('input', { bubbles: true })) // trigger mask.js

This lead that number incorrectly masked in total field. Instead of 10.34 it get 1034. So this mean:

mask.masked(mask.unmasked('10.234,54')) !== '10.234,54'

Steps to reproduce

const { Mask } = Maska;

const mask = new Mask({ number: { locale: 'pt-BR', fraction: 2 } })
console.log('correct', mask.unmasked('10.234,54')) // correct 10234.54
console.log('incorrect', mask.masked('10234.54')) // incorrect 1.023.454 (should be "10.234,54")
console.log('incorrect', mask.masked(mask.unmasked('10.234,54')), '!==', '10.234,54')

Reproduction link

Example

le0pard avatar Nov 27 '24 16:11 le0pard

https://github.com/beholdr/maska/issues/225 - If I understand correctly, in both cases, the masked handles the float attribute value as an integer: what is incorrectly or not expected.

rozsazoltan avatar Nov 27 '24 16:11 rozsazoltan

question here: should mask.masked(mask.unmasked(a)) === a or we should expect non deterministic results?

@rozsazoltan - it is number (float), not integers. and it lost fraction

le0pard avatar Nov 27 '24 16:11 le0pard

I think problem, that for mask.masked it should not expect value in opts.locale, but in locale, which it did mask.unmasked, which looks like en

le0pard avatar Nov 27 '24 16:11 le0pard

Yes, it's a known issue with some locales. You can pass initially formatted value as a workaround:

mask.masked(Intl.NumberFormat({ locale: 'pt-BR' }).format(10234.54)) // = 10.234,54

beholdr avatar Nov 27 '24 18:11 beholdr

Yes, but why mask.masked(mask.unmasked(a)) === a non deterministic? If you return unmasked in locale, which you not expect to handle in masked, this mean logic is incorrect.

le0pard avatar Nov 27 '24 18:11 le0pard

const mask = new Mask({ number: { locale: 'pt-BR', fraction: 2 } })

Intl.NumberFormat('pt-BR').format(10234.54) // 10.234,54
mask.masked('10.234,54') // 10.234,54 - same, just waste cpu time

as I understand, expectation:

const number = 10223.34
const numberAsStr = number.toString() // '10223.34'
mask.masked('10223.34') // should return '10.223,34', but not working
mask.unmasked('10.223,34') // should return '10223.34', so parseFloat('10223.34') => 10223.34

and this is not happening now

le0pard avatar Dec 03 '24 12:12 le0pard

Yeah, it’s currently not working with locales that have dot as separator. 10223.34 is not the same as 10.234,54 that’s why I suggest to pass value pre-formatted with Intl.NumberFormat.format()

If you have a universal solution for parsing all locales, PR are welcome.

beholdr avatar Dec 05 '24 18:12 beholdr

@beholdr I think stuff like "parsing" and "formating" need to be split, so parsing can work with normal numbers (not only based on locale), while "formating" do format based requested locale

le0pard avatar Dec 05 '24 22:12 le0pard

@le0pard I agree with that, but it’s more complicated. Problem is not to parse a correctly formatted number like 10.234,56. Problem is to parse a partially formatted number, like you have 10.234,56 and then press a backspace and get 10.234,5 which you should parse to correct float. I just couldn't solve this case at the time.

beholdr avatar Dec 06 '24 09:12 beholdr

Hey @beholdr I saw you ran a quick root cause analysis. Would you be open to a contribution with a possible fix?

arthurgousset avatar May 31 '25 10:05 arthurgousset

@arthurgousset yes, of course. Unfortunately, I don't have time for deep analysis right now. But if you can solve this issue, it will be cool.

beholdr avatar Jun 06 '25 06:06 beholdr

@beholdr Unfortunately it looks like this is a larger design question. Our tool (workback.ai) works best with self contained, well defined bugs. Are there any such bugs you'd welcome a contribution for?

arthurgousset avatar Jun 06 '25 22:06 arthurgousset

works best with self contained, well defined bugs

in this case for now it useless, because such task can do even beginner developer :)

le0pard avatar Jun 06 '25 22:06 le0pard

such task can do even beginner developer

That's a great point @le0pard, would you say all self-contained bugs are successfully resolved by junior developers in repos you work in?

arthurgousset avatar Jun 06 '25 23:06 arthurgousset

yes

le0pard avatar Jun 06 '25 23:06 le0pard

That's awesome, sounds like you are on top of your game in the repos you work in!

arthurgousset avatar Jun 06 '25 23:06 arthurgousset