JSFiddle - React, Tailwind, and code Playground
by jolleekin
HTML
<div>Format a credit card number as chunks of four digits depending on its cart type. The caret is handled correctly.</div>
<input type=text />
<div id=cardName></div>
CSS
body {
font: 15px/1.3333 'Segoe UI', 'Open Sans', sans-serif;
zoom: 2;
}
input {
width: 100%;
}
JavaScript
var input = document.querySelector('input');
var cartTypes = [{
'code': 'AMEX',
'name': 'American Express',
'startDigits': '34',
'length': 15,
'format': [4, 6, 5]
}, {
'code': 'VISA',
'name': 'Visa',
'startDigits': '4',
'length': 16,
'format': [4, 4, 4, 4]
}
];
input.onkeyup = function (e) {
if (this.value == this.lastValue) return;
var caretPosition = this.selectionStart;
var sanitizedValue = this.value.replace(/[^0-9]/gi, '');
var parts = [];
var cartType;
for (var i = 0, len = cartTypes.length; i < len; i++) {
if (sanitizedValue.indexOf(cartTypes[i].startDigits) == 0) {
cartType = cartTypes[i];
break;
}
}
cardName.textContent = cartType ? cartType.name : '';
if (!cartType) return;
if (sanitizedValue.length > cartType.length) {
sanitizedValue = sanitizedValue.substr(0, cartType.length);
}
for (var i = caretPosition - 1; i >= 0; i--) {
var c = this.value[i];
if (c < '0' || c > '9') {
caretPosition--;
}
}
var j = 0;
var dp = 0;
for (var i = 0, len = sanitizedValue.length; i < len;) {
var partLength = cartType.format[j];
parts.push(sanitizedValue.substring(i, i + partLength));
i += partLength;
if (caretPosition >= i) dp++;
j++;
}
caretPosition += dp;
this.value = this.lastValue = parts.join(' ');
this.selectionStart = this.selectionEnd = caretPosition;
}
input.focus();