Skip to content

Commit 2769a6e

Browse files
committed
Adds credit card validation to form validation #2729
1 parent 7889d19 commit 2769a6e

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

RELEASE-NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- **Dropdown** - Dropdown will now automatically update selected values when hidden input value changes (so long as `change` event is triggered) #2626
1111
- **Grid** - Added new responsive [`reversed`](http://www.semantic-ui.com/collections/grid.html#responsive-order) variations for reversing column order by device #2685
1212
- **Label** - Added a new `basic label` style, works symbiotically with other label types to provide a more lightweight style label
13+
- **Form Validation** - Added credit card validation, supports array of card types, and international cards including non luhn cards like China UnionPay #2729
1314
- **Form Validation** - Updated appearance of form validation prompts to use a more lightweight style. Added variables for controlling error validation prompt styles in `form.variables`
1415
- **Divider** - Vertical divider can now be used multiple times in a single column row (not just 50/50 split). #2808
1516
- **Input** - Added `disabled` state for inputs #2694

src/definitions/behaviors/form.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,113 @@ $.fn.form.settings = {
12441244
: false
12451245
;
12461246
},
1247+
creditCard: function(cardNumber, cardTypes) {
1248+
var
1249+
cards = {
1250+
amex: {
1251+
pattern: /^3[47]/,
1252+
length : [15]
1253+
},
1254+
visa: {
1255+
pattern: /^4/,
1256+
length : [16]
1257+
},
1258+
mastercard: {
1259+
pattern: /^5[1-5]/,
1260+
length : [16]
1261+
},
1262+
discover: {
1263+
pattern: /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/,
1264+
length : [16]
1265+
},
1266+
unionPay: {
1267+
pattern: /^(62|88)/,
1268+
length: [16, 17, 18, 19]
1269+
},
1270+
dinersClub: {
1271+
pattern: /^30[0-5]/,
1272+
length : [14]
1273+
},
1274+
dinersClubInternational: {
1275+
pattern: /^36/,
1276+
length : [14]
1277+
},
1278+
jcb: {
1279+
pattern: /^35(2[89]|[3-8][0-9])/,
1280+
length : [16]
1281+
},
1282+
laser: {
1283+
pattern: /^(6304|670[69]|6771)/,
1284+
length : [16, 17, 18, 19]
1285+
},
1286+
visaElectron: {
1287+
pattern: /^(4026|417500|4508|4844|491(3|7))/,
1288+
length : [16]
1289+
},
1290+
maestro: {
1291+
pattern: /^(5018|5020|5038|6304|6759|676[1-3])/,
1292+
length : [12, 13, 14, 15, 16, 17, 18, 19]
1293+
}
1294+
},
1295+
valid = {},
1296+
validCard = false,
1297+
requiredTypes = (typeof cardTypes == 'string')
1298+
? cardTypes.split(',')
1299+
: false,
1300+
unionPay,
1301+
validation
1302+
;
1303+
1304+
if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
1305+
return;
1306+
}
1307+
1308+
// verify card types
1309+
if(requiredTypes) {
1310+
$.each(requiredTypes, function(index, type){
1311+
// verify each card type
1312+
validation = cards[type];
1313+
if(validation) {
1314+
valid = {
1315+
length : ($.inArray(cardNumber.length, validation.length) !== -1),
1316+
pattern : (cardNumber.search(validation.pattern) !== -1)
1317+
};
1318+
if(valid.length && valid.pattern) {
1319+
validCard = true;
1320+
}
1321+
}
1322+
});
1323+
1324+
if(!validCard) {
1325+
return false;
1326+
}
1327+
}
1328+
1329+
// skip luhn for UnionPay
1330+
unionPay = {
1331+
number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
1332+
pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
1333+
};
1334+
if(unionPay.number && unionPay.pattern) {
1335+
return true;
1336+
}
1337+
1338+
// verify luhn, adapted from <https://gist.github.com/2134376>
1339+
var
1340+
length = cardNumber.length,
1341+
multiple = 0,
1342+
producedValue = [
1343+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
1344+
[0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
1345+
],
1346+
sum = 0
1347+
;
1348+
while (length--) {
1349+
sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
1350+
multiple ^= 1;
1351+
}
1352+
return (sum % 10 === 0 && sum > 0);
1353+
},
12471354

12481355
// different than another field
12491356
different: function(value, identifier) {

0 commit comments

Comments
 (0)