Giter VIP home page Giter VIP logo

cardjs's Introduction

CardJs

A simple, clean, credit card form for your website. Includes number formatting, validation and automatic card type detection.

View working example >

Example

By Zara 4 image compression service

Installation

  • Bower: bower install card-js --save
  • NPM: npm install card-js
  • Zip: Download

You will need to include both card-js.min.js and card-js.min.css into your web page.

Usage

For working examples of using CardJs, see the examples folder of this project.

Automatic Insertion

Any elements with the class card-js will be automatically converted into a basic credit card input with the expiry date and CVC check.

The easiest way to get started with CardJs is to insert the snippet of code:

<div class="card-js"></div>

Manual Insertion

If you wish to manually alter the fields used by CardJs to add additional classes or set the input field name or id etc, you can pre-populate the form fields as show below.

<div class="card-js">
  <input class="card-number my-custom-class" name="card-number">
  <input class="name" id="the-card-name-id" name="card-holders-name" placeholder="Name on card">
  <input class="expiry-month" name="expiry-month">
  <input class="expiry-year" name="expiry-year">
  <input class="cvc" name="cvc">
</div>

Reading Values

CardJs provides functionality allowing you to read the form field values directly with JavaScript. This can be useful if you wish to submit the values via Ajax.

Create a CardJs element and give it a unique id (in this example my-card)

<div class="card-js" id="my-card" data-capture-name="true"></div>

The javascript below demonstrates how to read each value of the form into local variables.

var myCard = $('#my-card');

var cardNumber = myCard.CardJs('cardNumber');
var cardType = myCard.CardJs('cardType');
var name = myCard.CardJs('name');
var expiryMonth = myCard.CardJs('expiryMonth');
var expiryYear = myCard.CardJs('expiryYear');
var cvc = myCard.CardJs('cvc');

Functions

To call a function on a CardJs element, follow the pattern below. Replace the text 'function' with the name of the function you wish to call.

$('#my-card').CardJs('function')

The functions available are listed below:

Function Description
cardNumber Get the card number entered
cardType Get the type of the card number entered
name Get the name entered
expiryMonth Get the expiry month entered
expiryYear Get the expiry year entered
cvc Get the CVC entered

CardType Function

The cardType function will return one of the following strings based on the card number entered. If the card type cannot be determined an empty string will be given instead.

Card Type
AMEX
Diners
Diners - Carte Blanche
Discover
JCB
Mastercard
Visa
Visa Electron

Static functions

If you just want to perform simple operations without the CardJs form, there are a number of static functions provided by the CardJs library that are made available.

Card Type from Card Number

var cardNumber = '4242 4242 4242 4242'; // Spacing is not important
var cardType = CardJs.cardTypeFromNumber(cardNumber);

Cleaning and Masking

// var formatMask = 'XXXX XXXX XXXX XXXX'; // You can manually define an input mask
// var formatMask = 'XX+X X XXXX XXXX XXXX'; // You can add characters other than spaces to the mask
var formatMask = CardJs.CREDIT_CARD_NUMBER_VISA_MASK; // Or use a standard mask.
var cardNumber = '424 2424242 42   42 42';
var cardNumberWithoutSpaces = CardJs.numbersOnlyString(cardNumber);
var formattedCardNumber = CardJs.applyFormatMask(cardNumberWithoutSpaces, formatMask);

Masks

Variable Name Mask
CardJs.CREDIT_CARD_NUMBER_DEFAULT_MASK XXXX XXXX XXXX XXXX
CardJs.CREDIT_CARD_NUMBER_VISA_MASK XXXX XXXX XXXX XXXX
CardJs.CREDIT_CARD_NUMBER_MASTERCARD_MASK XXXX XXXX XXXX XXXX
CardJs.CREDIT_CARD_NUMBER_DISCOVER_MASK XXXX XXXX XXXX XXXX
CardJs.CREDIT_CARD_NUMBER_JCB_MASK XXXX XXXX XXXX XXXX
CardJs.CREDIT_CARD_NUMBER_AMEX_MASK XXXX XXXXXX XXXXX
CardJs.CREDIT_CARD_NUMBER_DINERS_MASK XXXX XXXX XXXX XX

Card Expiry Validation

The expiry month can be in the range: 1 = January to 12 = December

var month = 3;
var year = 2019;
var valid = CardJs.isExpiryValid(month, year);

The expiry month and year can be either and integer or a string.

var month = "3";
var year = "2019";
var valid = CardJs.isExpiryValid(month, year);

The expiry year can be either 4 digits or 2 digits long.

var month = "3";
var year = "19";
var valid = CardJs.isExpiryValid(month, year);

License

CardJs is released under the MIT license. View license

cardjs's People

Contributors

colin-stannard avatar ghoofman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cardjs's Issues

NPM support

Would be nice to have native NPM support in addition to Bower. :)
It should only take a couple of minutes to submit, and card-js is available.

this.initCardNumberInput is not a function

I am using this in a form which is loaded dynamically via ajax. The associated scripts are also loaded along with the form (not in the <head>. This works fine on a fresh page load but not dynamically where I get the error:

TypeError: this.initCardNumberInput is not a function[Learn More]

Simply moving:

$(function(){$(".card-js").each(function(i,obj){$(obj).CardJs()})})

to the end of the minified file fixes the issue:

Can you shed light on why this is? Is there any reason why it's being called up front instead of afterward?

"Visa Electron" card type detection.

I've come across a slight issue in the card-js.js file that I'd like to call to your attention. Specifically, in the cardTypeFromNumber function, beginning at line 394.

The very first conditional statement that matches Visa will break the procedural flow out of the function, returning "Visa". The interpreter will never get down to lines 432-434 where the "Visa Electron" card is identified, as the previous regular expression pattern has already been matched.

I would recommend moving the "Visa Electron" check before the more generic "Visa" check, which would then function as more of a catch-all.

Using credit cards stored on the browser doesn't work

When using one of the credit cards stored on the browser
image
Is not changing the values for expiry_month and expiry_year
image
You need to type them in order to get these values assigned
image
Therefore when using a saved credit card to auto-fill the fields is not working, because on the back-end we are getting empty values for expiry_month and expiry_year. Please suggest us a workaround for this or update the library to handle this situation.
Thanks!

CardJs should check if it's already initialized on an element

I'm using cardjs with angular 1.x, and because ui-router renders the template after cardjs checks for the elements, it won't initialize the form if coming from another route.

I'm manually calling $(element).CardJs() to initialize the form, but if I navigate directly to the route, CardJs is loaded before angular, and the form is initialized twice, causing double keystrokes for each card number. So, I'm doing this:

if (!$el.data("cardjs"))
    $el.CardJs();

But this is kind of a private api. I propose CardJs should either be idempotent, and make sure that multiple calls to init only initialize the same element once, or have an alternate method we can call like $.CardJs('ensureInit') that makes this check internally.

Different card formatting mask for Amex

Hi,
nice job on this little library. Easy to use and no major issues so far ๐Ÿ˜Ž

I noticed that Amex wants to be extra special and has a different card pattern (4-6-5) - as does Diners Club (4-4-4-2) but that works with the standard mask. See https://stripe.com/docs/testing#cards

Would be nice if the mask would automatically change based on the detected type, probably quite easy to do.

What do you think?

Diners - Carte Blanche card detection

Diners - Carte Blanche cards never will be matched, because Diners's regExp will match that.

CardJs.cardTypeFromNumber = function(number) {
...
// Diners
re = new RegExp("^(30|36|38)");
if (number.match(re) != null)
return "Diners";

// Diners - Carte Blanche
re = new RegExp("^30[0-5]");
if (number.match(re) != null)
return "Diners - Carte Blanche";
...
};

How do i delete expiry date from input

hi,

For my application expiry inputs need to be modified.
How am i able to remove them from the inputs of cardjs?
Or can i make expiry-month and expiry-year in one input?

regards,
Jesper

Customize expiry fields

As per docs:

          <div class="modal-content card-js">
            <input class="card-number" name="own-name">
            <input class="expiry form-control"
                   autocomplete="off"
                   required>
            <input class="expiry-month" name="my-expiry-month__card-expiry-month">
            <input class="expiry-year" name="my-expiry-year__card-expiry-year">
            <input class="cvc" name="my-cvc">

card-number field and cvc field names are customized. However, expiry params are send as expiry-month and expiry-year

Change events doesn't work on fields

Awesome library, really love how clean and slick it is, just come across one problem that's all!

It looks like your library takes control of the .change, .keyup, .keydown events as when I try to update a custom input field when there has been a change in the card-number input field for example, it doesn't work at all.

I used this bit of code in Example 4 of your examples:

$("#card-number-1").change(function() {
        console.log("Hello World!");
      });

So in theory, should spit out the logging in console but does absolutely nothing.

I think lines 916-922 is the issue:

this.cardNumberInput.keydown(function(e) {
    CardJs.handleCreditCardNumberKey(e, $this.creditCardNumberMask);
  });
 this.cardNumberInput.keyup(function(e) {
    $this.refreshCreditCardTypeIcon();
  });
 this.cardNumberInput.change(CardJs.handleCreditCardNumberChange);

Not sure how to work around this.

Autofill

When I autofill with Safari or LastPass and attempt to edit the card number and press the backspace key at the end of the number, it will delete the first number in the fourth number set in the case of a Visa.

Browsers tested: Safari and Chrome with latest version of CardJS

Thanks!

name of expiry month and year not changing

Hi,

I have the following, but field names submitted are always expiry-month and expiry-year:

<div class="card-js form-group">
<input class="card-number form-control" name="card_number" autocomplete="off" required>
<input class="name form-control" id="the-card-name-id" name="card_name" placeholder="Name on card" autocomplete="off" required value="[% c.user.cn %]">
<input class="expiry-month form-control" name="card_expiry_month" autocomplete="off" required>
<input class="expiry-year form-control" name="card_expiry_year" autocomplete="off" required>
<input class="cvc form-control" name="card_cv2" autocomplete="off" required>
</div>

Billing Zipcode?

Why is there no field automatically for billing zipcode... even strip requires it... just curious.

NPM previous problem

I've met the issue stated here:
#34
when using version from npm. Could that happen that npm has outdated js? When I'm using the package installed from git directly - problem goes away

check expire year

Perfect project,

Please add a function to check if the expire-cc-year < 2016
for example : if I put 03/2015 (this is not correct year beacause we have 2016 today)

Why we have a jQuery post function with url https://cardjs.co.uk/beacon in your card-js.min.js

Best regards

Support for WordPress

In case anyone is using this library for a WordPress website, keep in mind you will get the $ is not a function runtime error when attempting to enqueue the card-js.min.js file.

A quick workaround is to include the var $j = jQuery.noConflict(); and find/replace instances of $ with $j. However, I would prefer not to edit the min.js file for use on my website. So, I didn't know if repo maintainers were aware of this?

(Also, this would be good to know in case your file is hosted on a CDN anywhere, which I did not find in a quick search.)

Mobile Support?

The Month & Year Fields do not work on mobile (android)

I'm going about replacing with two drop down lists

Credit Card and Expiry Mask broken on Android 6 and 7 Samsung devices

I saw some cannot preventDefault on passive event listener warnings when debugging the device remotely in chrome. The Mask formatting on the credit card and the expiry field does not work when entering the numbers but formatting does happen when pressing backspace. The expiry field does not populate the underlying expiry year input.

This issue affected did not affect a lollipop device that I tested on but it did affect an android 6 and android 7 device - android 6 and 7 emulators was not affected.

Form Validation?

Love the design.

Just wondering if there's (or a way to add) a function to check that all fields are valid, before form submission?

Example:

$("form").submit(function(e) {
  e.preventDefault();
  var myCard = $('.card-js');

  if (myCard.validate()) {
    var cardNumber = myCard.CardJs('cardNumber');
    var cardType = myCard.CardJs('cardType');
    var name = myCard.CardJs('name');
    ...
  }
});

credit card validation in android 10 version on a real device

i am able to fill the card details but its not submitting successfully giving some weird error can you guys help me on this.
Error msg is"Expiration date must be greater or equal to current month/year".I m getting this error msg only in android 10

Needs better readme file!

Its a bit difficult to understand how to start using this. Would be help full if the docs are updated.

initNameInput overwrites captureName setting

You've got:

this.captureName = this.elem.find(".name")[0] != null;

Therefore, if the input element doesn't exist the captureName setting gets set to false and breaks the data-capture-name attribute.

Not supporting angularjs

I have imported plugin to my angualr project and it does not work at all and also dont give any erros. Any perticular configurations i m missing.

Fails to Format Date on Specific Browsers

Hello,

We are encountering an issue were the date is not being formatted correctly and is triggering an invalid state. The user will enter 1224 and it does not reformat it to 12 / 24. This then triggers and invalid field warning and prevents the user from purchasing.

We have documented 50 errors in the past 30 days. Below is a screen grab of the input field and a sample list of the environment.

Screen grab of formatting failure:
https://www.screencast.com/t/QpSWF4gQ7i5

Sample of OS / Browser / Device

Chrome Mobile 61
Operating System Android 6
Device Mobile:LG Escape 3

Safari 10
Operating System macOS 10
Device Desktop/Laptop:Apple Macintosh

Kindle-Silk 58
Operating System Android 5
Device Tablet:Amazon Fire HD 8

Chrome Mobile 61
Operating System Android 7
Device Mobile:LG Stylo 3 LTE

How to retrieve data from the fields?

The documentation shows how to "start" using it, but doesn't show how to complete the process. It seems that it solely relies on form submission to transfer the data... this would be helpful to be documented. I looked into the source code, and there doesn't seem to be any methods that "get" the data from the fields for an AJAX post.

Confirm good number

After typing 4111 1111 1111 1111 there should be some visual indication that this number is good

Safari expiry bug

In Safari 5.7 "08/20" is incorrectly highlighted red as an invalid card expiry.

Thank you to Dan who emailed me about this bug.

How hidden the input for year and month

How hidden the input for year and month

I wanna delete this

                    <input class="expiry-month" id="expiration-date" name="expireMonth">
                    <input class="expiry-year" id="expiration-date" name="expiryYear">

But is impossible

Month and Year input field name attribute

When doing a "manual insertion" of individual input fields as outlined in the README, the new hidden input fields that are created to handle Month and Year data do not inherit the name attribute. Per lines 1061-1062 the original elements are simply overwritten with hidden fields that have their names hard-coded.

This causes potential mismatch when handling input from clients who have JavaScript disabled.

One possible solution is to check if the initialized expiryMonthInput and expiryYearInput objects have a non-empty name attribute already set and simply pass it to the new hidden element.

if ( this.expiryMonthInput.attr("name") ) {
  // inherit the existing "name" attribute.
  this.expiryMonthInput = $("<input type='hidden' />").attr("name", this.expiryMonthInput.attr("name"));
} else {
  // just in case it hasn't already been set.
  this.expiryMonthInput = $("<input type='hidden' name='expiry-month' />");
}

if ( this.expiryYearInput.attr("name") ) {
  // inherit the existing "name" attribute.
  this.expiryYearInput = $("<input type='hidden' />").attr("name", this.expiryYearInput.attr("name"));
} else {
  // just in case it hasn't already been set.
  this.expiryYearInput = $("<input type='hidden' name='expiry-year' />");
}

Alternatively, since the input elements have already been initialized by the initExpiryMonthInput and initExpiryYearInput methods, just changing their type to "hidden" would also do the trick. Of course, this assumes that they're valid input elements. There's also the chance that the existence of any other attributes (class, placeholder, etc.) may cause issues down the line. I definitely like the idea of keeping hidden fields as sterile as possible.

this.expiryMonthInput.attr("type", "hidden");
this.expiryYearInput.attr("type", "hidden");

Or you could leverage the copyAllElementAttributes method that you've already written and have used higher up for the DROPDOWN style month and year picker.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.