diff --git a/CHANGELOG b/CHANGELOG index 140c2bd..b8e8379 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ += 1.3.0 + * Updated Issuer Identification Number (IIN) patterns with documentaion (see PR #44 and #47) + * Allow right and left arrow keys to be used while navigating inside all input types (see PR #45) + * Fix issue with clearning selected text when typing (see PR #48) + * Fix issuewith the expiry field parsing when typing in a RTL context (see PR #50) + * Allow cursor repositioning when pasting full card numbers (see PR #51) + = 1.2.5 * Fixes #37, allowing for vendoring and fix event normalization (PR #39) * Fixes #38, full width character fixes for Safari diff --git a/dist/jquery.payform.js b/dist/jquery.payform.js index 9d2d55f..fab80e7 100644 --- a/dist/jquery.payform.js +++ b/dist/jquery.payform.js @@ -1,4 +1,4 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o License: MIT - Version: 1.2.5 + Version: 1.3.0 */ var 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; }; @@ -50,7 +49,7 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i return this[name] = definition(); } })('payform', function() { - var _eventNormalize, _getCaretPos, _on, cardFromNumber, cardFromType, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardExpiry, formatCardNumber, formatForwardExpiry, formatForwardSlashAndSpace, hasTextSelected, luhnCheck, payform, reFormatCVC, reFormatCardNumber, reFormatExpiry, replaceFullWidthChars, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric; + var _eventNormalize, _getCaretPos, _on, cardFromNumber, cardFromType, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardExpiry, formatCardNumber, formatForwardExpiry, formatForwardSlashAndSpace, getDirectionality, hasTextSelected, keyCodes, luhnCheck, payform, reFormatCVC, reFormatCardNumber, reFormatExpiry, replaceFullWidthChars, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric; _getCaretPos = function(ele) { var r, rc, re; if (ele.selectionStart != null) { @@ -100,11 +99,18 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i } }; payform = {}; + keyCodes = { + UNKNOWN: 0, + BACKSPACE: 8, + PAGE_UP: 33, + ARROW_LEFT: 37, + ARROW_RIGHT: 39 + }; defaultFormat = /(\d{1,4})/g; payform.cards = [ { type: 'elo', - pattern: /^((50670[7-8])|(506715)|(50671[7-9])|(50672[0-1])|(50672[4-9])|(50673[0-3])|(506739)|(50674[0-8])|(50675[0-3])|(50677[4-8])|(50900[0-9])|(50901[3-9])|(50902[0-9])|(50903[1-9])|(50904[0-9])|(50905[0-9])|(50906[0-4])|(50906[6-9])|(50907[0-2])|(50907[4-5])|(636368)|(636297)|(504175)|(438935)|(40117[8-9])|(45763[1-2])|(457393)|(431274)|(50907[6-9])|(50908[0-9])|(627780))/, + pattern: /^(4011(78|79)|43(1274|8935)|45(1416|7393|763(1|2))|50(4175|6699|67[0-7][0-9]|9000)|627780|63(6297|6368)|650(03([^4])|04([0-9])|05(0|1)|4(0[5-9]|3[0-9]|8[5-9]|9[0-9])|5([0-2][0-9]|3[0-8])|9([2-6][0-9]|7[0-8])|541|700|720|901)|651652|655000|655021)/, format: defaultFormat, length: [16], cvcLength: [3], @@ -118,7 +124,7 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i luhn: true }, { type: 'maestro', - pattern: /^(5(018|0[23]|[68])|6(39|7))/, + pattern: /^(5018|5020|5038|6304|6703|6708|6759|676[1-3])/, format: defaultFormat, length: [12, 13, 14, 15, 16, 17, 18, 19], cvcLength: [3], @@ -141,12 +147,12 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i type: 'visa', pattern: /^4/, format: defaultFormat, - length: [13, 16], + length: [13, 16, 19], cvcLength: [3], luhn: true }, { type: 'mastercard', - pattern: /^(5[1-5]|2[2-7])/, + pattern: /^(5[1-5]|677189)|^(222[1-9]|2[3-6]\d{2}|27[0-1]\d|2720)/, format: defaultFormat, length: [16], cvcLength: [3], @@ -156,25 +162,32 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i pattern: /^3[47]/, format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/, length: [15], - cvcLength: [3, 4], + cvcLength: [4], + luhn: true + }, { + type: 'hipercard', + pattern: /^(384100|384140|384160|606282|637095|637568|60(?!11))/, + format: defaultFormat, + length: [14, 15, 16, 17, 18, 19], + cvcLength: [3], luhn: true }, { type: 'dinersclub', - pattern: /^3[0689]/, - format: /(\d{1,4})(\d{1,4})?(\d{1,4})?(\d{1,2})?/, + pattern: /^(36|38|30[0-5])/, + format: /(\d{1,4})(\d{1,6})?(\d{1,4})?/, length: [14], cvcLength: [3], luhn: true }, { type: 'discover', - pattern: /^6([045]|22)/, + pattern: /^(6011|65|64[4-9]|622)/, format: defaultFormat, length: [16], cvcLength: [3], luhn: true }, { type: 'unionpay', - pattern: /^(62|88)/, + pattern: /^62/, format: defaultFormat, length: [16, 17, 18, 19], cvcLength: [3], @@ -183,7 +196,14 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i type: 'jcb', pattern: /^35/, format: defaultFormat, - length: [16], + length: [16, 17, 18, 19], + cvcLength: [3], + luhn: true + }, { + type: 'laser', + pattern: /^(6706|6771|6709)/, + format: defaultFormat, + length: [16, 17, 18, 19], cvcLength: [3], luhn: true } @@ -209,6 +229,11 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i } } }; + getDirectionality = function(target) { + var style; + style = getComputedStyle(target); + return style && style['direction'] || document.dir; + }; luhnCheck = function(num) { var digit, digits, i, len, odd, sum; odd = true; @@ -257,15 +282,22 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i }; reFormatCardNumber = function(e) { var cursor; + cursor = _getCaretPos(e.target); if (e.target.value === "") { return; } + if (getDirectionality(e.target) === 'ltr') { + cursor = _getCaretPos(e.target); + } e.target.value = payform.formatCardNumber(e.target.value); - if (document.dir === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { + if (getDirectionality(e.target) === 'ltr' && cursor !== e.target.selectionStart) { + cursor = _getCaretPos(e.target); + } + if (getDirectionality(e.target) === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { e.target.value = '‎\u200e'.concat(e.target.value); } cursor = _getCaretPos(e.target); - if ((cursor != null) && e.type !== 'change') { + if ((cursor != null) && cursor !== 0 && e.type !== 'change') { return e.target.setSelectionRange(cursor, cursor); } }; @@ -309,13 +341,16 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i formatBackCardNumber = function(e) { var cursor, value; value = e.target.value; - if (e.which !== 8) { + if (e.which !== keyCodes.BACKSPACE) { return; } cursor = _getCaretPos(e.target); if (cursor && cursor !== value.length) { return; } + if ((e.target.selectionEnd - e.target.selectionStart) > 1) { + return; + } if (/\d\s$/.test(value)) { e.preventDefault(); return setTimeout(function() { @@ -334,7 +369,7 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i return; } e.target.value = payform.formatCardExpiry(e.target.value); - if (document.dir === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { + if (getDirectionality(e.target) === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { e.target.value = '‎\u200e'.concat(e.target.value); } cursor = _getCaretPos(e.target); @@ -386,7 +421,7 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i formatBackExpiry = function(e) { var cursor, value; value = e.target.value; - if (e.which !== 8) { + if (e.which !== keyCodes.BACKSPACE) { return; } cursor = _getCaretPos(e.target); @@ -416,10 +451,10 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i if (e.metaKey || e.ctrlKey) { return; } - if (e.which === 0) { + if ([keyCodes.UNKNOWN, keyCodes.ARROW_LEFT, keyCodes.ARROW_RIGHT].indexOf(e.which) > -1) { return; } - if (e.which < 33) { + if (e.which < keyCodes.PAGE_UP) { return; } input = String.fromCharCode(e.which); @@ -513,7 +548,7 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i prefix = prefix.toString().slice(0, 2); year = prefix + year; } - month = parseInt(month, 10); + month = parseInt(month.replace(/[\u200e]/g, ""), 10); year = parseInt(year, 10); return { month: month, @@ -636,5 +671,4 @@ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i }); - },{}]},{},[1]); diff --git a/dist/jquery.payform.min.js b/dist/jquery.payform.min.js index 433ffdf..d96a3d0 100644 --- a/dist/jquery.payform.min.js +++ b/dist/jquery.payform.min.js @@ -1 +1 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o9){digit-=9}sum+=digit}return sum%10===0};hasTextSelected=function(target){var ref;if((typeof document!=="undefined"&&document!==null?(ref=document.selection)!=null?ref.createRange:void 0:void 0)!=null){if(document.selection.createRange().text){return true}}return target.selectionStart!=null&&target.selectionStart!==target.selectionEnd};replaceFullWidthChars=function(str){var char,chars,fullWidth,halfWidth,i,idx,len,value;if(str==null){str=""}fullWidth="0123456789";halfWidth="0123456789";value="";chars=str.split("");for(i=0,len=chars.length;i-1){char=halfWidth[idx]}value+=char}return value};reFormatCardNumber=function(e){var cursor;if(e.target.value===""){return}e.target.value=payform.formatCardNumber(e.target.value);if(document.dir==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardNumber=function(e){var card,cursor,digit,length,re,upperLength,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}value=e.target.value;card=cardFromNumber(value+digit);length=(value.replace(/\D/g,"")+digit).length;upperLength=16;if(card){upperLength=card.length[card.length.length-1]}if(length>=upperLength){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(card&&card.type==="amex"){re=/^(\d{4}|\d{4}\s\d{6})$/}else{re=/(?:^|\s)(\d{4})$/}if(re.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value+" "+digit})}else if(re.test(value+digit)){e.preventDefault();return setTimeout(function(){return e.target.value=value+digit+" "})}};formatBackCardNumber=function(e){var cursor,value;value=e.target.value;if(e.which!==8){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(/\d\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s$/,"")})}else if(/\s\d?$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d$/,"")})}};reFormatExpiry=function(e){var cursor;if(e.target.value===""){return}e.target.value=payform.formatCardExpiry(e.target.value);if(document.dir==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value+digit;if(/^\d$/.test(val)&&(val!=="0"&&val!=="1")){e.preventDefault();return setTimeout(function(){return e.target.value="0"+val+" / "})}else if(/^\d\d$/.test(val)){e.preventDefault();return setTimeout(function(){return e.target.value=val+" / "})}};formatForwardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value;if(/^\d\d$/.test(val)){return e.target.value=val+" / "}};formatForwardSlashAndSpace=function(e){var val,which;which=String.fromCharCode(e.which);if(!(which==="/"||which===" ")){return}val=e.target.value;if(/^\d$/.test(val)&&val!=="0"){return e.target.value="0"+val+" / "}};formatBackExpiry=function(e){var cursor,value;value=e.target.value;if(e.which!==8){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(/\d\s\/\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s\/\s$/,"")})}};reFormatCVC=function(e){var cursor;if(e.target.value===""){return}cursor=_getCaretPos(e.target);e.target.value=replaceFullWidthChars(e.target.value).replace(/\D/g,"").slice(0,4);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};restrictNumeric=function(e){var input;if(e.metaKey||e.ctrlKey){return}if(e.which===0){return}if(e.which<33){return}input=String.fromCharCode(e.which);if(!/^\d+$/.test(input)){return e.preventDefault()}};restrictCardNumber=function(e){var card,digit,maxLength,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}value=(e.target.value+digit).replace(/\D/g,"");card=cardFromNumber(value);maxLength=card?card.length[card.length.length-1]:16;if(value.length>maxLength){return e.preventDefault()}};restrictExpiry=function(e){var digit,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}value=e.target.value+digit;value=value.replace(/\D/g,"");if(value.length>6){return e.preventDefault()}};restrictCVC=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}val=e.target.value+digit;if(val.length>4){return e.preventDefault()}};payform.cvcInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCVC);_on(input,"paste",reFormatCVC);_on(input,"change",reFormatCVC);return _on(input,"input",reFormatCVC)};payform.expiryInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictExpiry);_on(input,"keypress",formatCardExpiry);_on(input,"keypress",formatForwardSlashAndSpace);_on(input,"keypress",formatForwardExpiry);_on(input,"keydown",formatBackExpiry);_on(input,"change",reFormatExpiry);return _on(input,"input",reFormatExpiry)};payform.cardNumberInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCardNumber);_on(input,"keypress",formatCardNumber);_on(input,"keydown",formatBackCardNumber);_on(input,"paste",reFormatCardNumber);_on(input,"change",reFormatCardNumber);return _on(input,"input",reFormatCardNumber)};payform.numericInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"paste",restrictNumeric);_on(input,"change",restrictNumeric);return _on(input,"input",restrictNumeric)};payform.parseCardExpiry=function(value){var month,prefix,ref,year;value=value.replace(/\s/g,"");ref=value.split("/",2),month=ref[0],year=ref[1];if((year!=null?year.length:void 0)===2&&/^\d+$/.test(year)){prefix=(new Date).getFullYear();prefix=prefix.toString().slice(0,2);year=prefix+year}month=parseInt(month,10);year=parseInt(year,10);return{month:month,year:year}};payform.validateCardNumber=function(num){var card,ref;num=(num+"").replace(/\s+|-/g,"");if(!/^\d+$/.test(num)){return false}card=cardFromNumber(num);if(!card){return false}return(ref=num.length,indexOf.call(card.length,ref)>=0)&&(card.luhn===false||luhnCheck(num))};payform.validateCardExpiry=function(month,year){var currentTime,expiry,ref;if(typeof month==="object"&&"month"in month){ref=month,month=ref.month,year=ref.year}if(!(month&&year)){return false}month=String(month).trim();year=String(year).trim();if(!/^\d+$/.test(month)){return false}if(!/^\d+$/.test(year)){return false}if(!(1<=month&&month<=12)){return false}if(year.length===2){if(year<70){year="20"+year}else{year="19"+year}}if(year.length!==4){return false}expiry=new Date(year,month);currentTime=new Date;expiry.setMonth(expiry.getMonth()-1);expiry.setMonth(expiry.getMonth()+1,1);return expiry>currentTime};payform.validateCardCVC=function(cvc,type){var card,ref;cvc=String(cvc).trim();if(!/^\d+$/.test(cvc)){return false}card=cardFromType(type);if(card!=null){return ref=cvc.length,indexOf.call(card.cvcLength,ref)>=0}else{return cvc.length>=3&&cvc.length<=4}};payform.parseCardType=function(num){var ref;if(!num){return null}return((ref=cardFromNumber(num))!=null?ref.type:void 0)||null};payform.formatCardNumber=function(num){var card,groups,ref,upperLength;num=replaceFullWidthChars(num);num=num.replace(/\D/g,"");card=cardFromNumber(num);if(!card){return num}upperLength=card.length[card.length.length-1];num=num.slice(0,upperLength);if(card.format.global){return(ref=num.match(card.format))!=null?ref.join(" "):void 0}else{groups=card.format.exec(num);if(groups==null){return}groups.shift();groups=groups.filter(Boolean);return groups.join(" ")}};payform.formatCardExpiry=function(expiry){var mon,parts,sep,year;expiry=replaceFullWidthChars(expiry);parts=expiry.match(/^\D*(\d{1,2})(\D+)?(\d{1,4})?/);if(!parts){return""}mon=parts[1]||"";sep=parts[2]||"";year=parts[3]||"";if(year.length>0){sep=" / "}else if(sep===" /"){mon=mon.substring(0,1);sep=""}else if(mon.length===2||sep.length>0){sep=" / "}else if(mon.length===1&&(mon!=="0"&&mon!=="1")){mon="0"+mon;sep=" / "}return mon+sep+year};return payform})},{}]},{},[1]); \ No newline at end of file +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i9){digit-=9}sum+=digit}return sum%10===0};hasTextSelected=function(target){var ref;if((typeof document!=="undefined"&&document!==null?(ref=document.selection)!=null?ref.createRange:void 0:void 0)!=null){if(document.selection.createRange().text){return true}}return target.selectionStart!=null&&target.selectionStart!==target.selectionEnd};replaceFullWidthChars=function(str){var char,chars,fullWidth,halfWidth,i,idx,len,value;if(str==null){str=""}fullWidth="0123456789";halfWidth="0123456789";value="";chars=str.split("");for(i=0,len=chars.length;i-1){char=halfWidth[idx]}value+=char}return value};reFormatCardNumber=function(e){var cursor;cursor=_getCaretPos(e.target);if(e.target.value===""){return}if(getDirectionality(e.target)==="ltr"){cursor=_getCaretPos(e.target)}e.target.value=payform.formatCardNumber(e.target.value);if(getDirectionality(e.target)==="ltr"&&cursor!==e.target.selectionStart){cursor=_getCaretPos(e.target)}if(getDirectionality(e.target)==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&cursor!==0&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardNumber=function(e){var card,cursor,digit,length,re,upperLength,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}value=e.target.value;card=cardFromNumber(value+digit);length=(value.replace(/\D/g,"")+digit).length;upperLength=16;if(card){upperLength=card.length[card.length.length-1]}if(length>=upperLength){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(card&&card.type==="amex"){re=/^(\d{4}|\d{4}\s\d{6})$/}else{re=/(?:^|\s)(\d{4})$/}if(re.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value+" "+digit})}else if(re.test(value+digit)){e.preventDefault();return setTimeout(function(){return e.target.value=value+digit+" "})}};formatBackCardNumber=function(e){var cursor,value;value=e.target.value;if(e.which!==keyCodes.BACKSPACE){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(e.target.selectionEnd-e.target.selectionStart>1){return}if(/\d\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s$/,"")})}else if(/\s\d?$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d$/,"")})}};reFormatExpiry=function(e){var cursor;if(e.target.value===""){return}e.target.value=payform.formatCardExpiry(e.target.value);if(getDirectionality(e.target)==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value+digit;if(/^\d$/.test(val)&&(val!=="0"&&val!=="1")){e.preventDefault();return setTimeout(function(){return e.target.value="0"+val+" / "})}else if(/^\d\d$/.test(val)){e.preventDefault();return setTimeout(function(){return e.target.value=val+" / "})}};formatForwardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value;if(/^\d\d$/.test(val)){return e.target.value=val+" / "}};formatForwardSlashAndSpace=function(e){var val,which;which=String.fromCharCode(e.which);if(!(which==="/"||which===" ")){return}val=e.target.value;if(/^\d$/.test(val)&&val!=="0"){return e.target.value="0"+val+" / "}};formatBackExpiry=function(e){var cursor,value;value=e.target.value;if(e.which!==keyCodes.BACKSPACE){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(/\d\s\/\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s\/\s$/,"")})}};reFormatCVC=function(e){var cursor;if(e.target.value===""){return}cursor=_getCaretPos(e.target);e.target.value=replaceFullWidthChars(e.target.value).replace(/\D/g,"").slice(0,4);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};restrictNumeric=function(e){var input;if(e.metaKey||e.ctrlKey){return}if([keyCodes.UNKNOWN,keyCodes.ARROW_LEFT,keyCodes.ARROW_RIGHT].indexOf(e.which)>-1){return}if(e.whichmaxLength){return e.preventDefault()}};restrictExpiry=function(e){var digit,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}value=e.target.value+digit;value=value.replace(/\D/g,"");if(value.length>6){return e.preventDefault()}};restrictCVC=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}val=e.target.value+digit;if(val.length>4){return e.preventDefault()}};payform.cvcInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCVC);_on(input,"paste",reFormatCVC);_on(input,"change",reFormatCVC);return _on(input,"input",reFormatCVC)};payform.expiryInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictExpiry);_on(input,"keypress",formatCardExpiry);_on(input,"keypress",formatForwardSlashAndSpace);_on(input,"keypress",formatForwardExpiry);_on(input,"keydown",formatBackExpiry);_on(input,"change",reFormatExpiry);return _on(input,"input",reFormatExpiry)};payform.cardNumberInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCardNumber);_on(input,"keypress",formatCardNumber);_on(input,"keydown",formatBackCardNumber);_on(input,"paste",reFormatCardNumber);_on(input,"change",reFormatCardNumber);return _on(input,"input",reFormatCardNumber)};payform.numericInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"paste",restrictNumeric);_on(input,"change",restrictNumeric);return _on(input,"input",restrictNumeric)};payform.parseCardExpiry=function(value){var month,prefix,ref,year;value=value.replace(/\s/g,"");ref=value.split("/",2),month=ref[0],year=ref[1];if((year!=null?year.length:void 0)===2&&/^\d+$/.test(year)){prefix=(new Date).getFullYear();prefix=prefix.toString().slice(0,2);year=prefix+year}month=parseInt(month.replace(/[\u200e]/g,""),10);year=parseInt(year,10);return{month:month,year:year}};payform.validateCardNumber=function(num){var card,ref;num=(num+"").replace(/\s+|-/g,"");if(!/^\d+$/.test(num)){return false}card=cardFromNumber(num);if(!card){return false}return(ref=num.length,indexOf.call(card.length,ref)>=0)&&(card.luhn===false||luhnCheck(num))};payform.validateCardExpiry=function(month,year){var currentTime,expiry,ref;if(typeof month==="object"&&"month"in month){ref=month,month=ref.month,year=ref.year}if(!(month&&year)){return false}month=String(month).trim();year=String(year).trim();if(!/^\d+$/.test(month)){return false}if(!/^\d+$/.test(year)){return false}if(!(1<=month&&month<=12)){return false}if(year.length===2){if(year<70){year="20"+year}else{year="19"+year}}if(year.length!==4){return false}expiry=new Date(year,month);currentTime=new Date;expiry.setMonth(expiry.getMonth()-1);expiry.setMonth(expiry.getMonth()+1,1);return expiry>currentTime};payform.validateCardCVC=function(cvc,type){var card,ref;cvc=String(cvc).trim();if(!/^\d+$/.test(cvc)){return false}card=cardFromType(type);if(card!=null){return ref=cvc.length,indexOf.call(card.cvcLength,ref)>=0}else{return cvc.length>=3&&cvc.length<=4}};payform.parseCardType=function(num){var ref;if(!num){return null}return((ref=cardFromNumber(num))!=null?ref.type:void 0)||null};payform.formatCardNumber=function(num){var card,groups,ref,upperLength;num=replaceFullWidthChars(num);num=num.replace(/\D/g,"");card=cardFromNumber(num);if(!card){return num}upperLength=card.length[card.length.length-1];num=num.slice(0,upperLength);if(card.format.global){return(ref=num.match(card.format))!=null?ref.join(" "):void 0}else{groups=card.format.exec(num);if(groups==null){return}groups.shift();groups=groups.filter(Boolean);return groups.join(" ")}};payform.formatCardExpiry=function(expiry){var mon,parts,sep,year;expiry=replaceFullWidthChars(expiry);parts=expiry.match(/^\D*(\d{1,2})(\D+)?(\d{1,4})?/);if(!parts){return""}mon=parts[1]||"";sep=parts[2]||"";year=parts[3]||"";if(year.length>0){sep=" / "}else if(sep===" /"){mon=mon.substring(0,1);sep=""}else if(mon.length===2||sep.length>0){sep=" / "}else if(mon.length===1&&(mon!=="0"&&mon!=="1")){mon="0"+mon;sep=" / "}return mon+sep+year};return payform})},{}]},{},[1]); \ No newline at end of file diff --git a/dist/payform.js b/dist/payform.js index 28e9d9f..21057f7 100644 --- a/dist/payform.js +++ b/dist/payform.js @@ -5,7 +5,7 @@ URL: https://github.com/jondavidjohn/payform Author: Jonathan D. Johnson License: MIT - Version: 1.2.5 + Version: 1.3.0 */ (function() { @@ -20,7 +20,7 @@ return this[name] = definition(); } })('payform', function() { - var _eventNormalize, _getCaretPos, _on, cardFromNumber, cardFromType, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardExpiry, formatCardNumber, formatForwardExpiry, formatForwardSlashAndSpace, hasTextSelected, luhnCheck, payform, reFormatCVC, reFormatCardNumber, reFormatExpiry, replaceFullWidthChars, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric; + var _eventNormalize, _getCaretPos, _on, cardFromNumber, cardFromType, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardExpiry, formatCardNumber, formatForwardExpiry, formatForwardSlashAndSpace, getDirectionality, hasTextSelected, keyCodes, luhnCheck, payform, reFormatCVC, reFormatCardNumber, reFormatExpiry, replaceFullWidthChars, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric; _getCaretPos = function(ele) { var r, rc, re; if (ele.selectionStart != null) { @@ -70,11 +70,18 @@ } }; payform = {}; + keyCodes = { + UNKNOWN: 0, + BACKSPACE: 8, + PAGE_UP: 33, + ARROW_LEFT: 37, + ARROW_RIGHT: 39 + }; defaultFormat = /(\d{1,4})/g; payform.cards = [ { type: 'elo', - pattern: /^((50670[7-8])|(506715)|(50671[7-9])|(50672[0-1])|(50672[4-9])|(50673[0-3])|(506739)|(50674[0-8])|(50675[0-3])|(50677[4-8])|(50900[0-9])|(50901[3-9])|(50902[0-9])|(50903[1-9])|(50904[0-9])|(50905[0-9])|(50906[0-4])|(50906[6-9])|(50907[0-2])|(50907[4-5])|(636368)|(636297)|(504175)|(438935)|(40117[8-9])|(45763[1-2])|(457393)|(431274)|(50907[6-9])|(50908[0-9])|(627780))/, + pattern: /^(4011(78|79)|43(1274|8935)|45(1416|7393|763(1|2))|50(4175|6699|67[0-7][0-9]|9000)|627780|63(6297|6368)|650(03([^4])|04([0-9])|05(0|1)|4(0[5-9]|3[0-9]|8[5-9]|9[0-9])|5([0-2][0-9]|3[0-8])|9([2-6][0-9]|7[0-8])|541|700|720|901)|651652|655000|655021)/, format: defaultFormat, length: [16], cvcLength: [3], @@ -88,7 +95,7 @@ luhn: true }, { type: 'maestro', - pattern: /^(5(018|0[23]|[68])|6(39|7))/, + pattern: /^(5018|5020|5038|6304|6703|6708|6759|676[1-3])/, format: defaultFormat, length: [12, 13, 14, 15, 16, 17, 18, 19], cvcLength: [3], @@ -111,12 +118,12 @@ type: 'visa', pattern: /^4/, format: defaultFormat, - length: [13, 16], + length: [13, 16, 19], cvcLength: [3], luhn: true }, { type: 'mastercard', - pattern: /^(5[1-5]|2[2-7])/, + pattern: /^(5[1-5]|677189)|^(222[1-9]|2[3-6]\d{2}|27[0-1]\d|2720)/, format: defaultFormat, length: [16], cvcLength: [3], @@ -126,25 +133,32 @@ pattern: /^3[47]/, format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/, length: [15], - cvcLength: [3, 4], + cvcLength: [4], + luhn: true + }, { + type: 'hipercard', + pattern: /^(384100|384140|384160|606282|637095|637568|60(?!11))/, + format: defaultFormat, + length: [14, 15, 16, 17, 18, 19], + cvcLength: [3], luhn: true }, { type: 'dinersclub', - pattern: /^3[0689]/, - format: /(\d{1,4})(\d{1,4})?(\d{1,4})?(\d{1,2})?/, + pattern: /^(36|38|30[0-5])/, + format: /(\d{1,4})(\d{1,6})?(\d{1,4})?/, length: [14], cvcLength: [3], luhn: true }, { type: 'discover', - pattern: /^6([045]|22)/, + pattern: /^(6011|65|64[4-9]|622)/, format: defaultFormat, length: [16], cvcLength: [3], luhn: true }, { type: 'unionpay', - pattern: /^(62|88)/, + pattern: /^62/, format: defaultFormat, length: [16, 17, 18, 19], cvcLength: [3], @@ -153,7 +167,14 @@ type: 'jcb', pattern: /^35/, format: defaultFormat, - length: [16], + length: [16, 17, 18, 19], + cvcLength: [3], + luhn: true + }, { + type: 'laser', + pattern: /^(6706|6771|6709)/, + format: defaultFormat, + length: [16, 17, 18, 19], cvcLength: [3], luhn: true } @@ -179,6 +200,11 @@ } } }; + getDirectionality = function(target) { + var style; + style = getComputedStyle(target); + return style && style['direction'] || document.dir; + }; luhnCheck = function(num) { var digit, digits, i, len, odd, sum; odd = true; @@ -227,15 +253,22 @@ }; reFormatCardNumber = function(e) { var cursor; + cursor = _getCaretPos(e.target); if (e.target.value === "") { return; } + if (getDirectionality(e.target) === 'ltr') { + cursor = _getCaretPos(e.target); + } e.target.value = payform.formatCardNumber(e.target.value); - if (document.dir === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { + if (getDirectionality(e.target) === 'ltr' && cursor !== e.target.selectionStart) { + cursor = _getCaretPos(e.target); + } + if (getDirectionality(e.target) === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { e.target.value = '‎\u200e'.concat(e.target.value); } cursor = _getCaretPos(e.target); - if ((cursor != null) && e.type !== 'change') { + if ((cursor != null) && cursor !== 0 && e.type !== 'change') { return e.target.setSelectionRange(cursor, cursor); } }; @@ -279,13 +312,16 @@ formatBackCardNumber = function(e) { var cursor, value; value = e.target.value; - if (e.which !== 8) { + if (e.which !== keyCodes.BACKSPACE) { return; } cursor = _getCaretPos(e.target); if (cursor && cursor !== value.length) { return; } + if ((e.target.selectionEnd - e.target.selectionStart) > 1) { + return; + } if (/\d\s$/.test(value)) { e.preventDefault(); return setTimeout(function() { @@ -304,7 +340,7 @@ return; } e.target.value = payform.formatCardExpiry(e.target.value); - if (document.dir === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { + if (getDirectionality(e.target) === 'rtl' && e.target.value.indexOf('‎\u200e') === -1) { e.target.value = '‎\u200e'.concat(e.target.value); } cursor = _getCaretPos(e.target); @@ -356,7 +392,7 @@ formatBackExpiry = function(e) { var cursor, value; value = e.target.value; - if (e.which !== 8) { + if (e.which !== keyCodes.BACKSPACE) { return; } cursor = _getCaretPos(e.target); @@ -386,10 +422,10 @@ if (e.metaKey || e.ctrlKey) { return; } - if (e.which === 0) { + if ([keyCodes.UNKNOWN, keyCodes.ARROW_LEFT, keyCodes.ARROW_RIGHT].indexOf(e.which) > -1) { return; } - if (e.which < 33) { + if (e.which < keyCodes.PAGE_UP) { return; } input = String.fromCharCode(e.which); @@ -483,7 +519,7 @@ prefix = prefix.toString().slice(0, 2); year = prefix + year; } - month = parseInt(month, 10); + month = parseInt(month.replace(/[\u200e]/g, ""), 10); year = parseInt(year, 10); return { month: month, diff --git a/dist/payform.min.js b/dist/payform.min.js index 0d17017..07f8b72 100644 --- a/dist/payform.min.js +++ b/dist/payform.min.js @@ -1 +1 @@ -(function(){var indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i9){digit-=9}sum+=digit}return sum%10===0};hasTextSelected=function(target){var ref;if((typeof document!=="undefined"&&document!==null?(ref=document.selection)!=null?ref.createRange:void 0:void 0)!=null){if(document.selection.createRange().text){return true}}return target.selectionStart!=null&&target.selectionStart!==target.selectionEnd};replaceFullWidthChars=function(str){var char,chars,fullWidth,halfWidth,i,idx,len,value;if(str==null){str=""}fullWidth="0123456789";halfWidth="0123456789";value="";chars=str.split("");for(i=0,len=chars.length;i-1){char=halfWidth[idx]}value+=char}return value};reFormatCardNumber=function(e){var cursor;if(e.target.value===""){return}e.target.value=payform.formatCardNumber(e.target.value);if(document.dir==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardNumber=function(e){var card,cursor,digit,length,re,upperLength,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}value=e.target.value;card=cardFromNumber(value+digit);length=(value.replace(/\D/g,"")+digit).length;upperLength=16;if(card){upperLength=card.length[card.length.length-1]}if(length>=upperLength){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(card&&card.type==="amex"){re=/^(\d{4}|\d{4}\s\d{6})$/}else{re=/(?:^|\s)(\d{4})$/}if(re.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value+" "+digit})}else if(re.test(value+digit)){e.preventDefault();return setTimeout(function(){return e.target.value=value+digit+" "})}};formatBackCardNumber=function(e){var cursor,value;value=e.target.value;if(e.which!==8){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(/\d\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s$/,"")})}else if(/\s\d?$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d$/,"")})}};reFormatExpiry=function(e){var cursor;if(e.target.value===""){return}e.target.value=payform.formatCardExpiry(e.target.value);if(document.dir==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value+digit;if(/^\d$/.test(val)&&(val!=="0"&&val!=="1")){e.preventDefault();return setTimeout(function(){return e.target.value="0"+val+" / "})}else if(/^\d\d$/.test(val)){e.preventDefault();return setTimeout(function(){return e.target.value=val+" / "})}};formatForwardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value;if(/^\d\d$/.test(val)){return e.target.value=val+" / "}};formatForwardSlashAndSpace=function(e){var val,which;which=String.fromCharCode(e.which);if(!(which==="/"||which===" ")){return}val=e.target.value;if(/^\d$/.test(val)&&val!=="0"){return e.target.value="0"+val+" / "}};formatBackExpiry=function(e){var cursor,value;value=e.target.value;if(e.which!==8){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(/\d\s\/\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s\/\s$/,"")})}};reFormatCVC=function(e){var cursor;if(e.target.value===""){return}cursor=_getCaretPos(e.target);e.target.value=replaceFullWidthChars(e.target.value).replace(/\D/g,"").slice(0,4);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};restrictNumeric=function(e){var input;if(e.metaKey||e.ctrlKey){return}if(e.which===0){return}if(e.which<33){return}input=String.fromCharCode(e.which);if(!/^\d+$/.test(input)){return e.preventDefault()}};restrictCardNumber=function(e){var card,digit,maxLength,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}value=(e.target.value+digit).replace(/\D/g,"");card=cardFromNumber(value);maxLength=card?card.length[card.length.length-1]:16;if(value.length>maxLength){return e.preventDefault()}};restrictExpiry=function(e){var digit,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}value=e.target.value+digit;value=value.replace(/\D/g,"");if(value.length>6){return e.preventDefault()}};restrictCVC=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}val=e.target.value+digit;if(val.length>4){return e.preventDefault()}};payform.cvcInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCVC);_on(input,"paste",reFormatCVC);_on(input,"change",reFormatCVC);return _on(input,"input",reFormatCVC)};payform.expiryInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictExpiry);_on(input,"keypress",formatCardExpiry);_on(input,"keypress",formatForwardSlashAndSpace);_on(input,"keypress",formatForwardExpiry);_on(input,"keydown",formatBackExpiry);_on(input,"change",reFormatExpiry);return _on(input,"input",reFormatExpiry)};payform.cardNumberInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCardNumber);_on(input,"keypress",formatCardNumber);_on(input,"keydown",formatBackCardNumber);_on(input,"paste",reFormatCardNumber);_on(input,"change",reFormatCardNumber);return _on(input,"input",reFormatCardNumber)};payform.numericInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"paste",restrictNumeric);_on(input,"change",restrictNumeric);return _on(input,"input",restrictNumeric)};payform.parseCardExpiry=function(value){var month,prefix,ref,year;value=value.replace(/\s/g,"");ref=value.split("/",2),month=ref[0],year=ref[1];if((year!=null?year.length:void 0)===2&&/^\d+$/.test(year)){prefix=(new Date).getFullYear();prefix=prefix.toString().slice(0,2);year=prefix+year}month=parseInt(month,10);year=parseInt(year,10);return{month:month,year:year}};payform.validateCardNumber=function(num){var card,ref;num=(num+"").replace(/\s+|-/g,"");if(!/^\d+$/.test(num)){return false}card=cardFromNumber(num);if(!card){return false}return(ref=num.length,indexOf.call(card.length,ref)>=0)&&(card.luhn===false||luhnCheck(num))};payform.validateCardExpiry=function(month,year){var currentTime,expiry,ref;if(typeof month==="object"&&"month"in month){ref=month,month=ref.month,year=ref.year}if(!(month&&year)){return false}month=String(month).trim();year=String(year).trim();if(!/^\d+$/.test(month)){return false}if(!/^\d+$/.test(year)){return false}if(!(1<=month&&month<=12)){return false}if(year.length===2){if(year<70){year="20"+year}else{year="19"+year}}if(year.length!==4){return false}expiry=new Date(year,month);currentTime=new Date;expiry.setMonth(expiry.getMonth()-1);expiry.setMonth(expiry.getMonth()+1,1);return expiry>currentTime};payform.validateCardCVC=function(cvc,type){var card,ref;cvc=String(cvc).trim();if(!/^\d+$/.test(cvc)){return false}card=cardFromType(type);if(card!=null){return ref=cvc.length,indexOf.call(card.cvcLength,ref)>=0}else{return cvc.length>=3&&cvc.length<=4}};payform.parseCardType=function(num){var ref;if(!num){return null}return((ref=cardFromNumber(num))!=null?ref.type:void 0)||null};payform.formatCardNumber=function(num){var card,groups,ref,upperLength;num=replaceFullWidthChars(num);num=num.replace(/\D/g,"");card=cardFromNumber(num);if(!card){return num}upperLength=card.length[card.length.length-1];num=num.slice(0,upperLength);if(card.format.global){return(ref=num.match(card.format))!=null?ref.join(" "):void 0}else{groups=card.format.exec(num);if(groups==null){return}groups.shift();groups=groups.filter(Boolean);return groups.join(" ")}};payform.formatCardExpiry=function(expiry){var mon,parts,sep,year;expiry=replaceFullWidthChars(expiry);parts=expiry.match(/^\D*(\d{1,2})(\D+)?(\d{1,4})?/);if(!parts){return""}mon=parts[1]||"";sep=parts[2]||"";year=parts[3]||"";if(year.length>0){sep=" / "}else if(sep===" /"){mon=mon.substring(0,1);sep=""}else if(mon.length===2||sep.length>0){sep=" / "}else if(mon.length===1&&(mon!=="0"&&mon!=="1")){mon="0"+mon;sep=" / "}return mon+sep+year};return payform})}).call(this); \ No newline at end of file +(function(){var indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i9){digit-=9}sum+=digit}return sum%10===0};hasTextSelected=function(target){var ref;if((typeof document!=="undefined"&&document!==null?(ref=document.selection)!=null?ref.createRange:void 0:void 0)!=null){if(document.selection.createRange().text){return true}}return target.selectionStart!=null&&target.selectionStart!==target.selectionEnd};replaceFullWidthChars=function(str){var char,chars,fullWidth,halfWidth,i,idx,len,value;if(str==null){str=""}fullWidth="0123456789";halfWidth="0123456789";value="";chars=str.split("");for(i=0,len=chars.length;i-1){char=halfWidth[idx]}value+=char}return value};reFormatCardNumber=function(e){var cursor;cursor=_getCaretPos(e.target);if(e.target.value===""){return}if(getDirectionality(e.target)==="ltr"){cursor=_getCaretPos(e.target)}e.target.value=payform.formatCardNumber(e.target.value);if(getDirectionality(e.target)==="ltr"&&cursor!==e.target.selectionStart){cursor=_getCaretPos(e.target)}if(getDirectionality(e.target)==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&cursor!==0&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardNumber=function(e){var card,cursor,digit,length,re,upperLength,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}value=e.target.value;card=cardFromNumber(value+digit);length=(value.replace(/\D/g,"")+digit).length;upperLength=16;if(card){upperLength=card.length[card.length.length-1]}if(length>=upperLength){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(card&&card.type==="amex"){re=/^(\d{4}|\d{4}\s\d{6})$/}else{re=/(?:^|\s)(\d{4})$/}if(re.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value+" "+digit})}else if(re.test(value+digit)){e.preventDefault();return setTimeout(function(){return e.target.value=value+digit+" "})}};formatBackCardNumber=function(e){var cursor,value;value=e.target.value;if(e.which!==keyCodes.BACKSPACE){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(e.target.selectionEnd-e.target.selectionStart>1){return}if(/\d\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s$/,"")})}else if(/\s\d?$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d$/,"")})}};reFormatExpiry=function(e){var cursor;if(e.target.value===""){return}e.target.value=payform.formatCardExpiry(e.target.value);if(getDirectionality(e.target)==="rtl"&&e.target.value.indexOf("‎‎")===-1){e.target.value="‎‎".concat(e.target.value)}cursor=_getCaretPos(e.target);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};formatCardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value+digit;if(/^\d$/.test(val)&&(val!=="0"&&val!=="1")){e.preventDefault();return setTimeout(function(){return e.target.value="0"+val+" / "})}else if(/^\d\d$/.test(val)){e.preventDefault();return setTimeout(function(){return e.target.value=val+" / "})}};formatForwardExpiry=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}val=e.target.value;if(/^\d\d$/.test(val)){return e.target.value=val+" / "}};formatForwardSlashAndSpace=function(e){var val,which;which=String.fromCharCode(e.which);if(!(which==="/"||which===" ")){return}val=e.target.value;if(/^\d$/.test(val)&&val!=="0"){return e.target.value="0"+val+" / "}};formatBackExpiry=function(e){var cursor,value;value=e.target.value;if(e.which!==keyCodes.BACKSPACE){return}cursor=_getCaretPos(e.target);if(cursor&&cursor!==value.length){return}if(/\d\s\/\s$/.test(value)){e.preventDefault();return setTimeout(function(){return e.target.value=value.replace(/\d\s\/\s$/,"")})}};reFormatCVC=function(e){var cursor;if(e.target.value===""){return}cursor=_getCaretPos(e.target);e.target.value=replaceFullWidthChars(e.target.value).replace(/\D/g,"").slice(0,4);if(cursor!=null&&e.type!=="change"){return e.target.setSelectionRange(cursor,cursor)}};restrictNumeric=function(e){var input;if(e.metaKey||e.ctrlKey){return}if([keyCodes.UNKNOWN,keyCodes.ARROW_LEFT,keyCodes.ARROW_RIGHT].indexOf(e.which)>-1){return}if(e.whichmaxLength){return e.preventDefault()}};restrictExpiry=function(e){var digit,value;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}value=e.target.value+digit;value=value.replace(/\D/g,"");if(value.length>6){return e.preventDefault()}};restrictCVC=function(e){var digit,val;digit=String.fromCharCode(e.which);if(!/^\d+$/.test(digit)){return}if(hasTextSelected(e.target)){return}val=e.target.value+digit;if(val.length>4){return e.preventDefault()}};payform.cvcInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCVC);_on(input,"paste",reFormatCVC);_on(input,"change",reFormatCVC);return _on(input,"input",reFormatCVC)};payform.expiryInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictExpiry);_on(input,"keypress",formatCardExpiry);_on(input,"keypress",formatForwardSlashAndSpace);_on(input,"keypress",formatForwardExpiry);_on(input,"keydown",formatBackExpiry);_on(input,"change",reFormatExpiry);return _on(input,"input",reFormatExpiry)};payform.cardNumberInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"keypress",restrictCardNumber);_on(input,"keypress",formatCardNumber);_on(input,"keydown",formatBackCardNumber);_on(input,"paste",reFormatCardNumber);_on(input,"change",reFormatCardNumber);return _on(input,"input",reFormatCardNumber)};payform.numericInput=function(input){_on(input,"keypress",restrictNumeric);_on(input,"paste",restrictNumeric);_on(input,"change",restrictNumeric);return _on(input,"input",restrictNumeric)};payform.parseCardExpiry=function(value){var month,prefix,ref,year;value=value.replace(/\s/g,"");ref=value.split("/",2),month=ref[0],year=ref[1];if((year!=null?year.length:void 0)===2&&/^\d+$/.test(year)){prefix=(new Date).getFullYear();prefix=prefix.toString().slice(0,2);year=prefix+year}month=parseInt(month.replace(/[\u200e]/g,""),10);year=parseInt(year,10);return{month:month,year:year}};payform.validateCardNumber=function(num){var card,ref;num=(num+"").replace(/\s+|-/g,"");if(!/^\d+$/.test(num)){return false}card=cardFromNumber(num);if(!card){return false}return(ref=num.length,indexOf.call(card.length,ref)>=0)&&(card.luhn===false||luhnCheck(num))};payform.validateCardExpiry=function(month,year){var currentTime,expiry,ref;if(typeof month==="object"&&"month"in month){ref=month,month=ref.month,year=ref.year}if(!(month&&year)){return false}month=String(month).trim();year=String(year).trim();if(!/^\d+$/.test(month)){return false}if(!/^\d+$/.test(year)){return false}if(!(1<=month&&month<=12)){return false}if(year.length===2){if(year<70){year="20"+year}else{year="19"+year}}if(year.length!==4){return false}expiry=new Date(year,month);currentTime=new Date;expiry.setMonth(expiry.getMonth()-1);expiry.setMonth(expiry.getMonth()+1,1);return expiry>currentTime};payform.validateCardCVC=function(cvc,type){var card,ref;cvc=String(cvc).trim();if(!/^\d+$/.test(cvc)){return false}card=cardFromType(type);if(card!=null){return ref=cvc.length,indexOf.call(card.cvcLength,ref)>=0}else{return cvc.length>=3&&cvc.length<=4}};payform.parseCardType=function(num){var ref;if(!num){return null}return((ref=cardFromNumber(num))!=null?ref.type:void 0)||null};payform.formatCardNumber=function(num){var card,groups,ref,upperLength;num=replaceFullWidthChars(num);num=num.replace(/\D/g,"");card=cardFromNumber(num);if(!card){return num}upperLength=card.length[card.length.length-1];num=num.slice(0,upperLength);if(card.format.global){return(ref=num.match(card.format))!=null?ref.join(" "):void 0}else{groups=card.format.exec(num);if(groups==null){return}groups.shift();groups=groups.filter(Boolean);return groups.join(" ")}};payform.formatCardExpiry=function(expiry){var mon,parts,sep,year;expiry=replaceFullWidthChars(expiry);parts=expiry.match(/^\D*(\d{1,2})(\D+)?(\d{1,4})?/);if(!parts){return""}mon=parts[1]||"";sep=parts[2]||"";year=parts[3]||"";if(year.length>0){sep=" / "}else if(sep===" /"){mon=mon.substring(0,1);sep=""}else if(mon.length===2||sep.length>0){sep=" / "}else if(mon.length===1&&(mon!=="0"&&mon!=="1")){mon="0"+mon;sep=" / "}return mon+sep+year};return payform})}).call(this); \ No newline at end of file diff --git a/package.json b/package.json index b9e701f..6ef05f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "payform", - "version": "1.2.5", + "version": "1.3.0", "description": "A general purpose library for building credit card forms, validating inputs, and formatting numbers.", "keywords": [ "payment", diff --git a/src/payform.coffee b/src/payform.coffee index bf9ab33..6866e00 100644 --- a/src/payform.coffee +++ b/src/payform.coffee @@ -4,7 +4,7 @@ URL: https://github.com/jondavidjohn/payform Author: Jonathan D. Johnson License: MIT - Version: 1.2.5 + Version: 1.3.0 ### ((name, definition) -> if module?