PluginProbe ʕ •ᴥ•ʔ
Strong Testimonials / 3.3.2
Strong Testimonials v3.3.2
3.3.2 3.3.1 trunk 1.0.1 2.30.9 2.31.10 2.32 2.32.1 2.32.2 2.32.3 2.32.4 2.33 2.34 2.35 2.36 2.37 2.38 2.38.1 2.39 2.39.1 2.39.2 2.39.3 2.40.0 2.40.1 2.40.2 2.40.3 2.40.4 2.40.5 2.40.6 2.40.7 2.41.0 2.41.1 2.50.0 2.50.1 2.50.2 2.50.3 2.50.4 2.51.0 2.51.1 2.51.2 2.51.3 2.51.4 2.51.5 2.51.6 2.51.7 2.51.8 2.51.9 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19 3.2.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0
strong-testimonials / assets / public / js / lib / validate / additional-methods.js
strong-testimonials / assets / public / js / lib / validate Last commit date
localization 1 year ago additional-methods.js 1 year ago additional-methods.min.js 1 year ago jquery-validate.js 1 year ago jquery-validate.min.js 1 year ago
additional-methods.js
1505 lines
1 /*!
2 * jQuery Validation Plugin v1.21.0
3 *
4 * https://jqueryvalidation.org/
5 *
6 * Copyright (c) 2024 Jörn Zaefferer
7 * Released under the MIT license
8 */
9 (function( factory ) {
10 if ( typeof define === "function" && define.amd ) {
11 define( ["jquery", "./jquery.validate"], factory );
12 } else if (typeof module === "object" && module.exports) {
13 module.exports = factory( require( "jquery" ) );
14 } else {
15 factory( jQuery );
16 }
17 }(function( $ ) {
18
19 ( function() {
20
21 function stripHtml( value ) {
22
23 // Remove html tags and space chars
24 return value.replace( /<.[^<>]*?>/g, " " ).replace( /&nbsp;|&#160;/gi, " " )
25
26 // Remove punctuation
27 .replace( /[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "" );
28 }
29
30 $.validator.addMethod( "maxWords", function( value, element, params ) {
31 return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length <= params;
32 }, $.validator.format( "Please enter {0} words or less." ) );
33
34 $.validator.addMethod( "minWords", function( value, element, params ) {
35 return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length >= params;
36 }, $.validator.format( "Please enter at least {0} words." ) );
37
38 $.validator.addMethod( "rangeWords", function( value, element, params ) {
39 var valueStripped = stripHtml( value ),
40 regex = /\b\w+\b/g;
41 return this.optional( element ) || valueStripped.match( regex ).length >= params[ 0 ] && valueStripped.match( regex ).length <= params[ 1 ];
42 }, $.validator.format( "Please enter between {0} and {1} words." ) );
43
44 }() );
45
46 /**
47 * This is used in the United States to process payments, deposits,
48 * or transfers using the Automated Clearing House (ACH) or Fedwire
49 * systems. A very common use case would be to validate a form for
50 * an ACH bill payment.
51 */
52 $.validator.addMethod( "abaRoutingNumber", function( value ) {
53 var checksum = 0;
54 var tokens = value.split( "" );
55 var length = tokens.length;
56
57 // Length Check
58 if ( length !== 9 ) {
59 return false;
60 }
61
62 // Calc the checksum
63 // https://en.wikipedia.org/wiki/ABA_routing_transit_number
64 for ( var i = 0; i < length; i += 3 ) {
65 checksum += parseInt( tokens[ i ], 10 ) * 3 +
66 parseInt( tokens[ i + 1 ], 10 ) * 7 +
67 parseInt( tokens[ i + 2 ], 10 );
68 }
69
70 // If not zero and divisible by 10 then valid
71 if ( checksum !== 0 && checksum % 10 === 0 ) {
72 return true;
73 }
74
75 return false;
76 }, "Please enter a valid routing number." );
77
78 // Accept a value from a file input based on a required mimetype
79 $.validator.addMethod( "accept", function( value, element, param ) {
80
81 // Split mime on commas in case we have multiple types we can accept
82 var typeParam = typeof param === "string" ? param.replace( /\s/g, "" ) : "image/*",
83 optionalValue = this.optional( element ),
84 i, file, regex;
85
86 // Element is optional
87 if ( optionalValue ) {
88 return optionalValue;
89 }
90
91 if ( $( element ).attr( "type" ) === "file" ) {
92
93 // Escape string to be used in the regex
94 // see: https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
95 // Escape also "/*" as "/.*" as a wildcard
96 typeParam = typeParam
97 .replace( /[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, "\\$&" )
98 .replace( /,/g, "|" )
99 .replace( /\/\*/g, "/.*" );
100
101 // Check if the element has a FileList before checking each file
102 if ( element.files && element.files.length ) {
103 regex = new RegExp( ".?(" + typeParam + ")$", "i" );
104 for ( i = 0; i < element.files.length; i++ ) {
105 file = element.files[ i ];
106
107 // Grab the mimetype from the loaded file, verify it matches
108 if ( !file.type.match( regex ) ) {
109 return false;
110 }
111 }
112 }
113 }
114
115 // Either return true because we've validated each file, or because the
116 // browser does not support element.files and the FileList feature
117 return true;
118 }, $.validator.format( "Please enter a value with a valid mimetype." ) );
119
120 $.validator.addMethod( "alphanumeric", function( value, element ) {
121 return this.optional( element ) || /^\w+$/i.test( value );
122 }, "Letters, numbers, and underscores only please." );
123
124 /*
125 * Dutch bank account numbers (not 'giro' numbers) have 9 digits
126 * and pass the '11 check'.
127 * We accept the notation with spaces, as that is common.
128 * acceptable: 123456789 or 12 34 56 789
129 */
130 $.validator.addMethod( "bankaccountNL", function( value, element ) {
131 if ( this.optional( element ) ) {
132 return true;
133 }
134 if ( !( /^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test( value ) ) ) {
135 return false;
136 }
137
138 // Now '11 check'
139 var account = value.replace( / /g, "" ), // Remove spaces
140 sum = 0,
141 len = account.length,
142 pos, factor, digit;
143 for ( pos = 0; pos < len; pos++ ) {
144 factor = len - pos;
145 digit = account.substring( pos, pos + 1 );
146 sum = sum + factor * digit;
147 }
148 return sum % 11 === 0;
149 }, "Please specify a valid bank account number." );
150
151 $.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
152 return this.optional( element ) ||
153 ( $.validator.methods.bankaccountNL.call( this, value, element ) ) ||
154 ( $.validator.methods.giroaccountNL.call( this, value, element ) );
155 }, "Please specify a valid bank or giro account number." );
156
157 /**
158 * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
159 *
160 * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
161 *
162 * Validation is case-insensitive. Please make sure to normalize input yourself.
163 *
164 * BIC definition in detail:
165 * - First 4 characters - bank code (only letters)
166 * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
167 * - Next 2 characters - location code (letters and digits)
168 * a. shall not start with '0' or '1'
169 * b. second character must be a letter ('O' is not allowed) or digit ('0' for test (therefore not allowed), '1' denoting passive participant, '2' typically reverse-billing)
170 * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
171 */
172 $.validator.addMethod( "bic", function( value, element ) {
173 return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() );
174 }, "Please specify a valid BIC code." );
175
176 /*
177 * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
178 * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
179 *
180 * Spanish CIF structure:
181 *
182 * [ T ][ P ][ P ][ N ][ N ][ N ][ N ][ N ][ C ]
183 *
184 * Where:
185 *
186 * T: 1 character. Kind of Organization Letter: [ABCDEFGHJKLMNPQRSUVW]
187 * P: 2 characters. Province.
188 * N: 5 characters. Secuencial Number within the province.
189 * C: 1 character. Control Digit: [0-9A-J].
190 *
191 * [ T ]: Kind of Organizations. Possible values:
192 *
193 * A. Corporations
194 * B. LLCs
195 * C. General partnerships
196 * D. Companies limited partnerships
197 * E. Communities of goods
198 * F. Cooperative Societies
199 * G. Associations
200 * H. Communities of homeowners in horizontal property regime
201 * J. Civil Societies
202 * K. Old format
203 * L. Old format
204 * M. Old format
205 * N. Nonresident entities
206 * P. Local authorities
207 * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
208 * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
209 * S. Organs of State Administration and regions
210 * V. Agrarian Transformation
211 * W. Permanent establishments of non-resident in Spain
212 *
213 * [ C ]: Control Digit. It can be a number or a letter depending on T value:
214 * [ T ] --> [ C ]
215 * ------ ----------
216 * A Number
217 * B Number
218 * E Number
219 * H Number
220 * K Letter
221 * P Letter
222 * Q Letter
223 * S Letter
224 *
225 */
226 $.validator.addMethod( "cifES", function( value, element ) {
227 "use strict";
228
229 if ( this.optional( element ) ) {
230 return true;
231 }
232
233 var cifRegEx = new RegExp( /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/gi );
234 var letter = value.substring( 0, 1 ), // [ T ]
235 number = value.substring( 1, 8 ), // [ P ][ P ][ N ][ N ][ N ][ N ][ N ]
236 control = value.substring( 8, 9 ), // [ C ]
237 all_sum = 0,
238 even_sum = 0,
239 odd_sum = 0,
240 i, n,
241 control_digit,
242 control_letter;
243
244 function isOdd( n ) {
245 return n % 2 === 0;
246 }
247
248 // Quick format test
249 if ( value.length !== 9 || !cifRegEx.test( value ) ) {
250 return false;
251 }
252
253 for ( i = 0; i < number.length; i++ ) {
254 n = parseInt( number[ i ], 10 );
255
256 // Odd positions
257 if ( isOdd( i ) ) {
258
259 // Odd positions are multiplied first.
260 n *= 2;
261
262 // If the multiplication is bigger than 10 we need to adjust
263 odd_sum += n < 10 ? n : n - 9;
264
265 // Even positions
266 // Just sum them
267 } else {
268 even_sum += n;
269 }
270 }
271
272 all_sum = even_sum + odd_sum;
273 control_digit = ( 10 - ( all_sum ).toString().substr( -1 ) ).toString();
274 control_digit = parseInt( control_digit, 10 ) > 9 ? "0" : control_digit;
275 control_letter = "JABCDEFGHI".substr( control_digit, 1 ).toString();
276
277 // Control must be a digit
278 if ( letter.match( /[ABEH]/ ) ) {
279 return control === control_digit;
280
281 // Control must be a letter
282 } else if ( letter.match( /[KPQS]/ ) ) {
283 return control === control_letter;
284 }
285
286 // Can be either
287 return control === control_digit || control === control_letter;
288
289 }, "Please specify a valid CIF number." );
290
291 /*
292 * Brazillian CNH number (Carteira Nacional de Habilitacao) is the License Driver number.
293 * CNH numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
294 */
295 $.validator.addMethod( "cnhBR", function( value ) {
296
297 // Removing special characters from value
298 value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
299
300 // Checking value to have 11 digits only
301 if ( value.length !== 11 ) {
302 return false;
303 }
304
305 var sum = 0, dsc = 0, firstChar,
306 firstCN, secondCN, i, j, v;
307
308 firstChar = value.charAt( 0 );
309
310 if ( new Array( 12 ).join( firstChar ) === value ) {
311 return false;
312 }
313
314 // Step 1 - using first Check Number:
315 for ( i = 0, j = 9, v = 0; i < 9; ++i, --j ) {
316 sum += +( value.charAt( i ) * j );
317 }
318
319 firstCN = sum % 11;
320 if ( firstCN >= 10 ) {
321 firstCN = 0;
322 dsc = 2;
323 }
324
325 sum = 0;
326 for ( i = 0, j = 1, v = 0; i < 9; ++i, ++j ) {
327 sum += +( value.charAt( i ) * j );
328 }
329
330 secondCN = sum % 11;
331 if ( secondCN >= 10 ) {
332 secondCN = 0;
333 } else {
334 secondCN = secondCN - dsc;
335 }
336
337 return ( String( firstCN ).concat( secondCN ) === value.substr( -2 ) );
338
339 }, "Please specify a valid CNH number." );
340
341 /*
342 * Brazillian value number (Cadastrado de Pessoas Juridica).
343 * value numbers have 14 digits in total: 12 numbers followed by 2 check numbers that are being used for validation.
344 */
345 $.validator.addMethod( "cnpjBR", function( value, element ) {
346 "use strict";
347
348 if ( this.optional( element ) ) {
349 return true;
350 }
351
352 // Removing no number
353 value = value.replace( /[^\d]+/g, "" );
354
355 // Checking value to have 14 digits only
356 if ( value.length !== 14 ) {
357 return false;
358 }
359
360 // Elimina values invalidos conhecidos
361 if ( value === "00000000000000" ||
362 value === "11111111111111" ||
363 value === "22222222222222" ||
364 value === "33333333333333" ||
365 value === "44444444444444" ||
366 value === "55555555555555" ||
367 value === "66666666666666" ||
368 value === "77777777777777" ||
369 value === "88888888888888" ||
370 value === "99999999999999" ) {
371 return false;
372 }
373
374 // Valida DVs
375 var tamanho = ( value.length - 2 );
376 var numeros = value.substring( 0, tamanho );
377 var digitos = value.substring( tamanho );
378 var soma = 0;
379 var pos = tamanho - 7;
380
381 for ( var i = tamanho; i >= 1; i-- ) {
382 soma += numeros.charAt( tamanho - i ) * pos--;
383 if ( pos < 2 ) {
384 pos = 9;
385 }
386 }
387
388 var resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
389
390 if ( resultado !== parseInt( digitos.charAt( 0 ), 10 ) ) {
391 return false;
392 }
393
394 tamanho = tamanho + 1;
395 numeros = value.substring( 0, tamanho );
396 soma = 0;
397 pos = tamanho - 7;
398
399 for ( var il = tamanho; il >= 1; il-- ) {
400 soma += numeros.charAt( tamanho - il ) * pos--;
401 if ( pos < 2 ) {
402 pos = 9;
403 }
404 }
405
406 resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
407
408 if ( resultado !== parseInt( digitos.charAt( 1 ), 10 ) ) {
409 return false;
410 }
411
412 return true;
413
414 }, "Please specify a CNPJ value number." );
415
416 /*
417 * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
418 * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
419 */
420 $.validator.addMethod( "cpfBR", function( value, element ) {
421 "use strict";
422
423 if ( this.optional( element ) ) {
424 return true;
425 }
426
427 // Removing special characters from value
428 value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
429
430 // Checking value to have 11 digits only
431 if ( value.length !== 11 ) {
432 return false;
433 }
434
435 var sum = 0,
436 firstCN, secondCN, checkResult, i;
437
438 firstCN = parseInt( value.substring( 9, 10 ), 10 );
439 secondCN = parseInt( value.substring( 10, 11 ), 10 );
440
441 checkResult = function( sum, cn ) {
442 var result = ( sum * 10 ) % 11;
443 if ( ( result === 10 ) || ( result === 11 ) ) {
444 result = 0;
445 }
446 return ( result === cn );
447 };
448
449 // Checking for dump data
450 if ( value === "" ||
451 value === "00000000000" ||
452 value === "11111111111" ||
453 value === "22222222222" ||
454 value === "33333333333" ||
455 value === "44444444444" ||
456 value === "55555555555" ||
457 value === "66666666666" ||
458 value === "77777777777" ||
459 value === "88888888888" ||
460 value === "99999999999"
461 ) {
462 return false;
463 }
464
465 // Step 1 - using first Check Number:
466 for ( i = 1; i <= 9; i++ ) {
467 sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 11 - i );
468 }
469
470 // If first Check Number (CN) is valid, move to Step 2 - using second Check Number:
471 if ( checkResult( sum, firstCN ) ) {
472 sum = 0;
473 for ( i = 1; i <= 10; i++ ) {
474 sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 12 - i );
475 }
476 return checkResult( sum, secondCN );
477 }
478 return false;
479
480 }, "Please specify a valid CPF number." );
481
482 // https://jqueryvalidation.org/creditcard-method/
483 // based on https://en.wikipedia.org/wiki/Luhn_algorithm
484 $.validator.addMethod( "creditcard", function( value, element ) {
485 if ( this.optional( element ) ) {
486 return "dependency-mismatch";
487 }
488
489 // Accept only spaces, digits and dashes
490 if ( /[^0-9 \-]+/.test( value ) ) {
491 return false;
492 }
493
494 var nCheck = 0,
495 nDigit = 0,
496 bEven = false,
497 n, cDigit;
498
499 value = value.replace( /\D/g, "" );
500
501 // Basing min and max length on
502 // https://dev.ean.com/general-info/valid-card-types/
503 if ( value.length < 13 || value.length > 19 ) {
504 return false;
505 }
506
507 for ( n = value.length - 1; n >= 0; n-- ) {
508 cDigit = value.charAt( n );
509 nDigit = parseInt( cDigit, 10 );
510 if ( bEven ) {
511 if ( ( nDigit *= 2 ) > 9 ) {
512 nDigit -= 9;
513 }
514 }
515
516 nCheck += nDigit;
517 bEven = !bEven;
518 }
519
520 return ( nCheck % 10 ) === 0;
521 }, "Please enter a valid credit card number." );
522
523 /* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
524 * Redistributed under the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
525 * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
526 */
527 $.validator.addMethod( "creditcardtypes", function( value, element, param ) {
528 if ( /[^0-9\-]+/.test( value ) ) {
529 return false;
530 }
531
532 value = value.replace( /\D/g, "" );
533
534 var validTypes = 0x0000;
535
536 if ( param.mastercard ) {
537 validTypes |= 0x0001;
538 }
539 if ( param.visa ) {
540 validTypes |= 0x0002;
541 }
542 if ( param.amex ) {
543 validTypes |= 0x0004;
544 }
545 if ( param.dinersclub ) {
546 validTypes |= 0x0008;
547 }
548 if ( param.enroute ) {
549 validTypes |= 0x0010;
550 }
551 if ( param.discover ) {
552 validTypes |= 0x0020;
553 }
554 if ( param.jcb ) {
555 validTypes |= 0x0040;
556 }
557 if ( param.unknown ) {
558 validTypes |= 0x0080;
559 }
560 if ( param.all ) {
561 validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
562 }
563 if ( validTypes & 0x0001 && ( /^(5[12345])/.test( value ) || /^(2[234567])/.test( value ) ) ) { // Mastercard
564 return value.length === 16;
565 }
566 if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa
567 return value.length === 16;
568 }
569 if ( validTypes & 0x0004 && /^(3[47])/.test( value ) ) { // Amex
570 return value.length === 15;
571 }
572 if ( validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test( value ) ) { // Dinersclub
573 return value.length === 14;
574 }
575 if ( validTypes & 0x0010 && /^(2(014|149))/.test( value ) ) { // Enroute
576 return value.length === 15;
577 }
578 if ( validTypes & 0x0020 && /^(6011)/.test( value ) ) { // Discover
579 return value.length === 16;
580 }
581 if ( validTypes & 0x0040 && /^(3)/.test( value ) ) { // Jcb
582 return value.length === 16;
583 }
584 if ( validTypes & 0x0040 && /^(2131|1800)/.test( value ) ) { // Jcb
585 return value.length === 15;
586 }
587 if ( validTypes & 0x0080 ) { // Unknown
588 return true;
589 }
590 return false;
591 }, "Please enter a valid credit card number." );
592
593 /**
594 * Validates currencies with any given symbols by @jameslouiz
595 * Symbols can be optional or required. Symbols required by default
596 *
597 * Usage examples:
598 * currency: ["£", false] - Use false for soft currency validation
599 * currency: ["$", false]
600 * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
601 *
602 * <input class="currencyInput" name="currencyInput">
603 *
604 * Soft symbol checking
605 * currencyInput: {
606 * currency: ["$", false]
607 * }
608 *
609 * Strict symbol checking (default)
610 * currencyInput: {
611 * currency: "$"
612 * //OR
613 * currency: ["$", true]
614 * }
615 *
616 * Multiple Symbols
617 * currencyInput: {
618 * currency: "$,£,¢"
619 * }
620 */
621 $.validator.addMethod( "currency", function( value, element, param ) {
622 var isParamString = typeof param === "string",
623 symbol = isParamString ? param : param[ 0 ],
624 soft = isParamString ? true : param[ 1 ],
625 regex;
626
627 symbol = symbol.replace( /,/g, "" );
628 symbol = soft ? symbol + "]" : symbol + "]?";
629 regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$";
630 regex = new RegExp( regex );
631 return this.optional( element ) || regex.test( value );
632
633 }, "Please specify a valid currency." );
634
635 $.validator.addMethod( "dateFA", function( value, element ) {
636 return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value );
637 }, $.validator.messages.date );
638
639 /**
640 * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
641 *
642 * @example $.validator.methods.date("01/01/1900")
643 * @result true
644 *
645 * @example $.validator.methods.date("01/13/1990")
646 * @result false
647 *
648 * @example $.validator.methods.date("01.01.1900")
649 * @result false
650 *
651 * @example <input name="pippo" class="{dateITA:true}" />
652 * @desc Declares an optional input element whose value must be a valid date.
653 *
654 * @name $.validator.methods.dateITA
655 * @type Boolean
656 * @cat Plugins/Validate/Methods
657 */
658 $.validator.addMethod( "dateITA", function( value, element ) {
659 var check = false,
660 re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
661 adata, gg, mm, aaaa, xdata;
662 if ( re.test( value ) ) {
663 adata = value.split( "/" );
664 gg = parseInt( adata[ 0 ], 10 );
665 mm = parseInt( adata[ 1 ], 10 );
666 aaaa = parseInt( adata[ 2 ], 10 );
667 xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) );
668 if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
669 check = true;
670 } else {
671 check = false;
672 }
673 } else {
674 check = false;
675 }
676 return this.optional( element ) || check;
677 }, $.validator.messages.date );
678
679 $.validator.addMethod( "dateNL", function( value, element ) {
680 return this.optional( element ) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test( value );
681 }, $.validator.messages.date );
682
683 // Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
684 $.validator.addMethod( "extension", function( value, element, param ) {
685 param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif";
686 return this.optional( element ) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) );
687 }, $.validator.format( "Please enter a value with a valid extension." ) );
688
689 /**
690 * Dutch giro account numbers (not bank numbers) have max 7 digits
691 */
692 $.validator.addMethod( "giroaccountNL", function( value, element ) {
693 return this.optional( element ) || /^[0-9]{1,7}$/.test( value );
694 }, "Please specify a valid giro account number." );
695
696 $.validator.addMethod( "greaterThan", function( value, element, param ) {
697 var target = $( param );
698
699 if ( this.settings.onfocusout && target.not( ".validate-greaterThan-blur" ).length ) {
700 target.addClass( "validate-greaterThan-blur" ).on( "blur.validate-greaterThan", function() {
701 $( element ).valid();
702 } );
703 }
704
705 return value > target.val();
706 }, "Please enter a greater value." );
707
708 $.validator.addMethod( "greaterThanEqual", function( value, element, param ) {
709 var target = $( param );
710
711 if ( this.settings.onfocusout && target.not( ".validate-greaterThanEqual-blur" ).length ) {
712 target.addClass( "validate-greaterThanEqual-blur" ).on( "blur.validate-greaterThanEqual", function() {
713 $( element ).valid();
714 } );
715 }
716
717 return value >= target.val();
718 }, "Please enter a greater value." );
719
720 /**
721 * IBAN is the international bank account number.
722 * It has a country - specific format, that is checked here too
723 *
724 * Validation is case-insensitive. Please make sure to normalize input yourself.
725 */
726 $.validator.addMethod( "iban", function( value, element ) {
727
728 // Some quick simple tests to prevent needless work
729 if ( this.optional( element ) ) {
730 return true;
731 }
732
733 // Remove spaces and to upper case
734 var iban = value.replace( / /g, "" ).toUpperCase(),
735 ibancheckdigits = "",
736 leadingZeroes = true,
737 cRest = "",
738 cOperator = "",
739 countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
740
741 // Check for IBAN code length.
742 // It contains:
743 // country code ISO 3166-1 - two letters,
744 // two check digits,
745 // Basic Bank Account Number (BBAN) - up to 30 chars
746 var minimalIBANlength = 5;
747 if ( iban.length < minimalIBANlength ) {
748 return false;
749 }
750
751 // Check the country code and find the country specific format
752 countrycode = iban.substring( 0, 2 );
753 bbancountrypatterns = {
754 "AL": "\\d{8}[\\dA-Z]{16}",
755 "AD": "\\d{8}[\\dA-Z]{12}",
756 "AT": "\\d{16}",
757 "AZ": "[\\dA-Z]{4}\\d{20}",
758 "BE": "\\d{12}",
759 "BH": "[A-Z]{4}[\\dA-Z]{14}",
760 "BA": "\\d{16}",
761 "BR": "\\d{23}[A-Z][\\dA-Z]",
762 "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
763 "CR": "\\d{17}",
764 "HR": "\\d{17}",
765 "CY": "\\d{8}[\\dA-Z]{16}",
766 "CZ": "\\d{20}",
767 "DK": "\\d{14}",
768 "DO": "[A-Z]{4}\\d{20}",
769 "EE": "\\d{16}",
770 "FO": "\\d{14}",
771 "FI": "\\d{14}",
772 "FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
773 "GE": "[\\dA-Z]{2}\\d{16}",
774 "DE": "\\d{18}",
775 "GI": "[A-Z]{4}[\\dA-Z]{15}",
776 "GR": "\\d{7}[\\dA-Z]{16}",
777 "GL": "\\d{14}",
778 "GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
779 "HU": "\\d{24}",
780 "IS": "\\d{22}",
781 "IE": "[\\dA-Z]{4}\\d{14}",
782 "IL": "\\d{19}",
783 "IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
784 "KZ": "\\d{3}[\\dA-Z]{13}",
785 "KW": "[A-Z]{4}[\\dA-Z]{22}",
786 "LV": "[A-Z]{4}[\\dA-Z]{13}",
787 "LB": "\\d{4}[\\dA-Z]{20}",
788 "LI": "\\d{5}[\\dA-Z]{12}",
789 "LT": "\\d{16}",
790 "LU": "\\d{3}[\\dA-Z]{13}",
791 "MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
792 "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
793 "MR": "\\d{23}",
794 "MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
795 "MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
796 "MD": "[\\dA-Z]{2}\\d{18}",
797 "ME": "\\d{18}",
798 "NL": "[A-Z]{4}\\d{10}",
799 "NO": "\\d{11}",
800 "PK": "[\\dA-Z]{4}\\d{16}",
801 "PS": "[\\dA-Z]{4}\\d{21}",
802 "PL": "\\d{24}",
803 "PT": "\\d{21}",
804 "RO": "[A-Z]{4}[\\dA-Z]{16}",
805 "SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
806 "SA": "\\d{2}[\\dA-Z]{18}",
807 "RS": "\\d{18}",
808 "SK": "\\d{20}",
809 "SI": "\\d{15}",
810 "ES": "\\d{20}",
811 "SE": "\\d{20}",
812 "CH": "\\d{5}[\\dA-Z]{12}",
813 "TN": "\\d{20}",
814 "TR": "\\d{5}[\\dA-Z]{17}",
815 "AE": "\\d{3}\\d{16}",
816 "GB": "[A-Z]{4}\\d{14}",
817 "VG": "[\\dA-Z]{4}\\d{16}"
818 };
819
820 bbanpattern = bbancountrypatterns[ countrycode ];
821
822 // As new countries will start using IBAN in the
823 // future, we only check if the countrycode is known.
824 // This prevents false negatives, while almost all
825 // false positives introduced by this, will be caught
826 // by the checksum validation below anyway.
827 // Strict checking should return FALSE for unknown
828 // countries.
829 if ( typeof bbanpattern !== "undefined" ) {
830 ibanregexp = new RegExp( "^[A-Z]{2}\\d{2}" + bbanpattern + "$", "" );
831 if ( !( ibanregexp.test( iban ) ) ) {
832 return false; // Invalid country specific format
833 }
834 }
835
836 // Now check the checksum, first convert to digits
837 ibancheck = iban.substring( 4, iban.length ) + iban.substring( 0, 4 );
838 for ( i = 0; i < ibancheck.length; i++ ) {
839 charAt = ibancheck.charAt( i );
840 if ( charAt !== "0" ) {
841 leadingZeroes = false;
842 }
843 if ( !leadingZeroes ) {
844 ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf( charAt );
845 }
846 }
847
848 // Calculate the result of: ibancheckdigits % 97
849 for ( p = 0; p < ibancheckdigits.length; p++ ) {
850 cChar = ibancheckdigits.charAt( p );
851 cOperator = "" + cRest + "" + cChar;
852 cRest = cOperator % 97;
853 }
854 return cRest === 1;
855 }, "Please specify a valid IBAN." );
856
857 $.validator.addMethod( "integer", function( value, element ) {
858 return this.optional( element ) || /^-?\d+$/.test( value );
859 }, "A positive or negative non-decimal number please." );
860
861 $.validator.addMethod( "ipv4", function( value, element ) {
862 return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value );
863 }, "Please enter a valid IP v4 address." );
864
865 $.validator.addMethod( "ipv6", function( value, element ) {
866 return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value );
867 }, "Please enter a valid IP v6 address." );
868
869 $.validator.addMethod( "lessThan", function( value, element, param ) {
870 var target = $( param );
871
872 if ( this.settings.onfocusout && target.not( ".validate-lessThan-blur" ).length ) {
873 target.addClass( "validate-lessThan-blur" ).on( "blur.validate-lessThan", function() {
874 $( element ).valid();
875 } );
876 }
877
878 return value < target.val();
879 }, "Please enter a lesser value." );
880
881 $.validator.addMethod( "lessThanEqual", function( value, element, param ) {
882 var target = $( param );
883
884 if ( this.settings.onfocusout && target.not( ".validate-lessThanEqual-blur" ).length ) {
885 target.addClass( "validate-lessThanEqual-blur" ).on( "blur.validate-lessThanEqual", function() {
886 $( element ).valid();
887 } );
888 }
889
890 return value <= target.val();
891 }, "Please enter a lesser value." );
892
893 $.validator.addMethod( "lettersonly", function( value, element ) {
894 return this.optional( element ) || /^[a-z]+$/i.test( value );
895 }, "Letters only please." );
896
897 $.validator.addMethod( "letterswithbasicpunc", function( value, element ) {
898 return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value );
899 }, "Letters or punctuation only please." );
900
901 // Limit the number of files in a FileList.
902 $.validator.addMethod( "maxfiles", function( value, element, param ) {
903 if ( this.optional( element ) ) {
904 return true;
905 }
906
907 if ( $( element ).attr( "type" ) === "file" ) {
908 if ( element.files && element.files.length > param ) {
909 return false;
910 }
911 }
912
913 return true;
914 }, $.validator.format( "Please select no more than {0} files." ) );
915
916 // Limit the size of each individual file in a FileList.
917 $.validator.addMethod( "maxsize", function( value, element, param ) {
918 if ( this.optional( element ) ) {
919 return true;
920 }
921
922 if ( $( element ).attr( "type" ) === "file" ) {
923 if ( element.files && element.files.length ) {
924 for ( var i = 0; i < element.files.length; i++ ) {
925 if ( element.files[ i ].size > param ) {
926 return false;
927 }
928 }
929 }
930 }
931
932 return true;
933 }, $.validator.format( "File size must not exceed {0} bytes each." ) );
934
935 // Limit the size of all files in a FileList.
936 $.validator.addMethod( "maxsizetotal", function( value, element, param ) {
937 if ( this.optional( element ) ) {
938 return true;
939 }
940
941 if ( $( element ).attr( "type" ) === "file" ) {
942 if ( element.files && element.files.length ) {
943 var totalSize = 0;
944
945 for ( var i = 0; i < element.files.length; i++ ) {
946 totalSize += element.files[ i ].size;
947 if ( totalSize > param ) {
948 return false;
949 }
950 }
951 }
952 }
953
954 return true;
955 }, $.validator.format( "Total size of all files must not exceed {0} bytes." ) );
956
957
958 $.validator.addMethod( "mobileNL", function( value, element ) {
959 return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
960 }, "Please specify a valid mobile number." );
961
962 $.validator.addMethod( "mobileRU", function( phone_number, element ) {
963 var ruPhone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
964 return this.optional( element ) || ruPhone_number.length > 9 && /^((\+7|7|8)+([0-9]){10})$/.test( ruPhone_number );
965 }, "Please specify a valid mobile number." );
966
967 /* For UK phone functions, do the following server side processing:
968 * Compare original input with this RegEx pattern:
969 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
970 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
971 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
972 * A number of very detailed GB telephone number RegEx patterns can also be found at:
973 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
974 */
975 $.validator.addMethod( "mobileUK", function( phone_number, element ) {
976 phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
977 return this.optional( element ) || phone_number.length > 9 &&
978 phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ );
979 }, "Please specify a valid mobile number." );
980
981 $.validator.addMethod( "netmask", function( value, element ) {
982 return this.optional( element ) || /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test( value );
983 }, "Please enter a valid netmask." );
984
985 /*
986 * The NIE (Número de Identificación de Extranjero) is a Spanish tax identification number assigned by the Spanish
987 * authorities to any foreigner.
988 *
989 * The NIE is the equivalent of a Spaniards Número de Identificación Fiscal (NIF) which serves as a fiscal
990 * identification number. The CIF number (Certificado de Identificación Fiscal) is equivalent to the NIF, but applies to
991 * companies rather than individuals. The NIE consists of an 'X' or 'Y' followed by 7 or 8 digits then another letter.
992 */
993 $.validator.addMethod( "nieES", function( value, element ) {
994 "use strict";
995
996 if ( this.optional( element ) ) {
997 return true;
998 }
999
1000 var nieRegEx = new RegExp( /^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi );
1001 var validChars = "TRWAGMYFPDXBNJZSQVHLCKET",
1002 letter = value.substr( value.length - 1 ).toUpperCase(),
1003 number;
1004
1005 value = value.toString().toUpperCase();
1006
1007 // Quick format test
1008 if ( value.length > 10 || value.length < 9 || !nieRegEx.test( value ) ) {
1009 return false;
1010 }
1011
1012 // X means same number
1013 // Y means number + 10000000
1014 // Z means number + 20000000
1015 value = value.replace( /^[X]/, "0" )
1016 .replace( /^[Y]/, "1" )
1017 .replace( /^[Z]/, "2" );
1018
1019 number = value.length === 9 ? value.substr( 0, 8 ) : value.substr( 0, 9 );
1020
1021 return validChars.charAt( parseInt( number, 10 ) % 23 ) === letter;
1022
1023 }, "Please specify a valid NIE number." );
1024
1025 /*
1026 * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
1027 */
1028 $.validator.addMethod( "nifES", function( value, element ) {
1029 "use strict";
1030
1031 if ( this.optional( element ) ) {
1032 return true;
1033 }
1034
1035 value = value.toUpperCase();
1036
1037 // Basic format test
1038 if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
1039 return false;
1040 }
1041
1042 // Test NIF
1043 if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
1044 return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
1045 }
1046
1047 // Test specials NIF (starts with K, L or M)
1048 if ( /^[KLM]{1}/.test( value ) ) {
1049 return ( value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 1 ) % 23 ) );
1050 }
1051
1052 return false;
1053
1054 }, "Please specify a valid NIF number." );
1055
1056 /*
1057 * Numer identyfikacji podatkowej ( NIP ) is the way tax identification used in Poland for companies
1058 */
1059 $.validator.addMethod( "nipPL", function( value ) {
1060 "use strict";
1061
1062 value = value.replace( /[^0-9]/g, "" );
1063
1064 if ( value.length !== 10 ) {
1065 return false;
1066 }
1067
1068 var arrSteps = [ 6, 5, 7, 2, 3, 4, 5, 6, 7 ];
1069 var intSum = 0;
1070 for ( var i = 0; i < 9; i++ ) {
1071 intSum += arrSteps[ i ] * value[ i ];
1072 }
1073 var int2 = intSum % 11;
1074 var intControlNr = ( int2 === 10 ) ? 0 : int2;
1075
1076 return ( intControlNr === parseInt( value[ 9 ], 10 ) );
1077 }, "Please specify a valid NIP number." );
1078
1079 /**
1080 * Created for project jquery-validation.
1081 * @Description Brazillian PIS or NIS number (Número de Identificação Social Pis ou Pasep) is the equivalent of a
1082 * Brazilian tax registration number NIS of PIS numbers have 11 digits in total: 10 numbers followed by 1 check numbers
1083 * that are being used for validation.
1084 * @copyright (c) 21/08/2018 13:14, Cleiton da Silva Mendonça
1085 * @author Cleiton da Silva Mendonça <cleiton.mendonca@gmail.com>
1086 * @link http://gitlab.com/csmendonca Gitlab of Cleiton da Silva Mendonça
1087 * @link http://github.com/csmendonca Github of Cleiton da Silva Mendonça
1088 */
1089 $.validator.addMethod( "nisBR", function( value ) {
1090 var number;
1091 var cn;
1092 var sum = 0;
1093 var dv;
1094 var count;
1095 var multiplier;
1096
1097 // Removing special characters from value
1098 value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
1099
1100 // Checking value to have 11 digits only
1101 if ( value.length !== 11 ) {
1102 return false;
1103 }
1104
1105 //Get check number of value
1106 cn = parseInt( value.substring( 10, 11 ), 10 );
1107
1108 //Get number with 10 digits of the value
1109 number = parseInt( value.substring( 0, 10 ), 10 );
1110
1111 for ( count = 2; count < 12; count++ ) {
1112 multiplier = count;
1113 if ( count === 10 ) {
1114 multiplier = 2;
1115 }
1116 if ( count === 11 ) {
1117 multiplier = 3;
1118 }
1119 sum += ( ( number % 10 ) * multiplier );
1120 number = parseInt( number / 10, 10 );
1121 }
1122 dv = ( sum % 11 );
1123
1124 if ( dv > 1 ) {
1125 dv = ( 11 - dv );
1126 } else {
1127 dv = 0;
1128 }
1129
1130 if ( cn === dv ) {
1131 return true;
1132 } else {
1133 return false;
1134 }
1135 }, "Please specify a valid NIS/PIS number." );
1136
1137 $.validator.addMethod( "notEqualTo", function( value, element, param ) {
1138 return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param );
1139 }, "Please enter a different value, values must not be the same." );
1140
1141 $.validator.addMethod( "nowhitespace", function( value, element ) {
1142 return this.optional( element ) || /^\S+$/i.test( value );
1143 }, "No white space please." );
1144
1145 /**
1146 * Return true if the field value matches the given format RegExp
1147 *
1148 * @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
1149 * @result true
1150 *
1151 * @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
1152 * @result false
1153 *
1154 * @name $.validator.methods.pattern
1155 * @type Boolean
1156 * @cat Plugins/Validate/Methods
1157 */
1158 $.validator.addMethod( "pattern", function( value, element, param ) {
1159 if ( this.optional( element ) ) {
1160 return true;
1161 }
1162 if ( typeof param === "string" ) {
1163 param = new RegExp( "^(?:" + param + ")$" );
1164 }
1165 return param.test( value );
1166 }, "Invalid format." );
1167
1168 /**
1169 * Dutch phone numbers have 10 digits (or 11 and start with +31).
1170 */
1171 $.validator.addMethod( "phoneNL", function( value, element ) {
1172 return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
1173 }, "Please specify a valid phone number." );
1174
1175 /**
1176 * Polish telephone numbers have 9 digits.
1177 *
1178 * Mobile phone numbers starts with following digits:
1179 * 45, 50, 51, 53, 57, 60, 66, 69, 72, 73, 78, 79, 88.
1180 *
1181 * Fixed-line numbers starts with area codes:
1182 * 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 29, 32, 33,
1183 * 34, 41, 42, 43, 44, 46, 48, 52, 54, 55, 56, 58, 59, 61,
1184 * 62, 63, 65, 67, 68, 71, 74, 75, 76, 77, 81, 82, 83, 84,
1185 * 85, 86, 87, 89, 91, 94, 95.
1186 *
1187 * Ministry of National Defence numbers and VoIP numbers starts with 26 and 39.
1188 *
1189 * Excludes intelligent networks (premium rate, shared cost, free phone numbers).
1190 *
1191 * Poland National Numbering Plan http://www.itu.int/oth/T02020000A8/en
1192 */
1193 $.validator.addMethod( "phonePL", function( phone_number, element ) {
1194 phone_number = phone_number.replace( /\s+/g, "" );
1195 var regexp = /^(?:(?:(?:\+|00)?48)|(?:\(\+?48\)))?(?:1[2-8]|2[2-69]|3[2-49]|4[1-68]|5[0-9]|6[0-35-9]|[7-8][1-9]|9[145])\d{7}$/;
1196 return this.optional( element ) || regexp.test( phone_number );
1197 }, "Please specify a valid phone number." );
1198
1199 /* For UK phone functions, do the following server side processing:
1200 * Compare original input with this RegEx pattern:
1201 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
1202 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
1203 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
1204 * A number of very detailed GB telephone number RegEx patterns can also be found at:
1205 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
1206 */
1207
1208 // Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
1209 $.validator.addMethod( "phonesUK", function( phone_number, element ) {
1210 phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
1211 return this.optional( element ) || phone_number.length > 9 &&
1212 phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ );
1213 }, "Please specify a valid uk phone number." );
1214
1215 /* For UK phone functions, do the following server side processing:
1216 * Compare original input with this RegEx pattern:
1217 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
1218 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
1219 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
1220 * A number of very detailed GB telephone number RegEx patterns can also be found at:
1221 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
1222 */
1223 $.validator.addMethod( "phoneUK", function( phone_number, element ) {
1224 phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
1225 return this.optional( element ) || phone_number.length > 9 &&
1226 phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ );
1227 }, "Please specify a valid phone number." );
1228
1229 /**
1230 * Matches US phone number format
1231 *
1232 * where the area code may not start with 1 and the prefix may not start with 1
1233 * allows '-' or ' ' as a separator and allows parens around area code
1234 * some people may want to put a '1' in front of their number
1235 *
1236 * 1(212)-999-2345 or
1237 * 212 999 2344 or
1238 * 212-999-0983
1239 *
1240 * but not
1241 * 111-123-5434
1242 * and not
1243 * 212 123 4567
1244 */
1245 $.validator.addMethod( "phoneUS", function( phone_number, element ) {
1246 phone_number = phone_number.replace( /\s+/g, "" );
1247 return this.optional( element ) || phone_number.length > 9 &&
1248 phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]\d{2}-?\d{4}$/ );
1249 }, "Please specify a valid phone number." );
1250
1251 /*
1252 * Valida CEPs do brasileiros:
1253 *
1254 * Formatos aceitos:
1255 * 99999-999
1256 * 99.999-999
1257 * 99999999
1258 */
1259 $.validator.addMethod( "postalcodeBR", function( cep_value, element ) {
1260 return this.optional( element ) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
1261 }, "Informe um CEP válido." );
1262
1263 /**
1264 * Matches a valid Canadian Postal Code
1265 *
1266 * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
1267 * @result true
1268 *
1269 * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
1270 * @result false
1271 *
1272 * @name jQuery.validator.methods.postalCodeCA
1273 * @type Boolean
1274 * @cat Plugins/Validate/Methods
1275 */
1276 $.validator.addMethod( "postalCodeCA", function( value, element ) {
1277 return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value );
1278 }, "Please specify a valid postal code." );
1279
1280 /* Matches Italian postcode (CAP) */
1281 $.validator.addMethod( "postalcodeIT", function( value, element ) {
1282 return this.optional( element ) || /^\d{5}$/.test( value );
1283 }, "Please specify a valid postal code." );
1284
1285 $.validator.addMethod( "postalcodeNL", function( value, element ) {
1286 return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value );
1287 }, "Please specify a valid postal code." );
1288
1289 // Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
1290 $.validator.addMethod( "postcodeUK", function( value, element ) {
1291 return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value );
1292 }, "Please specify a valid UK postcode." );
1293
1294 /*
1295 * Lets you say "at least X inputs that match selector Y must be filled."
1296 *
1297 * The end result is that neither of these inputs:
1298 *
1299 * <input class="productinfo" name="partnumber">
1300 * <input class="productinfo" name="description">
1301 *
1302 * ...will validate unless at least one of them is filled.
1303 *
1304 * partnumber: {require_from_group: [1,".productinfo"]},
1305 * description: {require_from_group: [1,".productinfo"]}
1306 *
1307 * options[0]: number of fields that must be filled in the group
1308 * options[1]: CSS selector that defines the group of conditionally required fields
1309 */
1310 $.validator.addMethod( "require_from_group", function( value, element, options ) {
1311 var $fields = $( options[ 1 ], element.form ),
1312 $fieldsFirst = $fields.eq( 0 ),
1313 validator = $fieldsFirst.data( "valid_req_grp" ) ? $fieldsFirst.data( "valid_req_grp" ) : $.extend( {}, this ),
1314 isValid = $fields.filter( function() {
1315 return validator.elementValue( this );
1316 } ).length >= options[ 0 ];
1317
1318 // Store the cloned validator for future validation
1319 $fieldsFirst.data( "valid_req_grp", validator );
1320
1321 // If element isn't being validated, run each require_from_group field's validation rules
1322 if ( !$( element ).data( "being_validated" ) ) {
1323 $fields.data( "being_validated", true );
1324 $fields.each( function() {
1325 validator.element( this );
1326 } );
1327 $fields.data( "being_validated", false );
1328 }
1329 return isValid;
1330 }, $.validator.format( "Please fill at least {0} of these fields." ) );
1331
1332 /*
1333 * Lets you say "either at least X inputs that match selector Y must be filled,
1334 * OR they must all be skipped (left blank)."
1335 *
1336 * The end result, is that none of these inputs:
1337 *
1338 * <input class="productinfo" name="partnumber">
1339 * <input class="productinfo" name="description">
1340 * <input class="productinfo" name="color">
1341 *
1342 * ...will validate unless either at least two of them are filled,
1343 * OR none of them are.
1344 *
1345 * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
1346 * description: {skip_or_fill_minimum: [2,".productinfo"]},
1347 * color: {skip_or_fill_minimum: [2,".productinfo"]}
1348 *
1349 * options[0]: number of fields that must be filled in the group
1350 * options[1]: CSS selector that defines the group of conditionally required fields
1351 *
1352 */
1353 $.validator.addMethod( "skip_or_fill_minimum", function( value, element, options ) {
1354 var $fields = $( options[ 1 ], element.form ),
1355 $fieldsFirst = $fields.eq( 0 ),
1356 validator = $fieldsFirst.data( "valid_skip" ) ? $fieldsFirst.data( "valid_skip" ) : $.extend( {}, this ),
1357 numberFilled = $fields.filter( function() {
1358 return validator.elementValue( this );
1359 } ).length,
1360 isValid = numberFilled === 0 || numberFilled >= options[ 0 ];
1361
1362 // Store the cloned validator for future validation
1363 $fieldsFirst.data( "valid_skip", validator );
1364
1365 // If element isn't being validated, run each skip_or_fill_minimum field's validation rules
1366 if ( !$( element ).data( "being_validated" ) ) {
1367 $fields.data( "being_validated", true );
1368 $fields.each( function() {
1369 validator.element( this );
1370 } );
1371 $fields.data( "being_validated", false );
1372 }
1373 return isValid;
1374 }, $.validator.format( "Please either skip these fields or fill at least {0} of them." ) );
1375
1376 /* Validates US States and/or Territories by @jdforsythe
1377 * Can be case insensitive or require capitalization - default is case insensitive
1378 * Can include US Territories or not - default does not
1379 * Can include US Military postal abbreviations (AA, AE, AP) - default does not
1380 *
1381 * Note: "States" always includes DC (District of Colombia)
1382 *
1383 * Usage examples:
1384 *
1385 * This is the default - case insensitive, no territories, no military zones
1386 * stateInput: {
1387 * caseSensitive: false,
1388 * includeTerritories: false,
1389 * includeMilitary: false
1390 * }
1391 *
1392 * Only allow capital letters, no territories, no military zones
1393 * stateInput: {
1394 * caseSensitive: false
1395 * }
1396 *
1397 * Case insensitive, include territories but not military zones
1398 * stateInput: {
1399 * includeTerritories: true
1400 * }
1401 *
1402 * Only allow capital letters, include territories and military zones
1403 * stateInput: {
1404 * caseSensitive: true,
1405 * includeTerritories: true,
1406 * includeMilitary: true
1407 * }
1408 *
1409 */
1410 $.validator.addMethod( "stateUS", function( value, element, options ) {
1411 var isDefault = typeof options === "undefined",
1412 caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
1413 includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
1414 includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
1415 regex;
1416
1417 if ( !includeTerritories && !includeMilitary ) {
1418 regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
1419 } else if ( includeTerritories && includeMilitary ) {
1420 regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
1421 } else if ( includeTerritories ) {
1422 regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
1423 } else {
1424 regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
1425 }
1426
1427 regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" );
1428 return this.optional( element ) || regex.test( value );
1429 }, "Please specify a valid state." );
1430
1431 // TODO check if value starts with <, otherwise don't try stripping anything
1432 $.validator.addMethod( "strippedminlength", function( value, element, param ) {
1433 return $( value ).text().length >= param;
1434 }, $.validator.format( "Please enter at least {0} characters." ) );
1435
1436 $.validator.addMethod( "time", function( value, element ) {
1437 return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value );
1438 }, "Please enter a valid time, between 00:00 and 23:59." );
1439
1440 $.validator.addMethod( "time12h", function( value, element ) {
1441 return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
1442 }, "Please enter a valid time in 12-hour am/pm format." );
1443
1444 // Same as url, but TLD is optional
1445 $.validator.addMethod( "url2", function( value, element ) {
1446 return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?: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-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?)|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff])|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62}\.)))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
1447 }, $.validator.messages.url );
1448
1449 /**
1450 * Return true, if the value is a valid vehicle identification number (VIN).
1451 *
1452 * Works with all kind of text inputs.
1453 *
1454 * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
1455 * @desc Declares a required input element whose value must be a valid vehicle identification number.
1456 *
1457 * @name $.validator.methods.vinUS
1458 * @type Boolean
1459 * @cat Plugins/Validate/Methods
1460 */
1461 $.validator.addMethod( "vinUS", function( v ) {
1462 if ( v.length !== 17 ) {
1463 return false;
1464 }
1465
1466 var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ],
1467 VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
1468 FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
1469 rs = 0,
1470 i, n, d, f, cd, cdv;
1471
1472 for ( i = 0; i < 17; i++ ) {
1473 f = FL[ i ];
1474 d = v.slice( i, i + 1 );
1475 if ( isNaN( d ) ) {
1476 d = d.toUpperCase();
1477 n = VL[ LL.indexOf( d ) ];
1478 } else {
1479 n = parseInt( d, 10 );
1480 }
1481 if ( i === 8 )
1482 {
1483 cdv = n;
1484 if ( d === "X" ) {
1485 cdv = 10;
1486 }
1487 }
1488 rs += n * f;
1489 }
1490 cd = rs % 11;
1491 if ( cd === cdv ) {
1492 return true;
1493 }
1494 return false;
1495 }, "The specified vehicle identification number (VIN) is invalid." );
1496
1497 $.validator.addMethod( "zipcodeUS", function( value, element ) {
1498 return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value );
1499 }, "The specified US ZIP Code is invalid." );
1500
1501 $.validator.addMethod( "ziprange", function( value, element ) {
1502 return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value );
1503 }, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx." );
1504 return $;
1505 }));