Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plain Javascript way to add a space on the fly after every 5th digit in input field

How can I add a space after every 5th number (as the user types) in input field?

12345 56789 12345 56789

The limitation is that I cannot use any framework like jQuery. This has to be done using plain Javascript or CSS.

I also need to support the ability to hit backspace and correct the number or place cursor anywhere and start correcting with backspace.

The following code is based on the answer here: How to insert space every 4 characters for IBAN registering?

The backspace does not work reliably.

function space(str, after) {
  if (!str) {
    return false;
  }
  after = after || 4;
  var v = str.replace(/[^\dA-Z]/g, ''),
    reg = new RegExp(".{" + after + "}", "g");
  return v.replace(reg, function(a) {
    return a + ' ';
  });
}

var el = document.getElementById('pin');
el.addEventListener('keyup', function() {
  this.value = space(this.value, 4);
});
<form>
  <input autocapitalize="off" autocorrect="off" maxlength=20 type="text" placeholder="type the pin" id="pin" name="pin" />
  <script>
  </script>
</form>
like image 431
akirekadu Avatar asked Feb 11 '23 13:02

akirekadu


1 Answers

Here is a relatively short approach:

Just add an event listener for the input event (or keyup/keydown), and then use some regex.

In the example directly below, all whitespace is initially removed using .replace(/\s/g, ''), and then .replace(/(\d{5})/g, '$1 ') essentially adds a space after every 5th character.

The reason all the whitespace is removed is so that there is always a space between every 5th character (even if you go back and edit previous characters).

document.getElementById('target').addEventListener('input', function (e) {
  e.target.value = e.target.value.replace(/\s/g, '').replace(/(\d{5})/g, '$1 ').trim();
});
<input id="target" type="text"/>

It seems like the only caveat with the approach above is that the caret's position is lost when editing previous characters.

If you want to prevent this, retrieve the caret's current position by accessing the selectionEnd property and then set the caret's position after the regex formatting has been applied.

document.getElementById('target').addEventListener('input', function (e) {
  var target = e.target, position = target.selectionEnd, length = target.value.length;
  
  target.value = target.value.replace(/\s/g, '').replace(/(\d{5})/g, '$1 ').trim();
  target.selectionEnd = position += ((target.value.charAt(position - 1) === ' ' && target.value.charAt(length - 1) === ' ' && length !== target.value.length) ? 1 : 0);
});
<input id="target" type="text"/>

You will notice that there is a slight issue when the character after the caret is a space (because the space wasn't accounted for when initially retrieving the caret's position to begin with). To fix this, the position is manually incremented if the succeeding character is a space (assuming a space was actually added - which is determined by comparing the length before and after replacing the characters).

like image 144
Josh Crozier Avatar answered Feb 13 '23 04:02

Josh Crozier