1

I am trying to format credit cards as users type them into the field. I've read every topic on the subject here on stack overflow, looked at tons of sites, lots of libraries and the code behind them. I want to create a simple function that will format credit cards as the user types them into the field using VANILLA JAVASCRIPT. Some of the following code comes from topics found here on Stack Overflow but none of the threads have solved the particular problem of doing this as the user is typing into the field.

PROBLEM: By default as the user is typing the into the given credit card field it changes the value by putting spaces in between the numbers, it will not validate as an American Express card until all the digits have been entered and thus not adjust the format until it is complete. I've tried casting the value without spaces and retesting it every cycle but to no avail.

function cc_format(v) {
        //Strip the field value of spaces.
        amextest = v.replace(/\s/g, '');
        //Test if the card is an american express each cycle
        if(/3[47]\d{2}[ -]*\d{6}[ -]*\d{5}/.test(amextest))
        {
         //This is some borrowed code to format american express cards - http://stackoverflow.com/questions/27322733/javascript-regex-format-string-containing-american-express-card-number
            v.replace(/\b(\d{4})(\d{6})(\d{5})\b/, '$1-$2-$3');
            return v;
        }
        else 
        {
           //This properly formats every other card type as its being typed.
            var v = v.replace(/[^\d]/g, '').match(/.{1,4}/g);
            return v ? v.join(' ') : '';
        }
    }

    //This binds the function to an input
    document.getElementById('credit_card').oninput = function() {
        this.value = cc_format(this.value)
    }

I call upon the gods of stack overflow, please help me put this rest once and for all!

Nicholas Koskowski
  • 793
  • 1
  • 4
  • 23
  • 1
    Just check the first two digits. If it's `34` or `37` use the Amex format, otherwise use the standard format. – Barmar Nov 16 '16 at 23:20

1 Answers1

2

EDIT: Forgot the OP wanted plain JS. I'll leave this here for posterity, but it is obviously not an answer.

You could try this - match on the first two digits, and then automatically update the input after the 4th digit (and prevent an input greater than 17 characters (15 digits and 2 dashes):

$('#cc').on('keyup', function() {
  var amexTest = $(this).val().replace(/ /g, '');
  if (amexTest.match(/^3[47]\d{2}/)) {
    if (amexTest.length == 4) {
      amexTest += '-';
      $('#cc').val(amexTest);
    }
    if (amexTest.length == 11) {
      amexTest += '-';
      $('#cc').val(amexTest);
    }
    if (amexTest.length > 17) {
      val = $(this).val().substr(0, $(this).val().length - 1);
      $(this).val(val);
    }
  } else {
    if (amexTest.length > 16) {
      val = $(this).val().substr(0, $(this).val().length - 1);
      $(this).val(val);
    }
    if (amexTest.length == 16) {
      var splits = amexTest.match(/\d{4}/g);
      val = splits.join(' ');
      $(this).val(val);
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="cc">
sideroxylon
  • 4,338
  • 1
  • 22
  • 40
  • This is close to what I'm looking for, it's not perfect but I'm working off of it.. so props! Any chance you could include the other formatting case? I've tried adapting it into this so far but it's producing weird behavior adding commas into every other card type. – Nicholas Koskowski Nov 17 '16 at 00:19
  • $('#credit_card').on('input', function() { var amexTest = $(this).val().replace(/ /g, ''); if (amexTest.match(/^3[47]\d{2}/)) { if (amexTest.length == 4) { amexTest += '-'; $(this).val(amexTest); } if (amexTest.length == 11) { amexTest += '-'; $(this).val(amexTest); } if (amexTest.length > 17) { val = $(this).val().substr(0, $(this).val().length - 1); $(this).val(val); } } else { var v = $(this).val().replace(/[^\d]/g, ' ').match(/.{1,4}/g); v ? v.join(' ') : ' '; $(this).val(v); } }); – Nicholas Koskowski Nov 17 '16 at 00:21
  • Updated to add space after every 4th number in a non-amex card. – sideroxylon Nov 17 '16 at 01:30