javascriptjqueryregexjquery-mask

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


Solution

  • 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.

    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">