Coverage

100%
83
83
0

/Users/sebastiansandqvist/Documents/Sites & Projects/apps/modules/s-valid/index.js

100%
83
83
0
LineHitsSource
11'use strict';
2
31var valid = {};
4
5// ----- Regexp checks from is_js
6// -- Modified url to include port: https://gist.github.com/dperini/729294
7// -- Modified affirmative to include 'on' and allowed any capitalization
8// -- Added negatory
9// -- Improved creditCard regexp allows for more card types
10// - http://stackoverflow.com/a/23231321
11// ---------------------------------------
121valid._regexps = {
13 affirmative: /^(?:1|t(?:rue)?|y(?:es)?|on|ok(?:ay)?)$/,
14 alphabetic: /^[A-Za-z]+$/,
15 alphaNumeric: /^[A-Za-z0-9]+$/,
16 creditCard: {
17 mastercardVisa: /^4[0-9]{12}(?:[0-9]{3})?$^5[1-5][0-9]{14}$|^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$/,
18 amex: /^3[47][0-9]{13}$/,
19 carteBlanche: /^389[0-9]{11}$|^380[0-9]{11}$/,
20 dinersClub: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
21 discover: /^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$/,
22 jcb: /^(?:2131|1800|35\d{3})\d{11}$/,
23 lasercard: /^(6304|6706|6709|6771)[0-9]{12,15}$/,
24 maestro: /^(5018|5020|5038|6304|6759|6761|6763|6799)[0-9]{8,19}$/,
25 solo: /^(6334|6767)[0-9]{12}|(6334|6767)[0-9]{14}|(6334|6767)[0-9]{15}$|^(4903|4905|4911|4936|6333|6759)[0-9]{12}|(4903|4905|4911|4936|6333|6759)[0-9]{14}|(4903|4905|4911|4936|6333|6759)[0-9]{15}|564182[0-9]{10}|564182[0-9]{12}|564182[0-9]{13}|633110[0-9]{10}|633110[0-9]{12}|633110[0-9]{13}$/,
26 unionpay: /^(62[0-9]{14,17})$/
27 },
28 email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
29 negatory: /^(?:1|f(?:alse)?|n(?:o)?|off)$/,
30 url: /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/i
31};
32
33
34// --------------------------------- string methods ---------------------------------
35
36// ----- private typechecker method
37// ---------------------------------------
381valid._isString = function(str) {
39
40147 if (typeof str === 'string' || str instanceof String) {
41138 return true;
42 }
43
449 return false;
45
46};
47
48// ----- private regexp test methods
49// ---------------------------------------
501valid._testRegexp = function(regexp, str) {
51
52108 if (!this._isString(str)) {
536 return false;
54 }
55
56102 str = str.toLowerCase();
57
58102 return this._regexps[regexp].test(str);
59};
60
611valid._testCardRegexp = function(regexp, n) {
6246 return this._regexps.creditCard[regexp].test(n);
63};
64
65
66// ----- affirmative
67// ---------------------------------------
681valid.affirmative = function(str) {
69
7025 return this._testRegexp('affirmative', str);
71
72};
73
74
75// ----- alphanumeric
76// ---------------------------------------
771valid.alphaNumeric = function(str) {
78
7915 return this._testRegexp('alphaNumeric', str);
80
81};
82
83
84// ----- alphabetic
85// ---------------------------------------
861valid.alpha = function(str) {
87
8817 return this._testRegexp('alphabetic', str);
89
90};
91
92
93// ----- email
94// ---------------------------------------
951valid.email = function(str) {
96
979 return this._testRegexp('email', str);
98
99};
100
101
102// ----- negatory
103// ---------------------------------------
1041valid.negatory = function(str) {
105
10619 return this._testRegexp('negatory', str);
107
108};
109
110
111// ----- numeric
112// ---------------------------------------
1131valid.numeric = function(str) {
114
11512 if (!this._isString(str)) {
1161 return false;
117 }
118
11911 if (str === '') {
1201 return false;
121 }
122
12310 return !isNaN(str); // http://stackoverflow.com/a/175787
124
125};
126
127
128// ----- value
129// ---------------------------------------
1301valid.value = function(str) {
131
13225 if (this._isString(str)) {
133
13424 str = str.replace(',', '');
13524 var numbers = ['0','1','2','3','4','5','6','7','8','9', '-'];
136
137 // for $100 and #123, etc.
13824 if (numbers.indexOf(str[0]) === -1) {
13911 str = str.slice(1);
140 }
141
142 }
143
144 else {
1451 return false;
146 }
147
14824 return !isNaN(parseInt(str), 10);
149
150};
151
152
153// ----- url
154// ---------------------------------------
1551valid.url = function(str) {
156
15721 return this._testRegexp('url', str);
158
159};
160
161
162
163
164
165// --------------------------------- number methods ---------------------------------
166
167// ----- private typechecker method
168// ---------------------------------------
1691valid._isNumber = function(str) {
170
17192 if (typeof str === 'number' || str instanceof Number) {
17286 return true;
173 }
174
1756 return false;
176
177};
178
179
180// -------------- credit card methods --------------
181
182// ----- credit card check constructor
183// ---------------------------------------
1841function CreditCard(name) {
185
18612 return function(n) {
187
18845 if (!valid._isNumber(n)) {
1891 return false;
190 }
191
19244 if (!valid._testCardRegexp(name, n)) {
19312 return false;
194 }
195
19632 return true;
197
198 };
199
200}
201
202
203// ----- specific card regexp validation
204// ---------------------------------------
2051valid.card = {
206 mastercardVisa: new CreditCard('mastercardVisa'),
207 mastercard: new CreditCard('mastercardVisa'), // alias
208 visa: new CreditCard('mastercardVisa'), // alias
209 amex: new CreditCard('amex'),
210 maestro: new CreditCard('maestro'),
211 jcb: new CreditCard('jcb'),
212 unionpay: new CreditCard('unionpay'),
213 discover: new CreditCard('discover'),
214 solo: new CreditCard('solo'),
215 carteBlanche: new CreditCard('carteBlanche'),
216 dinersClub: new CreditCard('dinersClub'),
217 lasercard: new CreditCard('lasercard')
218};
219
220
221// ----- generic card validation
222// -- 1. input must be number
223// -- 2. input length must be valid
224// -- 3. return true if any specific test passes
225// -- 4. perform complex check based on number
226// ---------------------------------------
2271valid.creditCard = valid.card.generic = function(n) {
228
22928 if (!valid._isNumber(n)) {
2302 return false;
231 }
232
23326 var str = n.toString();
234
235 // must be valid card length
23626 if (str.length < 13 || str.length > 19) {
2372 return false;
238 }
239
240 // should return true if any specific regexp tests pass
24124 for (var prop in valid._regexps.creditCard) {
242
243121 if (valid._regexps.creditCard.hasOwnProperty(prop)) {
244121 if (valid._regexps.creditCard[prop].test(n)) {
24522 return true;
246 }
247 }
248
249 }
250
251 // method of testing credit cards from
252 // http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.1/jquery.validate.js
2532 var testNumber = 0;
254
2552 for (var i = str.length - 1, current, currentInteger = 0, even = false; i>=0; i--) {
256
25732 current = str.charAt(i);
25832 currentInteger = parseInt(current, 10);
259
26032 if (even && (currentInteger *= 2) > 9 ) {
2615 currentInteger -= 9;
262 }
263
26432 testNumber += currentInteger;
26532 even = !even;
266 }
267
2682 return (testNumber % 10) === 0;
269
270};
271
272
273// ----- integer
274// ---------------------------------------
2751valid.integer = function(n) {
276
27711 if (!this._isNumber(n)) {
2781 return false;
279 }
280
28110 return n % 1 === 0;
282
283};
284
285
286// ----- zip code
287// ---------------------------------------
2881valid.zipCode = function(n) {
289
2906 if (!this._isNumber(n)) {
2911 return false;
292 }
293
2945 var len = n.toString().length;
295
2965 if (len !== 5 && len !== 9) {
2973 return false;
298 }
299
3002 return true;
301
302};
303
3041module.exports = valid;