Skip to content

Commit

Permalink
[Issue-8] Add credit card type detect event callback
Browse files Browse the repository at this point in the history
  • Loading branch information
nosir committed Jul 10, 2016
1 parent c7668a5 commit 5581ca0
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 88 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"form",
"input"
],
"version": "0.2.1",
"version": "0.4.1",
"author": {
"name": "Max Huang",
"email": "[email protected]",
Expand Down
124 changes: 96 additions & 28 deletions dist/cleave-react.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/cleave-react.min.js

Large diffs are not rendered by default.

110 changes: 89 additions & 21 deletions dist/cleave.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,9 @@ Cleave.prototype = {
value = Util.strip(value, /[^\d]/g);
}

// update credit card blocks
// and at least one of first 4 characters has changed
if (pps.creditCard && Util.headStr(pps.result, 4) !== Util.headStr(value, 4)) {
pps.blocks = Cleave.CreditCardDetector.getBlocksByPAN(value, pps.creditCardStrictMode);
pps.blocksLength = pps.blocks.length;
pps.maxLength = Util.getMaxLength(pps.blocks);
// update credit card props
if (pps.creditCard) {
owner.updateCreditCardPropsByValue(value);
}

// strip over length characters
Expand All @@ -183,6 +180,30 @@ Cleave.prototype = {
owner.updateValueState();
},

updateCreditCardPropsByValue: function (value) {
var owner = this, pps = owner.properties,
Util = Cleave.Util,
creditCardInfo;

// At least one of the first 4 characters has changed
if (Util.headStr(pps.result, 4) === Util.headStr(value, 4)) {
return;
}

creditCardInfo = Cleave.CreditCardDetector.getInfo(value, pps.creditCardStrictMode);

pps.blocks = creditCardInfo.blocks;
pps.blocksLength = pps.blocks.length;
pps.maxLength = Util.getMaxLength(pps.blocks);

// credit card type changed
if (pps.creditCardType !== creditCardInfo.type) {
pps.creditCardType = creditCardInfo.type;

pps.onCreditCardTypeChanged.call(owner, pps.creditCardType);
}
},

updateValueState: function () {
var owner = this;

Expand Down Expand Up @@ -321,6 +342,8 @@ var DefaultProperties = {
// credit card
target.creditCard = !!opts.creditCard;
target.creditCardStrictMode = !!opts.creditCardStrictMode;
target.creditCardType = '';
target.onCreditCardTypeChanged = opts.onCreditCardTypeChanged || (function () {});

// phone
target.phone = !!opts.phone;
Expand Down Expand Up @@ -374,12 +397,14 @@ var CreditCardDetector = {
uatp: [4, 5, 6],
amex: [4, 6, 5],
diners: [4, 6, 4],
discover: [4, 4, 4, 4],
mastercard: [4, 4, 4, 4],
dankort: [4, 4, 4, 4],
instapayment: [4, 4, 4, 4],
jcb: [4, 4, 4, 4],
generalStrict: [4, 4, 4, 7],
generalLoose: [4, 4, 4, 4]
visa: [4, 4, 4, 4],
generalLoose: [4, 4, 4, 4],
generalStrict: [4, 4, 4, 7]
},

re: {
Expand All @@ -389,10 +414,13 @@ var CreditCardDetector = {
// starts with 34/37; 15 digits
amex: /^3[47]\d{0,13}/,

// starts with 6011/65/644-649; 16 digits
discover: /^(?:6011|65\d{0,2}|64[4-9]\d?)\d{0,12}/,

// starts with 300-305/309 or 36/38/39; 14 digits
diners: /^3(?:0([0-5]|9)|[689]\d?)\d{0,11}/,

// starts with 51-55 or 22-27; 16 digits
// starts with 51-55/22-27; 16 digits
mastercard: /^(5[1-5]|2[2-7])\d{0,14}/,

// starts with 5019/4175/4571; 16 digits
Expand All @@ -402,37 +430,77 @@ var CreditCardDetector = {
instapayment: /^63[7-9]\d{0,13}/,

// starts with 2131/1800/35; 16 digits
jcb: /^(?:2131|1800|35\d{0,2})\d{0,12}/
jcb: /^(?:2131|1800|35\d{0,2})\d{0,12}/,

// starts with 4; 16 digits
visa: /^4\d{0,15}/
},

getBlocksByPAN: function (value, strictMode) {
getInfo: function (value, strictMode) {
var blocks = CreditCardDetector.blocks,
re = CreditCardDetector.re;

// In theory, credit card can have up to 19 digits number.
// In theory, visa credit card can have up to 19 digits number.
// Set strictMode to true will remove the 16 max-length restrain,
// however, I never found any website validate card number like
// this, hence probably you don't need to enable this option.
strictMode = !!strictMode;

if (re.amex.test(value)) {
return blocks.amex;
return {
type: 'amex',
blocks: blocks.amex
};
} else if (re.uatp.test(value)) {
return blocks.uatp;
return {
type: 'uatp',
blocks: blocks.uatp
};
} else if (re.diners.test(value)) {
return blocks.diners;
return {
type: 'diners',
blocks: blocks.diners
};
} else if (re.discover.test(value)) {
return {
type: 'discover',
blocks: blocks.discover
};
} else if (re.mastercard.test(value)) {
return blocks.mastercard;
return {
type: 'mastercard',
blocks: blocks.mastercard
};
} else if (re.dankort.test(value)) {
return blocks.dankort;
return {
type: 'dankort',
blocks: blocks.dankort
};
} else if (re.instapayment.test(value)) {
return blocks.instapayment;
return {
type: 'instapayment',
blocks: blocks.instapayment
};
} else if (re.jcb.test(value)) {
return blocks.jcb;
return {
type: 'jcb',
blocks: blocks.jcb
};
} else if (re.visa.test(value)) {
return {
type: 'visa',
blocks: blocks.visa
};
} else if (strictMode) {
return blocks.generalStrict;
return {
type: 'unknown',
blocks: blocks.generalStrict
};
} else {
return blocks.generalLoose;
return {
type: 'unknown',
blocks: blocks.generalLoose
};
}
}
};
Expand Down
4 changes: 2 additions & 2 deletions dist/cleave.min.js

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions doc/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Credit card numbers:
- [creditCard](#creditcard)
- [onCreditCardTypeChanged](#oncreditcardtypechanged)
- Phone numbers:
- [phone](#phone)
- [phoneRegionCode](#phoneregioncode)
Expand Down Expand Up @@ -48,6 +49,23 @@ new Cleave('.my-input', {
...
```

### `onCreditCardTypeChanged`

A callback `Function`. Triggered after credit card type changes.

The unique `String` argument `type` is the type of the detected credit, which can be:

`amex` `mastercard` `visa` `diners` `discover` `jcb` `dankort` `instapayment` `uatp`

```js
new Cleave('.my-input', {
creditCard: true,
onCreditCardTypeChanged: function (type) {
// update UI ...
}
});
```

## Phone numbers

### `phone`
Expand Down
3 changes: 3 additions & 0 deletions doc/reactjs-component-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ As you can see, here you simply use `<Cleave/>` as a normal `<input/>` field

In the example above, we get the `rawValue` and update its `state` in handler, eventually it will be passed to backend or `store` layer.

## Playground

- [React JSFiddle](https://jsfiddle.net/nosir/gLLsrxxf/)

## References

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"form",
"input"
],
"version": "0.3.2",
"version": "0.4.1",
"author": {
"name": "Max Huang",
"url": "http://github.com/nosir",
Expand Down
33 changes: 27 additions & 6 deletions src/Cleave.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,9 @@ Cleave.prototype = {
value = Util.strip(value, /[^\d]/g);
}

// update credit card blocks
// and at least one of first 4 characters has changed
if (pps.creditCard && Util.headStr(pps.result, 4) !== Util.headStr(value, 4)) {
pps.blocks = Cleave.CreditCardDetector.getBlocksByPAN(value, pps.creditCardStrictMode);
pps.blocksLength = pps.blocks.length;
pps.maxLength = Util.getMaxLength(pps.blocks);
// update credit card props
if (pps.creditCard) {
owner.updateCreditCardPropsByValue(value);
}

// strip over length characters
Expand All @@ -181,6 +178,30 @@ Cleave.prototype = {
owner.updateValueState();
},

updateCreditCardPropsByValue: function (value) {
var owner = this, pps = owner.properties,
Util = Cleave.Util,
creditCardInfo;

// At least one of the first 4 characters has changed
if (Util.headStr(pps.result, 4) === Util.headStr(value, 4)) {
return;
}

creditCardInfo = Cleave.CreditCardDetector.getInfo(value, pps.creditCardStrictMode);

pps.blocks = creditCardInfo.blocks;
pps.blocksLength = pps.blocks.length;
pps.maxLength = Util.getMaxLength(pps.blocks);

// credit card type changed
if (pps.creditCardType !== creditCardInfo.type) {
pps.creditCardType = creditCardInfo.type;

pps.onCreditCardTypeChanged.call(owner, pps.creditCardType);
}
},

updateValueState: function () {
var owner = this;

Expand Down
42 changes: 31 additions & 11 deletions src/Cleave.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ var Cleave = React.createClass({

getInitialState: function () {
var owner = this,
{ value, options, onKeydown, onChange, ...other } = owner.props;
{ value, options, onKeyDown, onChange, ...other } = owner.props;

owner.registeredEvents = {
onChange: onChange || Util.noop,
onKeydown: onKeydown || Util.noop
onKeyDown: onKeyDown || Util.noop
};

options.initValue = value;
Expand Down Expand Up @@ -113,7 +113,7 @@ var Cleave = React.createClass({
}
},

onKeydown: function (event) {
onKeyDown: function (event) {
var owner = this,
pps = owner.properties,
charCode = event.which || event.keyCode;
Expand All @@ -125,7 +125,7 @@ var Cleave = React.createClass({
pps.backspace = false;
}

owner.registeredEvents.onKeydown(event);
owner.registeredEvents.onKeyDown(event);
},

onChange: function (event) {
Expand Down Expand Up @@ -183,12 +183,9 @@ var Cleave = React.createClass({
value = Util.strip(value, /[^\d]/g);
}

// update credit card blocks
// and at least one of first 4 characters has changed
if (pps.creditCard && Util.headStr(pps.result, 4) !== Util.headStr(value, 4)) {
pps.blocks = CreditCardDetector.getBlocksByPAN(value, pps.creditCardStrictMode);
pps.blocksLength = pps.blocks.length;
pps.maxLength = Util.getMaxLength(pps.blocks);
// update credit card props
if (pps.creditCard) {
owner.updateCreditCardPropsByValue(value);
}

// strip over length characters
Expand All @@ -210,6 +207,29 @@ var Cleave = React.createClass({
owner.updateValueState();
},

updateCreditCardPropsByValue: function (value) {
var owner = this, pps = owner.properties,
creditCardInfo;

// At least one of the first 4 characters has changed
if (Util.headStr(pps.result, 4) === Util.headStr(value, 4)) {
return;
}

creditCardInfo = CreditCardDetector.getInfo(value, pps.creditCardStrictMode);

pps.blocks = creditCardInfo.blocks;
pps.blocksLength = pps.blocks.length;
pps.maxLength = Util.getMaxLength(pps.blocks);

// credit card type changed
if (pps.creditCardType !== creditCardInfo.type) {
pps.creditCardType = creditCardInfo.type;

pps.onCreditCardTypeChanged.call(owner, pps.creditCardType);
}
},

updateValueState: function () {
this.setState({value: this.properties.result});
},
Expand All @@ -220,7 +240,7 @@ var Cleave = React.createClass({
return (
<input type="text" {...owner.state.other}
value={owner.state.value}
onKeydown={owner.onKeydown}
onKeyDown={owner.onKeyDown}
onChange={owner.onChange}/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/common/DefaultProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ var DefaultProperties = {
// credit card
target.creditCard = !!opts.creditCard;
target.creditCardStrictMode = !!opts.creditCardStrictMode;
target.creditCardType = '';
target.onCreditCardTypeChanged = opts.onCreditCardTypeChanged || (function () {});

// phone
target.phone = !!opts.phone;
Expand Down
Loading

0 comments on commit 5581ca0

Please sign in to comment.