4

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>
Community
  • 1
  • 1
akirekadu
  • 2,244
  • 3
  • 24
  • 31
  • Keep count of letter after every key stroke – coder hacker Mar 28 '15 at 01:45
  • 1
    If a user enters 1234567890 and it auto spaces to 12345 67890 and the user goes back and edits the number by adding another 6 at the end of the first grouping should it correct to 12345 6 67890 or 12345 66789 0? – bdrx Mar 28 '15 at 02:57
  • @brdx, if a group is full, adding another digit shouldn't be allowed. I'm thinking this would be the most intuitive (or least confusing) behavior from end user point of view. – akirekadu Mar 28 '15 at 05:13
  • 1
    It sounds like having multiple input boxes each with a 5 digit only validation is more what you want. After all the fields are entered you can just combine them into one string – bdrx Mar 28 '15 at 15:51
  • @brdx, The solution you are suggesting is definitely more flexible and reliable than manipulating text in one input field. I'll write this version and test it out. – akirekadu Mar 29 '15 at 23:39

2 Answers2

10

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

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • 1
    Try typing 123456, it will not print 6 – coder hacker Mar 28 '15 at 01:58
  • Also, inserting a digit to a field that is already full will insert an extra space after that field – akirekadu Mar 28 '15 at 02:02
  • This moves the cursor from the end of the line to before the last character as a person is typing. – bdrx Mar 28 '15 at 03:01
  • Type 111112222233333 (which will correctly displace as 11111 22222 33333), then go to the second group and insert a digit. This will cause a lone 2 to appear between 2nd and 3rd groups. – akirekadu Mar 28 '15 at 05:07
  • Another issue as @bdrx suggested, any editing will send the cursor all the way to the end – akirekadu Mar 28 '15 at 05:08
  • A couple of issues/caveats: 1: this will not allow the user to enter any spaces and will move the cursor forward one character every time spacebar is pressed. 2: If a user backspaces the first character of a word (other than the first) then the cursor will move to the back to the same position since the character before it will be a space. – bdrx Mar 28 '15 at 19:34
  • 1
    @bdrx Thanks for pointing those issues out, I appreciate it. I fixed the second issue and updated my answer. For the first issue, I'm not sure that's worth fixing since the user probably won't have to enter a space since the formatting is already done automatically and they can now go back and edit whatever they typed.. plus this would probably result in stray characters, as [akirekadu pointed out](http://stackoverflow.com/questions/29312719/plain-javascript-or-css-way-to-add-a-space-on-the-fly-after-every-5th-digit-in-i/29312803#comment46820934_29312803). Thanks again! – Josh Crozier Mar 28 '15 at 21:34
  • 1
    The second version works perfect for the solution I needed. Thanks a bunch for the detailed explanation in the answer. – akirekadu Mar 29 '15 at 23:36
0

function myFunction() {
    str = document.getElementById('num').value;

    str=str.replace(/\s/g, '');
    if(str.length%5==0){
    
        document.getElementById('num').value+=" ";
    }
}
<input id='num' type="text" onkeyup="myFunction()">
coder hacker
  • 4,819
  • 1
  • 25
  • 50