1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 sc_require('validators/validator') ; 9 10 /** @class 11 Validate a field value as a credit card number. 12 13 This validator will perform a basic check to ensure the credit card number 14 is mathematically valid. It will also accept numbers with spaces, dashes 15 or other punctuation. 16 17 Converted credit card numbers are broken into units of 4. 18 19 Basic credit card validation courtesy David Leppek 20 (https://www.azcode.com/Mod10) 21 22 @extends SC.Validator 23 @since SproutCore 1.0 24 */ 25 SC.Validator.CreditCard = SC.Validator.extend( 26 /** @scope SC.Validator.CreditCard.prototype */ { 27 28 /** 29 Expects a string of 16 digits. Will split into groups of 4 for display. 30 */ 31 fieldValueForObject: function(object, form, field) { 32 if (typeof(object) == "string" && object.length == 16) { 33 object = [object.slice(0,4),object.slice(4,8),object.slice(8,12),object.slice(12,16)].join(' ') ; 34 } 35 return object ; 36 }, 37 38 /** 39 Removes all whitespace or dashes to make a single string. 40 */ 41 objectForFieldValue: function(value, form, field) { 42 return value.replace(/[\s-\.\:]/g,'') ; 43 }, 44 45 validate: function(form, field) { 46 return this.checkNumber(field.get('fieldValue')) ; 47 }, 48 49 validateError: function(form, field) { 50 var label = field.get('errorLabel') || 'Field' ; 51 return SC.$error(SC.String.loc("Invalid.CreditCard(%@)", label), label); 52 }, 53 54 /** 55 Allow only numbers, dashes, and spaces 56 */ 57 validateKeyDown: function(form, field, charStr) { 58 return !!charStr.match(/[0-9\- ]/); 59 }, 60 61 checkNumber: function(ccNumb) { 62 63 if (!ccNumb || ccNumb.length===0) return YES; // do not validate empty 64 65 // remove any spaces or dashes 66 ccNumb = ccNumb.replace(/[^0-9]/g,''); 67 68 var valid = "0123456789"; // Valid digits in a credit card number 69 var len = ccNumb.length; // The length of the submitted cc number 70 var iCCN = parseInt(ccNumb,0); // integer of ccNumb 71 var sCCN = ccNumb.toString(); // string of ccNumb 72 sCCN = sCCN.replace (/^\s+|\s+$/g,''); // strip spaces 73 var iTotal = 0; // integer total set at zero 74 var bNum = true; // by default assume it is a number 75 var bResult = false; // by default assume it is NOT a valid cc 76 var temp; // temp variable for parsing string 77 var calc; // used for calculation of each digit 78 79 // Determine if the ccNumb is in fact all numbers 80 for (var j=0; j<len; j++) { 81 temp = "" + sCCN.substring(j, j+1); 82 if (valid.indexOf(temp) == "-1"){bNum = false;} 83 } 84 85 // if it is NOT a number, you can either alert to the fact, 86 // or just pass a failure 87 if(!bNum) bResult = false; 88 89 // Determine if it is the proper length 90 if((len === 0)&&(bResult)){ // nothing, field is blank AND passed above # check 91 bResult = false; 92 } else{ // ccNumb is a number and the proper length - let's see if it is a valid card number 93 if(len >= 15){ // 15 or 16 for Amex or V/MC 94 for(var i=len;i>0;i--){ // LOOP through the digits of the card 95 calc = parseInt(iCCN,0) % 10; // right most digit 96 calc = parseInt(calc,0); // assure it is an integer 97 iTotal += calc; // running total of the card number as we loop - Do Nothing to first digit 98 i--; // decrement the count - move to the next digit in the card 99 iCCN = iCCN / 10; // subtracts right most digit from ccNumb 100 calc = parseInt(iCCN,0) % 10 ; // NEXT right most digit 101 calc = calc *2; // multiply the digit by two 102 // Instead of some screwy method of converting 16 to a string and then parsing 1 and 6 and then adding them to make 7, 103 // I use a simple switch statement to change the value of calc2 to 7 if 16 is the multiple. 104 switch(calc){ 105 case 10: calc = 1; break; //5*2=10 & 1+0 = 1 106 case 12: calc = 3; break; //6*2=12 & 1+2 = 3 107 case 14: calc = 5; break; //7*2=14 & 1+4 = 5 108 case 16: calc = 7; break; //8*2=16 & 1+6 = 7 109 case 18: calc = 9; break; //9*2=18 & 1+8 = 9 110 default: calc = calc; //4*2= 8 & 8 = 8 -same for all lower numbers 111 } 112 iCCN = iCCN / 10; // subtracts right most digit from ccNum 113 iTotal += calc; // running total of the card number as we loop 114 } // END OF LOOP 115 if ((iTotal%10)===0){ // check to see if the sum Mod 10 is zero 116 bResult = true; // This IS (or could be) a valid credit card number. 117 } else { 118 bResult = false; // This could NOT be a valid credit card number 119 } 120 } 121 } 122 return bResult; // Return the results 123 } 124 125 }) ; 126