jquery.payment.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. // Generated by CoffeeScript 1.4.0
  2. (function() {
  3. var $, cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlash, hasTextSelected, luhnCheck, reFormatCardNumber, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric, setCardType,
  4. __slice = [].slice,
  5. __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
  6. _this = this;
  7. $ = jQuery;
  8. $.payment = {};
  9. $.payment.fn = {};
  10. $.fn.payment = function() {
  11. var args, method;
  12. method = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  13. return $.payment.fn[method].apply(this, args);
  14. };
  15. defaultFormat = /(\d{1,4})/g;
  16. cards = [
  17. // {
  18. // type: 'maestro',
  19. // pattern: /^(5018|5020|5038|6304|6759|676[1-3])/,
  20. // format: defaultFormat,
  21. // length: [12, 13, 14, 15, 16, 17, 18, 19],
  22. // cvcLength: [3],
  23. // luhn: true
  24. // }, {
  25. // type: 'dinersclub',
  26. // pattern: /^(36|38|30[0-5])/,
  27. // format: defaultFormat,
  28. // length: [14],
  29. // cvcLength: [3],
  30. // luhn: true
  31. // }, {
  32. // type: 'laser',
  33. // pattern: /^(6706|6771|6709)/,
  34. // format: defaultFormat,
  35. // length: [16, 17, 18, 19],
  36. // cvcLength: [3],
  37. // luhn: true
  38. // }, {
  39. // type: 'jcb',
  40. // pattern: /^35/,
  41. // format: defaultFormat,
  42. // length: [16],
  43. // cvcLength: [3],
  44. // luhn: true
  45. // }, {
  46. // type: 'unionpay',
  47. // pattern: /^62/,
  48. // format: defaultFormat,
  49. // length: [16, 17, 18, 19],
  50. // cvcLength: [3],
  51. // luhn: false
  52. // },
  53. {
  54. type: 'discover',
  55. pattern: /^(6011|65|64[4-9]|622)/,
  56. format: defaultFormat,
  57. length: [16],
  58. cvcLength: [3],
  59. luhn: true
  60. }, {
  61. type: 'mastercard',
  62. pattern: /^5/,
  63. format: defaultFormat,
  64. length: [16],
  65. cvcLength: [3],
  66. luhn: true
  67. }, {
  68. type: 'amex',
  69. pattern: /^3[47]/,
  70. format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
  71. length: [15],
  72. cvcLength: [3, 4],
  73. luhn: true
  74. }, {
  75. type: 'visa',
  76. pattern: /^4/,
  77. format: defaultFormat,
  78. length: [13, 14, 15, 16],
  79. cvcLength: [3],
  80. luhn: true
  81. }
  82. ];
  83. cardFromNumber = function(num) {
  84. var card, _i, _len;
  85. num = (num + '').replace(/\D/g, '');
  86. for (_i = 0, _len = cards.length; _i < _len; _i++) {
  87. card = cards[_i];
  88. if (card.pattern.test(num)) {
  89. return card;
  90. }
  91. }
  92. };
  93. cardFromType = function(type) {
  94. var card, _i, _len;
  95. for (_i = 0, _len = cards.length; _i < _len; _i++) {
  96. card = cards[_i];
  97. if (card.type === type) {
  98. return card;
  99. }
  100. }
  101. };
  102. luhnCheck = function(num) {
  103. var digit, digits, odd, sum, _i, _len;
  104. odd = true;
  105. sum = 0;
  106. digits = (num + '').split('').reverse();
  107. for (_i = 0, _len = digits.length; _i < _len; _i++) {
  108. digit = digits[_i];
  109. digit = parseInt(digit, 10);
  110. if ((odd = !odd)) {
  111. digit *= 2;
  112. }
  113. if (digit > 9) {
  114. digit -= 9;
  115. }
  116. sum += digit;
  117. }
  118. return sum % 10 === 0;
  119. };
  120. hasTextSelected = function($target) {
  121. var _ref;
  122. if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== $target.prop('selectionEnd')) {
  123. return true;
  124. }
  125. if (typeof document !== "undefined" && document !== null ? (_ref = document.selection) != null ? typeof _ref.createRange === "function" ? _ref.createRange().text : void 0 : void 0 : void 0) {
  126. return true;
  127. }
  128. return false;
  129. };
  130. reFormatCardNumber = function(e) {
  131. var _this = this;
  132. return setTimeout(function() {
  133. var $target, value;
  134. $target = $(e.currentTarget);
  135. value = $target.val();
  136. value = $.payment.formatCardNumber(value);
  137. return $target.val(value);
  138. });
  139. };
  140. formatCardNumber = function(e) {
  141. var $target, card, digit, length, re, upperLength, value;
  142. digit = String.fromCharCode(e.which);
  143. if (!/^\d+$/.test(digit)) {
  144. return;
  145. }
  146. $target = $(e.currentTarget);
  147. value = $target.val();
  148. card = cardFromNumber(value + digit);
  149. length = (value.replace(/\D/g, '') + digit).length;
  150. upperLength = 16;
  151. if (card) {
  152. upperLength = card.length[card.length.length - 1];
  153. }
  154. if (length >= upperLength) {
  155. return;
  156. }
  157. if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) {
  158. return;
  159. }
  160. if (card && card.type === 'amex') {
  161. re = /^(\d{4}|\d{4}\s\d{6})$/;
  162. } else {
  163. re = /(?:^|\s)(\d{4})$/;
  164. }
  165. if (re.test(value)) {
  166. e.preventDefault();
  167. return $target.val(value + ' ' + digit);
  168. } else if (re.test(value + digit)) {
  169. e.preventDefault();
  170. return $target.val(value + digit + ' ');
  171. }
  172. };
  173. formatBackCardNumber = function(e) {
  174. var $target, value;
  175. $target = $(e.currentTarget);
  176. value = $target.val();
  177. if (e.meta) {
  178. return;
  179. }
  180. if (e.which !== 8) {
  181. return;
  182. }
  183. if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) {
  184. return;
  185. }
  186. if (/\d\s$/.test(value)) {
  187. e.preventDefault();
  188. return $target.val(value.replace(/\d\s$/, ''));
  189. } else if (/\s\d?$/.test(value)) {
  190. e.preventDefault();
  191. return $target.val(value.replace(/\s\d?$/, ''));
  192. }
  193. };
  194. formatExpiry = function(e) {
  195. var $target, digit, val;
  196. digit = String.fromCharCode(e.which);
  197. if (!/^\d+$/.test(digit)) {
  198. return;
  199. }
  200. $target = $(e.currentTarget);
  201. val = $target.val() + digit;
  202. if (/^\d$/.test(val) && (val !== '0' && val !== '1')) {
  203. e.preventDefault();
  204. return $target.val("0" + val + " / ");
  205. } else if (/^\d\d$/.test(val)) {
  206. e.preventDefault();
  207. return $target.val("" + val + " / ");
  208. }
  209. };
  210. formatForwardExpiry = function(e) {
  211. var $target, digit, val;
  212. digit = String.fromCharCode(e.which);
  213. if (!/^\d+$/.test(digit)) {
  214. return;
  215. }
  216. $target = $(e.currentTarget);
  217. val = $target.val();
  218. if (/^\d\d$/.test(val)) {
  219. return $target.val("" + val + " / ");
  220. }
  221. };
  222. formatForwardSlash = function(e) {
  223. var $target, slash, val;
  224. slash = String.fromCharCode(e.which);
  225. if (slash !== '/') {
  226. return;
  227. }
  228. $target = $(e.currentTarget);
  229. val = $target.val();
  230. if (/^\d$/.test(val) && val !== '0') {
  231. return $target.val("0" + val + " / ");
  232. }
  233. };
  234. formatBackExpiry = function(e) {
  235. var $target, value;
  236. if (e.meta) {
  237. return;
  238. }
  239. $target = $(e.currentTarget);
  240. value = $target.val();
  241. if (e.which !== 8) {
  242. return;
  243. }
  244. if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) {
  245. return;
  246. }
  247. if (/\d(\s|\/)+$/.test(value)) {
  248. e.preventDefault();
  249. return $target.val(value.replace(/\d(\s|\/)*$/, ''));
  250. } else if (/\s\/\s?\d?$/.test(value)) {
  251. e.preventDefault();
  252. return $target.val(value.replace(/\s\/\s?\d?$/, ''));
  253. }
  254. };
  255. restrictNumeric = function(e) {
  256. var input;
  257. if (e.metaKey || e.ctrlKey) {
  258. return true;
  259. }
  260. if (e.which === 32) {
  261. return false;
  262. }
  263. if (e.which === 0) {
  264. return true;
  265. }
  266. if (e.which < 33) {
  267. return true;
  268. }
  269. input = String.fromCharCode(e.which);
  270. return !!/[\d\s]/.test(input);
  271. };
  272. restrictCardNumber = function(e) {
  273. var $target, card, digit, value;
  274. $target = $(e.currentTarget);
  275. digit = String.fromCharCode(e.which);
  276. if (!/^\d+$/.test(digit)) {
  277. return;
  278. }
  279. if (hasTextSelected($target)) {
  280. return;
  281. }
  282. value = ($target.val() + digit).replace(/\D/g, '');
  283. card = cardFromNumber(value);
  284. if (card) {
  285. return value.length <= card.length[card.length.length - 1];
  286. } else {
  287. return value.length <= 16;
  288. }
  289. };
  290. restrictExpiry = function(e) {
  291. var $target, digit, value;
  292. $target = $(e.currentTarget);
  293. digit = String.fromCharCode(e.which);
  294. if (!/^\d+$/.test(digit)) {
  295. return;
  296. }
  297. if (hasTextSelected($target)) {
  298. return;
  299. }
  300. value = $target.val() + digit;
  301. value = value.replace(/\D/g, '');
  302. if (value.length > 6) {
  303. return false;
  304. }
  305. };
  306. restrictCVC = function(e) {
  307. var $target, digit, val;
  308. $target = $(e.currentTarget);
  309. digit = String.fromCharCode(e.which);
  310. if (!/^\d+$/.test(digit)) {
  311. return;
  312. }
  313. val = $target.val() + digit;
  314. return val.length <= 4;
  315. };
  316. setCardType = function(e) {
  317. var $target, allTypes, card, cardType, val;
  318. $target = $(e.currentTarget);
  319. val = $target.val();
  320. cardType = $.payment.cardType(val) || 'unknown';
  321. if (!$target.hasClass(cardType)) {
  322. allTypes = (function() {
  323. var _i, _len, _results;
  324. _results = [];
  325. for (_i = 0, _len = cards.length; _i < _len; _i++) {
  326. card = cards[_i];
  327. _results.push(card.type);
  328. }
  329. return _results;
  330. })();
  331. $target.removeClass('unknown');
  332. $target.removeClass(allTypes.join(' '));
  333. $target.addClass(cardType);
  334. $target.toggleClass('identified', cardType !== 'unknown');
  335. return $target.trigger('payment.cardType', cardType);
  336. }
  337. };
  338. $.payment.fn.formatCardCVC = function() {
  339. this.payment('restrictNumeric');
  340. this.on('keypress', restrictCVC);
  341. return this;
  342. };
  343. $.payment.fn.formatCardExpiry = function() {
  344. this.payment('restrictNumeric');
  345. this.on('keypress', restrictExpiry);
  346. this.on('keypress', formatExpiry);
  347. this.on('keypress', formatForwardSlash);
  348. this.on('keypress', formatForwardExpiry);
  349. this.on('keydown', formatBackExpiry);
  350. return this;
  351. };
  352. $.payment.fn.formatCardNumber = function() {
  353. this.payment('restrictNumeric');
  354. this.on('keypress', restrictCardNumber);
  355. this.on('keypress', formatCardNumber);
  356. this.on('keydown', formatBackCardNumber);
  357. this.on('keyup', setCardType);
  358. this.on('paste', reFormatCardNumber);
  359. return this;
  360. };
  361. $.payment.fn.restrictNumeric = function() {
  362. this.on('keypress', restrictNumeric);
  363. return this;
  364. };
  365. $.payment.fn.cardExpiryVal = function() {
  366. return $.payment.cardExpiryVal($(this).val());
  367. };
  368. $.payment.cardExpiryVal = function(value) {
  369. var month, prefix, year, _ref;
  370. value = value.replace(/\s/g, '');
  371. _ref = value.split('/', 2), month = _ref[0], year = _ref[1];
  372. if ((year != null ? year.length : void 0) === 2 && /^\d+$/.test(year)) {
  373. prefix = (new Date).getFullYear();
  374. prefix = prefix.toString().slice(0, 2);
  375. year = prefix + year;
  376. }
  377. month = parseInt(month, 10);
  378. year = parseInt(year, 10);
  379. return {
  380. month: month,
  381. year: year
  382. };
  383. };
  384. $.payment.validateCardNumber = function(num) {
  385. var card, _ref;
  386. num = (num + '').replace(/\s+|-/g, '');
  387. if (!/^\d+$/.test(num)) {
  388. return false;
  389. }
  390. card = cardFromNumber(num);
  391. if (!card) {
  392. return false;
  393. }
  394. return (_ref = num.length, __indexOf.call(card.length, _ref) >= 0) && (card.luhn === false || luhnCheck(num));
  395. };
  396. $.payment.validateCardExpiry = function(month, year) {
  397. var currentTime, expiry, prefix, _ref;
  398. if (typeof month === 'object' && 'month' in month) {
  399. _ref = month, month = _ref.month, year = _ref.year;
  400. }
  401. if (!(month && year)) {
  402. return false;
  403. }
  404. month = $.trim(month);
  405. year = $.trim(year);
  406. if (!/^\d+$/.test(month)) {
  407. return false;
  408. }
  409. if (!/^\d+$/.test(year)) {
  410. return false;
  411. }
  412. if (!(parseInt(month, 10) <= 12)) {
  413. return false;
  414. }
  415. if (year.length === 2) {
  416. prefix = (new Date).getFullYear();
  417. prefix = prefix.toString().slice(0, 2);
  418. year = prefix + year;
  419. }
  420. expiry = new Date(year, month);
  421. currentTime = new Date;
  422. expiry.setMonth(expiry.getMonth() - 1);
  423. expiry.setMonth(expiry.getMonth() + 1, 1);
  424. return expiry > currentTime;
  425. };
  426. $.payment.validateCardCVC = function(cvc, type) {
  427. var _ref, _ref1;
  428. cvc = $.trim(cvc);
  429. if (!/^\d+$/.test(cvc)) {
  430. return false;
  431. }
  432. if (type) {
  433. return _ref = cvc.length, __indexOf.call((_ref1 = cardFromType(type)) != null ? _ref1.cvcLength : void 0, _ref) >= 0;
  434. } else {
  435. return cvc.length >= 3 && cvc.length <= 4;
  436. }
  437. };
  438. $.payment.cardType = function(num) {
  439. var _ref;
  440. if (!num) {
  441. return null;
  442. }
  443. return ((_ref = cardFromNumber(num)) != null ? _ref.type : void 0) || null;
  444. };
  445. $.payment.formatCardNumber = function(num) {
  446. var card, groups, upperLength, _ref;
  447. card = cardFromNumber(num);
  448. if (!card) {
  449. return num;
  450. }
  451. upperLength = card.length[card.length.length - 1];
  452. num = num.replace(/\D/g, '');
  453. num = num.slice(0, +upperLength + 1 || 9e9);
  454. if (card.format.global) {
  455. return (_ref = num.match(card.format)) != null ? _ref.join(' ') : void 0;
  456. } else {
  457. groups = card.format.exec(num);
  458. if (groups != null) {
  459. groups.shift();
  460. }
  461. return groups != null ? groups.join(' ') : void 0;
  462. }
  463. };
  464. }).call(this);