Search code examples
javascriptformsmask

How to position the cursor at the beginning of the mask when pushing tab key?


In the form in the phone field, I use a mask based on the Imask library.

  1. I am trying to make it when focusing with both the mouse or the tab on the field, a full mask with brackets appears, and the cursor is set to the initial input position. There is a problem here: either an incomplete mask appears, or only +38, or the cursor moves to the end due to a taboo on the field.
  2. I can't clear the phone field after submitting the form, I get warning:

Element value was changed outside of mask. Syncronize mask using mask.updateValue() to work properly.

const phone = document.querySelector('.phone');
const name = document.querySelector('.name');
const form = document.querySelector('#form');

if (phone) {
  phone.onfocus = () => {
    newIMask(phone)
  }

  form.addEventListener('keydown', function(e) {
    if (e.key == 'Tab') {
      if (phone.value === '') {
        let tabMask = IMask(
          phone, {
            mask: '+38( 000) 000-00-00',
            lazy: false
          });
      }
    }
  });
}

function newIMask(phone) {
  let phoneMask = IMask(
    phone, {
      mask: '{+38} (000) 000-00-00',
      lazy: false
    });
  phone.value = phoneMask.unmaskedValue; //если закомментировать, то по табу курсор сместиться вконец
}

document.getElementById("form").addEventListener('submit', function(e) {
  e.preventDefault();
  phone.value = "";
  window.open('mailto:[email protected]?name=' + name.value + '&body=' + phone.value);
});
<script src="https://unpkg.com/imask"></script>
<form id="form">
  <input type="text" name="name" class="name">
  <input type="tel" name="phone" class="phone">
  <input type="submit" value="Отправить">
  <form>

UPD With this insertion of the code, I sort of solve the issue with the tab

const form = document.querySelector('#form');
    form.addEventListener('keydown', function (e) {
      if(e.key == 'Tab') {
        if(phone.value === '') {
          let tabMask = IMask(
            phone, {
              mask: '+38( 000) 000-00-00',
              lazy: false
          });
        }
      }
    });

but each digit is entered with a warring:

Warring: Element value was changed outside of mask. Syncronize mask using mask.updateValue() to work properly.

and the phone field is not cleared when sending.

Could you help me with finding the right solution?


Solution

  • This warning happens because you need to configure the Imask and inside the configuration have functions which catch input value.

    Use prepare (value, masked) option for preprocessing input and commit (value, masked) option for postprocessing after UI is deactivated

    And for work correctly need only to use mask.updateOptions to update options.

      const phone = document.querySelector('.phone');
      const name = document.querySelector('.name');
      const form = document.getElementById('form');
    
      const maskOptions = {
        mask: '',
        lazy: false,
        placeholderChar: '#',
        overwrite: true,
        prepare: value => value, // onChange event
        commit: value => (phone.value = value), // set value to phone number
      };
    
      // Init IMask
      const mask = IMask(phone, maskOptions);
    
      if (phone) {
        form.addEventListener('keydown', e => {
          if (e.key == 'Tab') {
            // Update options "mask" after pressed Tab key
            mask.updateOptions({
              mask: '{+38}(000)000-00-00',
            });
          }
        });
      }
    
      phone.addEventListener('focus', () => {
        // Update options "mask" after focused
        mask.updateOptions({
          mask: '{+38}(000)000-00-00',
        });
      });
    
      form.addEventListener('submit', e => {
        e.preventDefault();
        console.log('sending phone number ', phone.value);
    
        // Update options & clear up values after submit form
        mask.updateOptions({
          mask: '',
          commit: (value, masked) => {
            value = '';
            masked._value = '';
          },
        });
    
        phone.blur();
        name.value = '';
    
        window.open(
          'mailto:[email protected]?name=' + name.value + '&body=' + phone.value
        );
      });
    <script src="https://unpkg.com/imask"></script>
        <form id="form">
          <input type="text" name="name" class="name" >
          <input type="tel" name="phone" class="phone">
          <input type="submit" value="Отправить">
          <form>