Rob Owl Rob Owl - 1 month ago 11
Javascript Question

Card Number Regex and caret/cursor position (javascript)

I have a regex to split out a credit card number in to 4 groups of 4 digits.

The Regex works a treat but if I want to go back in to the string and edit it the cursor jumps to the end of the selection.

<input id= "cardNumber" maxlength="19" type="tel"/>


JS as follows:

document.getElementById('cardNumber').addEventListener('input', function (e) {

var field = e.target;

field.value = field.value.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim();

});


Obviously I don't want the cursor to jump to the end of the entry. I've been playing around with caret positions, selectionStart and End but no luck so far.

Any pointers much appreciated.

see jsfiddle here: https://jsfiddle.net/oo7Ljm4j/1/

Answer

OK so after some digging I found the answer!

By making use of field.selectionEnd and resetting this on every (on)input it keeps the cursor where you want it for editing.

The problem stems from the fact that the regex will re-render and update the ENTIRE field when you make a change to it (so, obviously, the cursor then defaults to the end of the value when the regex fires as the browser thinks you're finished every time.)

  document.getElementById('cardNumber').addEventListener('input', function (e) {

  var field = e.target, position = field.selectionEnd, length = field.value.length;


  field.value = field.value.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim();


  field.selectionEnd = position += ((field.value.charAt(position - 1) === ' ' && field.value.charAt(length - 1) === ' ') ? 1 : 0);    
});

This way we're telling the cursor to recalculate it's selectionEnd position on every input.

Check out the working JSFiddle aqui: https://jsfiddle.net/oo7Ljm4j/6/