Text-mask: Forcing cursor at next available slot

Created on 3 Mar 2018  路  4Comments  路  Source: text-mask/text-mask

Is there a way to for the cursor to be at next available slot?

example:

mask: ['(', /[1-9]/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/]
value: '15'

so it shows: (15 ) - for now

If I focus the input, I'd like to have an option to get the cursor forced at next position (3rd slot), because that's how an <input type="text"> would behave, when you are typing a phone number, you don't really want to type the end first then point back at the start

When using '\u2000' or any other empty char as placeholder, it becomes even more needed

Most helpful comment

A simple workaround would be to execute the following code whenever you want to set the cursor to the end of the user input:

function selectAfterUserInput() {
  let placeholder = '_';
  let i = input.value.indexOf(placeholder)
  if (i === -1) { i = input.value.length; }
  setTimeout(function() { input.setSelectionRange(i, i); }, 0);
}

where input is the HTMLInputElement

The setTimeout is necessary for Chrome and Safari, but not Firefox, as far as I can tell.

Works in Chrome, Firefox, Safari. Haven't tested IE

All 4 comments

We're having the same issue. It causes weird UX issues where users can't type their whole phone number.

It's fixed by turning off guide, but then you can't backspace through special characters, which is more important.

Use this directive on your input :

@Directive({
selector: '[phone]'
})
export class PhoneMaskCursorProcessorDirective {

@HostListener('click', ['$event'])
keypress(event: MouseEvent) {
let input = ( event.target);
input.focus();
if (input.selectionEnd <= 2) {
input.setSelectionRange(2, 2);
} else {
let valueSelected = input.value.substring(0, input.selectionEnd);
let match = valueSelected.match(/\d/gi);
let lastDigitIndexInSelection = valueSelected.lastIndexOf(match[match.length - 1]) + 1;
if (input.value.substring(lastDigitIndexInSelection, lastDigitIndexInSelection + 1).match(/[-\s]/)) {
lastDigitIndexInSelection++;
}
input.setSelectionRange(lastDigitIndexInSelection, lastDigitIndexInSelection);
}
}

}

@Directive({
  selector: '[phone]'
})
export class PhoneMaskCursorProcessorDirective {

  @HostListener('click', ['$event', '$event.target'])
  keypress(event: MouseEvent, target: HTMLInputElement) {
    target.focus();

    if (target.selectionEnd <= 2) {
      target.setSelectionRange(2, 2);
    } else {
      const valueSelected = target.value.substring(0, target.selectionEnd);
      const match = valueSelected.match(/\d/gi);
      let lastDigitIndexInSelection = valueSelected.lastIndexOf(match[match.length - 1]) + 1;
      if (target.value.substring(lastDigitIndexInSelection, lastDigitIndexInSelection + 1).match(/[-\s]/)) {
        lastDigitIndexInSelection++;
      }
      target.setSelectionRange(lastDigitIndexInSelection, lastDigitIndexInSelection);
    }
  }
}

@eleoleeye cleaned it up for you. This should work a lot better.

A simple workaround would be to execute the following code whenever you want to set the cursor to the end of the user input:

function selectAfterUserInput() {
  let placeholder = '_';
  let i = input.value.indexOf(placeholder)
  if (i === -1) { i = input.value.length; }
  setTimeout(function() { input.setSelectionRange(i, i); }, 0);
}

where input is the HTMLInputElement

The setTimeout is necessary for Chrome and Safari, but not Firefox, as far as I can tell.

Works in Chrome, Firefox, Safari. Haven't tested IE

Was this page helpful?
0 / 5 - 0 ratings

Related issues

douglasdtc picture douglasdtc  路  3Comments

gabrielamarques picture gabrielamarques  路  6Comments

LXensen picture LXensen  路  6Comments

ktriek picture ktriek  路  3Comments

badre429 picture badre429  路  3Comments