jaridmargolin / formatter.js

Format html inputs to match a specified pattern
http://firstopinion.github.io/formatter.js
2.48k stars 235 forks source link

Incorrect cursor position with multiple patterns #73

Open AlexanderBilichenko opened 9 years ago

AlexanderBilichenko commented 9 years ago

I want to format phone number on input. If I use single 'pattern' option everything is fine. But if I use something like this: 'patterns': [ { '^\d{5}$': '{{9}} {{99}} {{99}}' }, { '^\d{6}$': '{{99}} {{99}} {{99}}' }, { '^\d{7}$': '{{999}} {{99}} {{99}}' }, { '': '{{***}}' } ], 'persistent': false after 5th digit my cursor is not at the end but between 4th and 5th symbol.

scarhand commented 9 years ago

Yeah, I had the same problem with these patterns:

 'patterns': [
                                     { '^\\d{7}$': '{{99}}.{{99}}.{{999}}' },
                                     { '^\\d{9}$': '{{9999}}.{{99}}.{{999}}' },
                                     { '*': '{{9999999999}}' }
                     ]

I replaced the condition in Formatter.prototype._addChar (line 432 in formatter.js)

  if (utils.isBetween(i, [this.sel.begin -1, this.newPos +1]))

with

  if (utils.isBetween(i, [-1, this.newPos +1]))

and that did the trick for me.

Edit: GIven solution does not seem to work when deleting a character after the first group in a pattern.

Edit 2: Ok, it's not the prettiest solution, but it seems to work. I added this code (in addition to the previous modification) at the end of the Formatter constructor and it seems to fix the problem.

if (this.patternMatcher.patterns.length > 1) {
          // Get current state
          this.sel = inptSel.get(this.el);
          this.val = this.el.value;
          // Init values
          this.delta = 0;
          //reset input for each pattern
          for (var i = 0; i < this.patternMatcher.patterns.length; i++) {
              var newPattern = this.patternMatcher.patterns[i];
              this.mLength = newPattern.mLength;
              this.chars = newPattern.chars;
              this.inpts = newPattern.inpts;
              //remove the chars for this pattern
              this._removeChars();
          }
          //we've got a completely unformatted string now, so let's format it
          this._formatValue(true);
      }

Furthermore, I added this to Formatter.prototype._removeChars:

if (pos < this.newPos) {
    this.newPos--;
}

right after shift--;

nesvet commented 9 years ago

+1

nreynis commented 9 years ago

Thank you, this patch works and saved me a lot of time. This should really be ported on the master branch.