baldr
baldr

Reputation: 2999

jQuery Mask Plugin: mask for negative integers

I am using jQuery Mask Plugin in my web project. It is used widely and I don't want to change it for now.

I use the following mask for the numbers with decimal separators:

For example for the element:

<input class="number-field" value="123456">

I use the following mask:

$('input.number-field').mask('#,##0', {'reverse': true});

It works for positive numbers, but now I would like to add support of negative numbers.

Neither of the following patterns work:

$('input.number-field').mask('#,##0Z', {
  reverse: true,
  translation: {
    'Z': {
      pattern: /\-?/
    }
  }
})

$('input.number-field').mask('Z#,##0', {
  reverse: true,
  translation: {
    'Z': {
      pattern: /\-?/
    }
  }
})

$('input.number-field').mask('Z#,##0', {
  reverse: true,
  translation: {
    'Z': {
      pattern: /-/,
      optional: true
    }
  }
})

Last one seems working, but only for 4 digits in the line.

How can I use this plugin for negative numbers? I may consider even patching this plugin if someone can propose an idea.

You can try it with jsFiddle template

Upvotes: 6

Views: 20261

Answers (6)

Heitor Marcos
Heitor Marcos

Reputation: 61

In my case i needed the thousands separator to be a

,

and the decimal to be

.

I also wanted to be able to set the value to negative any time. and if the value already in the input before pressing minus was 12 i wanted it to result in -12 and so on.

In the end i ended up with

    function DecimalMaskPTBR(element) {
      element.mask("#.##X,XX", {
        reverse: true,
        translation: {
          "#": {
            pattern: /-|\d/,
            recursive: true
          },
          "X": {
            pattern: /-|\d/,
            recursive: false
          }
        },
        onChange: function(value, e) {
          var target = e.target,
            position = target.selectionStart; // Capture initial position
          if (value.length > 1 && e.originalEvent && e.originalEvent.data == "-") {
            value = value.replace(/-/g, '').replace(/\./g, '');
            var decimalpos = value.length - value.indexOf(',');
            if (value.length > 1 && decimalpos == 2) {
              var pos = value.length - 3;
              value = value.replace(/,/g, '');
              value = value.substring(0, pos) + "," + value.substring(pos);
            }
            target.value = value;
            target.selectionEnd = position;
            value = target.value = "-" + element.masked(target.value);
          }
          target.value = value.replace(/^-,/, '-').replace(/^-\./, '-').replace(/(?!^)-/g, '');
          target.selectionEnd = position; // Set the cursor back to the initial position.
        }
      });
    }
    $(function() {
      DecimalMaskPTBR($('.number-field'));
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://igorescobar.github.io/jQuery-Mask-Plugin/js/jquery.mask.min.js"></script>
<input class="number-field" value="-123456">

Fiddle

I based my solution on what @Josh Crozier had already done in his answer

Upvotes: 1

Airton J. Colombini
Airton J. Colombini

Reputation: 609

/* For negative decimal values */

$('.money').mask("#.##0,00", {
  reverse: true,
  translation: {
    '0': { pattern: /\d/ },
    '#': {
      pattern: /\-|\d/, /*signal included*/
      recursive: true
    },
  }
});

Upvotes: 0

ozn
ozn

Reputation: 3

If callback doesnt work you can

$(this).find("td.selling").each(function (i, element) {
        $(element).unmask().mask('###.###.###.###.###.###.###.###', {
            reverse: true,
            translation: {
                '#': {
                    pattern: /\-|\d/,
                    recursive: true
                }
            },
        });
        $(element).text($(element).text().replace('-.', '-'));
       
    });

Upvotes: 0

You can do this way:

$('#input').mask('000.000,00', {
            reverse: true,
            translation: { 
                '0': {
                    pattern: /-|\d/,
                    recursive: true
                }
            },
onChange: function(value, e) {
    e.target.value = value.replace(/^-\./, '-').replace(/^-,/, '-').replace(/(?!^)-/g, '');
    }
});

If you use de charactere #, you can not initialize number with - therfore use 0 to translation

  1. value.replace(/^-\./, '-') This will change string like -. to -
  2. replace(/^-,/, '-') This will change string like -, to -
  3. replace(/(?!^)-/g, '') This will remove charactere - that are not at the beginning of the line

Upvotes: -1

Filipe Mendes
Filipe Mendes

Reputation: 185

Just choose a character to translate signal, im my case Z.

$("#input").mask("Z0999999.00", {

   translation: {
     '0': {pattern: /\d/},
     '9': {pattern: /\d/, optional: true},
     'Z': {pattern: /[\-\+]/, optional: true}
   }

});

And put the mask on input.

<input id="input"/>

Upvotes: 3

Josh Crozier
Josh Crozier

Reputation: 240888

I expanded off of your last attempt and translated the special # character to recursively accept digits and dashes (i.e., /[\d-]/). Then I changed the masking pattern to #,##0.

Since the plugin doesn't allow you to add negative/positive lookaheads in the regular expression pattern, I added an onChange callback to prevent - characters from being anywhere but the beginning of the string.

  • .replace(/(?!^)-/g, '') - This will remove all of the - characters that are not at the beginning of the line.
  • .replace(/^,/, '') - This will remove leading , characters (i.e., it would remove the , from a string like ,123).
  • .replace(/^-,/, '-') - This will remove , characters directly following - characters (i.e., it would remove , from -,123).

Updated Example

$('input.number-field').mask('#,##0', {
  reverse: true,
  translation: {
    '#': {
      pattern: /-|\d/,
      recursive: true
    }
  },
  onChange: function(value, e) {      
    e.target.value = value.replace(/(?!^)-/g, '').replace(/^,/, '').replace(/^-,/, '-');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.13.4/jquery.mask.min.js"></script>
<input class="number-field" value="123456">

Additionally, if you want to prevent the cursor indicator from jumping to the end of the string when replacing the characters, you could leverage the code from my other answer here.

$('input.number-field').mask('#,##0', {
  reverse: true,
  translation: {
    '#': {
      pattern: /-|\d/,
      recursive: true
    }
  },
  onChange: function(value, e) {
    var target = e.target,
        position = target.selectionStart; // Capture initial position

    target.value = value.replace(/(?!^)-/g, '').replace(/^,/, '').replace(/^-,/, '-');

    target.selectionEnd = position; // Set the cursor back to the initial position.
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.13.4/jquery.mask.min.js"></script>
<input class="number-field" value="123456">

Upvotes: 12

Related Questions