jquery-validation-rails 1.13.1 → 1.15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +0 -1
  4. data/app/assets/javascripts/jquery.validate.additional-methods.js +1024 -908
  5. data/app/assets/javascripts/jquery.validate.js +1513 -1346
  6. data/app/assets/javascripts/jquery.validate.localization/messages_ar.js +8 -18
  7. data/app/assets/javascripts/jquery.validate.localization/messages_bg.js +8 -18
  8. data/app/assets/javascripts/jquery.validate.localization/messages_bn_BD.js +23 -0
  9. data/app/assets/javascripts/jquery.validate.localization/messages_ca.js +9 -19
  10. data/app/assets/javascripts/jquery.validate.localization/messages_cs.js +8 -18
  11. data/app/assets/javascripts/jquery.validate.localization/messages_da.js +8 -18
  12. data/app/assets/javascripts/jquery.validate.localization/messages_de.js +8 -18
  13. data/app/assets/javascripts/jquery.validate.localization/messages_el.js +8 -18
  14. data/app/assets/javascripts/jquery.validate.localization/messages_es.js +8 -18
  15. data/app/assets/javascripts/jquery.validate.localization/messages_es_AR.js +8 -18
  16. data/app/assets/javascripts/jquery.validate.localization/messages_es_PE.js +27 -0
  17. data/app/assets/javascripts/jquery.validate.localization/messages_et.js +8 -18
  18. data/app/assets/javascripts/jquery.validate.localization/messages_eu.js +8 -18
  19. data/app/assets/javascripts/jquery.validate.localization/messages_fa.js +10 -20
  20. data/app/assets/javascripts/jquery.validate.localization/messages_fi.js +12 -22
  21. data/app/assets/javascripts/jquery.validate.localization/messages_fr.js +12 -22
  22. data/app/assets/javascripts/jquery.validate.localization/messages_ge.js +23 -0
  23. data/app/assets/javascripts/jquery.validate.localization/messages_gl.js +10 -20
  24. data/app/assets/javascripts/jquery.validate.localization/messages_he.js +8 -18
  25. data/app/assets/javascripts/jquery.validate.localization/messages_hr.js +8 -18
  26. data/app/assets/javascripts/jquery.validate.localization/messages_hu.js +8 -18
  27. data/app/assets/javascripts/jquery.validate.localization/messages_hy_AM.js +23 -0
  28. data/app/assets/javascripts/jquery.validate.localization/messages_id.js +8 -18
  29. data/app/assets/javascripts/jquery.validate.localization/messages_is.js +8 -18
  30. data/app/assets/javascripts/jquery.validate.localization/messages_it.js +23 -32
  31. data/app/assets/javascripts/jquery.validate.localization/messages_ja.js +8 -18
  32. data/app/assets/javascripts/jquery.validate.localization/messages_ka.js +8 -18
  33. data/app/assets/javascripts/jquery.validate.localization/messages_kk.js +8 -18
  34. data/app/assets/javascripts/jquery.validate.localization/messages_ko.js +8 -18
  35. data/app/assets/javascripts/jquery.validate.localization/messages_lt.js +8 -18
  36. data/app/assets/javascripts/jquery.validate.localization/messages_lv.js +8 -18
  37. data/app/assets/javascripts/jquery.validate.localization/messages_mk.js +23 -0
  38. data/app/assets/javascripts/jquery.validate.localization/messages_my.js +8 -18
  39. data/app/assets/javascripts/jquery.validate.localization/messages_nl.js +9 -19
  40. data/app/assets/javascripts/jquery.validate.localization/messages_no.js +8 -18
  41. data/app/assets/javascripts/jquery.validate.localization/messages_pl.js +9 -18
  42. data/app/assets/javascripts/jquery.validate.localization/messages_pt_BR.js +58 -21
  43. data/app/assets/javascripts/jquery.validate.localization/messages_pt_PT.js +8 -18
  44. data/app/assets/javascripts/jquery.validate.localization/messages_ro.js +8 -18
  45. data/app/assets/javascripts/jquery.validate.localization/messages_ru.js +8 -18
  46. data/app/assets/javascripts/jquery.validate.localization/messages_si.js +8 -18
  47. data/app/assets/javascripts/jquery.validate.localization/messages_sk.js +10 -20
  48. data/app/assets/javascripts/jquery.validate.localization/messages_sl.js +8 -18
  49. data/app/assets/javascripts/jquery.validate.localization/messages_sr.js +8 -18
  50. data/app/assets/javascripts/jquery.validate.localization/messages_sr_lat.js +10 -20
  51. data/app/assets/javascripts/jquery.validate.localization/messages_sv.js +8 -18
  52. data/app/assets/javascripts/jquery.validate.localization/messages_th.js +8 -18
  53. data/app/assets/javascripts/jquery.validate.localization/messages_tj.js +8 -18
  54. data/app/assets/javascripts/jquery.validate.localization/messages_tr.js +9 -18
  55. data/app/assets/javascripts/jquery.validate.localization/messages_uk.js +8 -18
  56. data/app/assets/javascripts/jquery.validate.localization/messages_vi.js +8 -18
  57. data/app/assets/javascripts/jquery.validate.localization/messages_zh.js +13 -23
  58. data/app/assets/javascripts/jquery.validate.localization/messages_zh_TW.js +8 -18
  59. data/app/assets/javascripts/jquery.validate.localization/methods_de.js +6 -16
  60. data/app/assets/javascripts/jquery.validate.localization/methods_es_CL.js +6 -16
  61. data/app/assets/javascripts/jquery.validate.localization/methods_fi.js +6 -16
  62. data/app/assets/javascripts/jquery.validate.localization/methods_nl.js +4 -14
  63. data/app/assets/javascripts/jquery.validate.localization/methods_pt.js +4 -14
  64. data/jquery-validation-rails.gemspec +0 -5
  65. data/lib/jquery/validation/rails/version.rb +1 -1
  66. metadata +9 -52
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4691809abf49bdbe7976df0d05ea7f7cbc626f20
4
- data.tar.gz: 087209bab6f17cccb3c95cf47ae1d98f883e5613
3
+ metadata.gz: 68933135192adb060190b207dab9e80b9abb6ae1
4
+ data.tar.gz: 18216f9797ca5d0d1955a860d247a6eee322795e
5
5
  SHA512:
6
- metadata.gz: fd3d64b8fe0c49136c4482107d68e3a461d0b88dfad33171c49c6c01fff65ab2cf16544b79fa2665cb3caf072f189ca57775dc5cfdd7521279b69960d0cf665c
7
- data.tar.gz: 36b29911708276c3ceec81c33cb7d48b4978248ec1fdeafcc0d80cac3e892da17da15e6e89bea68e1b50c26a451b43717816b2bd7159075f2bd93f9e0c923ea0
6
+ metadata.gz: df6a7e2036f9e3f950a1b439bc4d373cb718363e333f8b365e7a9d9d68ab83705181e27c3c113df056c655951813bd65f3f0b9191a9696c6ea9e5cf4cc24a716
7
+ data.tar.gz: 22ec87568a2a0d8d95ecab4088e29775903d431a214cf4fd9cfd730fa0556f12cdb1c4eab4d6096b5d9be8d45383cb53efe20fe050eb8545f8e81799e9adcfef
@@ -1,3 +1,7 @@
1
+ ## 1.15.0
2
+
3
+ * Update included jquery.validation files to 1.15.0
4
+
1
5
  ## 1.13.1
2
6
 
3
7
  * Update included jquery.validation files to 1.13.1
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # Jquery::Validation::Rails
2
2
 
3
-
4
3
  ## Installation
5
4
 
6
5
  Add this line to your application's Gemfile:
@@ -1,940 +1,1056 @@
1
1
  /*!
2
- * jQuery Validation Plugin v1.13.1
2
+ * jQuery Validation Plugin v1.15.0
3
3
  *
4
4
  * http://jqueryvalidation.org/
5
5
  *
6
- * Copyright (c) 2014 Jörn Zaefferer
6
+ * Copyright (c) 2016 Jörn Zaefferer
7
7
  * Released under the MIT license
8
8
  */
9
9
  (function( factory ) {
10
- if ( typeof define === "function" && define.amd ) {
11
- define( ["jquery", "./jquery.validate"], factory );
12
- } else {
13
- factory( jQuery );
14
- }
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
+ }
15
17
  }(function( $ ) {
16
18
 
17
- (function() {
19
+ ( function() {
18
20
 
19
- function stripHtml(value) {
20
- // remove html tags and space chars
21
- return value.replace(/<.[^<>]*?>/g, " ").replace(/&nbsp;|&#160;/gi, " ")
22
- // remove punctuation
23
- .replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "");
24
- }
21
+ function stripHtml( value ) {
25
22
 
26
- $.validator.addMethod("maxWords", function(value, element, params) {
27
- return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params;
28
- }, $.validator.format("Please enter {0} words or less."));
23
+ // Remove html tags and space chars
24
+ return value.replace( /<.[^<>]*?>/g, " " ).replace( /&nbsp;|&#160;/gi, " " )
29
25
 
30
- $.validator.addMethod("minWords", function(value, element, params) {
31
- return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params;
32
- }, $.validator.format("Please enter at least {0} words."));
26
+ // Remove punctuation
27
+ .replace( /[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "" );
28
+ }
33
29
 
34
- $.validator.addMethod("rangeWords", function(value, element, params) {
35
- var valueStripped = stripHtml(value),
36
- regex = /\b\w+\b/g;
37
- return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];
38
- }, $.validator.format("Please enter between {0} and {1} words."));
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." ) );
39
33
 
40
- }());
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." ) );
41
37
 
42
- // Accept a value from a file input based on a required mimetype
43
- $.validator.addMethod("accept", function(value, element, param) {
44
- // Split mime on commas in case we have multiple types we can accept
45
- var typeParam = typeof param === "string" ? param.replace(/\s/g, "").replace(/,/g, "|") : "image/*",
46
- optionalValue = this.optional(element),
47
- i, file;
48
-
49
- // Element is optional
50
- if (optionalValue) {
51
- return optionalValue;
52
- }
53
-
54
- if ($(element).attr("type") === "file") {
55
- // If we are using a wildcard, make it regex friendly
56
- typeParam = typeParam.replace(/\*/g, ".*");
57
-
58
- // Check if the element has a FileList before checking each file
59
- if (element.files && element.files.length) {
60
- for (i = 0; i < element.files.length; i++) {
61
- file = element.files[i];
62
-
63
- // Grab the mimetype from the loaded file, verify it matches
64
- if (!file.type.match(new RegExp( ".?(" + typeParam + ")$", "i"))) {
65
- return false;
66
- }
67
- }
68
- }
69
- }
70
-
71
- // Either return true because we've validated each file, or because the
72
- // browser does not support element.files and the FileList feature
73
- return true;
74
- }, $.validator.format("Please enter a value with a valid mimetype."));
75
-
76
- $.validator.addMethod("alphanumeric", function(value, element) {
77
- return this.optional(element) || /^\w+$/i.test(value);
78
- }, "Letters, numbers, and underscores only please");
79
-
80
- /*
81
- * Dutch bank account numbers (not 'giro' numbers) have 9 digits
82
- * and pass the '11 check'.
83
- * We accept the notation with spaces, as that is common.
84
- * acceptable: 123456789 or 12 34 56 789
85
- */
86
- $.validator.addMethod("bankaccountNL", function(value, element) {
87
- if (this.optional(element)) {
88
- return true;
89
- }
90
- if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {
91
- return false;
92
- }
93
- // now '11 check'
94
- var account = value.replace(/ /g, ""), // remove spaces
95
- sum = 0,
96
- len = account.length,
97
- pos, factor, digit;
98
- for ( pos = 0; pos < len; pos++ ) {
99
- factor = len - pos;
100
- digit = account.substring(pos, pos + 1);
101
- sum = sum + factor * digit;
102
- }
103
- return sum % 11 === 0;
104
- }, "Please specify a valid bank account number");
105
-
106
- $.validator.addMethod("bankorgiroaccountNL", function(value, element) {
107
- return this.optional(element) ||
108
- ($.validator.methods.bankaccountNL.call(this, value, element)) ||
109
- ($.validator.methods.giroaccountNL.call(this, value, element));
110
- }, "Please specify a valid bank or giro account number");
111
-
112
- /**
113
- * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
114
- *
115
- * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
116
- *
117
- * BIC definition in detail:
118
- * - First 4 characters - bank code (only letters)
119
- * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
120
- * - Next 2 characters - location code (letters and digits)
121
- * a. shall not start with '0' or '1'
122
- * b. second character must be a letter ('O' is not allowed) or one of the following digits ('0' for test (therefore not allowed), '1' for passive participant and '2' for active participant)
123
- * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
124
- */
125
- $.validator.addMethod("bic", function(value, element) {
126
- return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value );
127
- }, "Please specify a valid BIC code");
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." ) );
128
43
 
129
- /*
130
- * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
131
- * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
132
- */
133
- $.validator.addMethod( "cifES", function( value ) {
134
- "use strict";
135
-
136
- var num = [],
137
- controlDigit, sum, i, count, tmp, secondDigit;
138
-
139
- value = value.toUpperCase();
140
-
141
- // Quick format test
142
- 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}$)" ) ) {
143
- return false;
144
- }
145
-
146
- for ( i = 0; i < 9; i++ ) {
147
- num[ i ] = parseInt( value.charAt( i ), 10 );
148
- }
149
-
150
- // Algorithm for checking CIF codes
151
- sum = num[ 2 ] + num[ 4 ] + num[ 6 ];
152
- for ( count = 1; count < 8; count += 2 ) {
153
- tmp = ( 2 * num[ count ] ).toString();
154
- secondDigit = tmp.charAt( 1 );
155
-
156
- sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) );
157
- }
158
-
159
- /* The first (position 1) is a letter following the following criteria:
160
- * A. Corporations
161
- * B. LLCs
162
- * C. General partnerships
163
- * D. Companies limited partnerships
164
- * E. Communities of goods
165
- * F. Cooperative Societies
166
- * G. Associations
167
- * H. Communities of homeowners in horizontal property regime
168
- * J. Civil Societies
169
- * K. Old format
170
- * L. Old format
171
- * M. Old format
172
- * N. Nonresident entities
173
- * P. Local authorities
174
- * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
175
- * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
176
- * S. Organs of State Administration and regions
177
- * V. Agrarian Transformation
178
- * W. Permanent establishments of non-resident in Spain
179
- */
180
- if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {
181
- sum += "";
182
- controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );
183
- value += controlDigit;
184
- return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );
185
- }
186
-
187
- return false;
188
-
189
- }, "Please specify a valid CIF number." );
190
-
191
- /* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
192
- * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
193
- * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
194
- */
195
- $.validator.addMethod("creditcardtypes", function(value, element, param) {
196
- if (/[^0-9\-]+/.test(value)) {
197
- return false;
198
- }
199
-
200
- value = value.replace(/\D/g, "");
201
-
202
- var validTypes = 0x0000;
203
-
204
- if (param.mastercard) {
205
- validTypes |= 0x0001;
206
- }
207
- if (param.visa) {
208
- validTypes |= 0x0002;
209
- }
210
- if (param.amex) {
211
- validTypes |= 0x0004;
212
- }
213
- if (param.dinersclub) {
214
- validTypes |= 0x0008;
215
- }
216
- if (param.enroute) {
217
- validTypes |= 0x0010;
218
- }
219
- if (param.discover) {
220
- validTypes |= 0x0020;
221
- }
222
- if (param.jcb) {
223
- validTypes |= 0x0040;
224
- }
225
- if (param.unknown) {
226
- validTypes |= 0x0080;
227
- }
228
- if (param.all) {
229
- validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
230
- }
231
- if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard
232
- return value.length === 16;
233
- }
234
- if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa
235
- return value.length === 16;
236
- }
237
- if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex
238
- return value.length === 15;
239
- }
240
- if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub
241
- return value.length === 14;
242
- }
243
- if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute
244
- return value.length === 15;
245
- }
246
- if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover
247
- return value.length === 16;
248
- }
249
- if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb
250
- return value.length === 16;
251
- }
252
- if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb
253
- return value.length === 15;
254
- }
255
- if (validTypes & 0x0080) { //unknown
256
- return true;
257
- }
258
- return false;
259
- }, "Please enter a valid credit card number.");
260
-
261
- /**
262
- * Validates currencies with any given symbols by @jameslouiz
263
- * Symbols can be optional or required. Symbols required by default
264
- *
265
- * Usage examples:
266
- * currency: ["£", false] - Use false for soft currency validation
267
- * currency: ["$", false]
268
- * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
269
- *
270
- * <input class="currencyInput" name="currencyInput">
271
- *
272
- * Soft symbol checking
273
- * currencyInput: {
44
+ }() );
45
+
46
+ // Accept a value from a file input based on a required mimetype
47
+ $.validator.addMethod( "accept", function( value, element, param ) {
48
+
49
+ // Split mime on commas in case we have multiple types we can accept
50
+ var typeParam = typeof param === "string" ? param.replace( /\s/g, "" ) : "image/*",
51
+ optionalValue = this.optional( element ),
52
+ i, file, regex;
53
+
54
+ // Element is optional
55
+ if ( optionalValue ) {
56
+ return optionalValue;
57
+ }
58
+
59
+ if ( $( element ).attr( "type" ) === "file" ) {
60
+
61
+ // Escape string to be used in the regex
62
+ // see: http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
63
+ // Escape also "/*" as "/.*" as a wildcard
64
+ typeParam = typeParam.replace( /[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, "\\$&" ).replace( /,/g, "|" ).replace( "\/*", "/.*" );
65
+
66
+ // Check if the element has a FileList before checking each file
67
+ if ( element.files && element.files.length ) {
68
+ regex = new RegExp( ".?(" + typeParam + ")$", "i" );
69
+ for ( i = 0; i < element.files.length; i++ ) {
70
+ file = element.files[ i ];
71
+
72
+ // Grab the mimetype from the loaded file, verify it matches
73
+ if ( !file.type.match( regex ) ) {
74
+ return false;
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ // Either return true because we've validated each file, or because the
81
+ // browser does not support element.files and the FileList feature
82
+ return true;
83
+ }, $.validator.format( "Please enter a value with a valid mimetype." ) );
84
+
85
+ $.validator.addMethod( "alphanumeric", function( value, element ) {
86
+ return this.optional( element ) || /^\w+$/i.test( value );
87
+ }, "Letters, numbers, and underscores only please" );
88
+
89
+ /*
90
+ * Dutch bank account numbers (not 'giro' numbers) have 9 digits
91
+ * and pass the '11 check'.
92
+ * We accept the notation with spaces, as that is common.
93
+ * acceptable: 123456789 or 12 34 56 789
94
+ */
95
+ $.validator.addMethod( "bankaccountNL", function( value, element ) {
96
+ if ( this.optional( element ) ) {
97
+ return true;
98
+ }
99
+ if ( !( /^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test( value ) ) ) {
100
+ return false;
101
+ }
102
+
103
+ // Now '11 check'
104
+ var account = value.replace( / /g, "" ), // Remove spaces
105
+ sum = 0,
106
+ len = account.length,
107
+ pos, factor, digit;
108
+ for ( pos = 0; pos < len; pos++ ) {
109
+ factor = len - pos;
110
+ digit = account.substring( pos, pos + 1 );
111
+ sum = sum + factor * digit;
112
+ }
113
+ return sum % 11 === 0;
114
+ }, "Please specify a valid bank account number" );
115
+
116
+ $.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
117
+ return this.optional( element ) ||
118
+ ( $.validator.methods.bankaccountNL.call( this, value, element ) ) ||
119
+ ( $.validator.methods.giroaccountNL.call( this, value, element ) );
120
+ }, "Please specify a valid bank or giro account number" );
121
+
122
+ /**
123
+ * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
124
+ *
125
+ * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
126
+ *
127
+ * Validation is case-insensitive. Please make sure to normalize input yourself.
128
+ *
129
+ * BIC definition in detail:
130
+ * - First 4 characters - bank code (only letters)
131
+ * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
132
+ * - Next 2 characters - location code (letters and digits)
133
+ * a. shall not start with '0' or '1'
134
+ * 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)
135
+ * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
136
+ */
137
+ $.validator.addMethod( "bic", function( value, element ) {
138
+ 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() );
139
+ }, "Please specify a valid BIC code" );
140
+
141
+ /*
142
+ * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
143
+ * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
144
+ */
145
+ $.validator.addMethod( "cifES", function( value ) {
146
+ "use strict";
147
+
148
+ var num = [],
149
+ controlDigit, sum, i, count, tmp, secondDigit;
150
+
151
+ value = value.toUpperCase();
152
+
153
+ // Quick format test
154
+ 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}$)" ) ) {
155
+ return false;
156
+ }
157
+
158
+ for ( i = 0; i < 9; i++ ) {
159
+ num[ i ] = parseInt( value.charAt( i ), 10 );
160
+ }
161
+
162
+ // Algorithm for checking CIF codes
163
+ sum = num[ 2 ] + num[ 4 ] + num[ 6 ];
164
+ for ( count = 1; count < 8; count += 2 ) {
165
+ tmp = ( 2 * num[ count ] ).toString();
166
+ secondDigit = tmp.charAt( 1 );
167
+
168
+ sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) );
169
+ }
170
+
171
+ /* The first (position 1) is a letter following the following criteria:
172
+ * A. Corporations
173
+ * B. LLCs
174
+ * C. General partnerships
175
+ * D. Companies limited partnerships
176
+ * E. Communities of goods
177
+ * F. Cooperative Societies
178
+ * G. Associations
179
+ * H. Communities of homeowners in horizontal property regime
180
+ * J. Civil Societies
181
+ * K. Old format
182
+ * L. Old format
183
+ * M. Old format
184
+ * N. Nonresident entities
185
+ * P. Local authorities
186
+ * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
187
+ * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
188
+ * S. Organs of State Administration and regions
189
+ * V. Agrarian Transformation
190
+ * W. Permanent establishments of non-resident in Spain
191
+ */
192
+ if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {
193
+ sum += "";
194
+ controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );
195
+ value += controlDigit;
196
+ return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );
197
+ }
198
+
199
+ return false;
200
+
201
+ }, "Please specify a valid CIF number." );
202
+
203
+ /*
204
+ * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
205
+ * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
206
+ */
207
+ $.validator.addMethod( "cpfBR", function( value ) {
208
+
209
+ // Removing special characters from value
210
+ value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
211
+
212
+ // Checking value to have 11 digits only
213
+ if ( value.length !== 11 ) {
214
+ return false;
215
+ }
216
+
217
+ var sum = 0,
218
+ firstCN, secondCN, checkResult, i;
219
+
220
+ firstCN = parseInt( value.substring( 9, 10 ), 10 );
221
+ secondCN = parseInt( value.substring( 10, 11 ), 10 );
222
+
223
+ checkResult = function( sum, cn ) {
224
+ var result = ( sum * 10 ) % 11;
225
+ if ( ( result === 10 ) || ( result === 11 ) ) {
226
+ result = 0;
227
+ }
228
+ return ( result === cn );
229
+ };
230
+
231
+ // Checking for dump data
232
+ if ( value === "" ||
233
+ value === "00000000000" ||
234
+ value === "11111111111" ||
235
+ value === "22222222222" ||
236
+ value === "33333333333" ||
237
+ value === "44444444444" ||
238
+ value === "55555555555" ||
239
+ value === "66666666666" ||
240
+ value === "77777777777" ||
241
+ value === "88888888888" ||
242
+ value === "99999999999"
243
+ ) {
244
+ return false;
245
+ }
246
+
247
+ // Step 1 - using first Check Number:
248
+ for ( i = 1; i <= 9; i++ ) {
249
+ sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 11 - i );
250
+ }
251
+
252
+ // If first Check Number (CN) is valid, move to Step 2 - using second Check Number:
253
+ if ( checkResult( sum, firstCN ) ) {
254
+ sum = 0;
255
+ for ( i = 1; i <= 10; i++ ) {
256
+ sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 12 - i );
257
+ }
258
+ return checkResult( sum, secondCN );
259
+ }
260
+ return false;
261
+
262
+ }, "Please specify a valid CPF number" );
263
+
264
+ // http://jqueryvalidation.org/creditcard-method/
265
+ // based on http://en.wikipedia.org/wiki/Luhn_algorithm
266
+ $.validator.addMethod( "creditcard", function( value, element ) {
267
+ if ( this.optional( element ) ) {
268
+ return "dependency-mismatch";
269
+ }
270
+
271
+ // Accept only spaces, digits and dashes
272
+ if ( /[^0-9 \-]+/.test( value ) ) {
273
+ return false;
274
+ }
275
+
276
+ var nCheck = 0,
277
+ nDigit = 0,
278
+ bEven = false,
279
+ n, cDigit;
280
+
281
+ value = value.replace( /\D/g, "" );
282
+
283
+ // Basing min and max length on
284
+ // http://developer.ean.com/general_info/Valid_Credit_Card_Types
285
+ if ( value.length < 13 || value.length > 19 ) {
286
+ return false;
287
+ }
288
+
289
+ for ( n = value.length - 1; n >= 0; n-- ) {
290
+ cDigit = value.charAt( n );
291
+ nDigit = parseInt( cDigit, 10 );
292
+ if ( bEven ) {
293
+ if ( ( nDigit *= 2 ) > 9 ) {
294
+ nDigit -= 9;
295
+ }
296
+ }
297
+
298
+ nCheck += nDigit;
299
+ bEven = !bEven;
300
+ }
301
+
302
+ return ( nCheck % 10 ) === 0;
303
+ }, "Please enter a valid credit card number." );
304
+
305
+ /* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
306
+ * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
307
+ * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
308
+ */
309
+ $.validator.addMethod( "creditcardtypes", function( value, element, param ) {
310
+ if ( /[^0-9\-]+/.test( value ) ) {
311
+ return false;
312
+ }
313
+
314
+ value = value.replace( /\D/g, "" );
315
+
316
+ var validTypes = 0x0000;
317
+
318
+ if ( param.mastercard ) {
319
+ validTypes |= 0x0001;
320
+ }
321
+ if ( param.visa ) {
322
+ validTypes |= 0x0002;
323
+ }
324
+ if ( param.amex ) {
325
+ validTypes |= 0x0004;
326
+ }
327
+ if ( param.dinersclub ) {
328
+ validTypes |= 0x0008;
329
+ }
330
+ if ( param.enroute ) {
331
+ validTypes |= 0x0010;
332
+ }
333
+ if ( param.discover ) {
334
+ validTypes |= 0x0020;
335
+ }
336
+ if ( param.jcb ) {
337
+ validTypes |= 0x0040;
338
+ }
339
+ if ( param.unknown ) {
340
+ validTypes |= 0x0080;
341
+ }
342
+ if ( param.all ) {
343
+ validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
344
+ }
345
+ if ( validTypes & 0x0001 && /^(5[12345])/.test( value ) ) { // Mastercard
346
+ return value.length === 16;
347
+ }
348
+ if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa
349
+ return value.length === 16;
350
+ }
351
+ if ( validTypes & 0x0004 && /^(3[47])/.test( value ) ) { // Amex
352
+ return value.length === 15;
353
+ }
354
+ if ( validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test( value ) ) { // Dinersclub
355
+ return value.length === 14;
356
+ }
357
+ if ( validTypes & 0x0010 && /^(2(014|149))/.test( value ) ) { // Enroute
358
+ return value.length === 15;
359
+ }
360
+ if ( validTypes & 0x0020 && /^(6011)/.test( value ) ) { // Discover
361
+ return value.length === 16;
362
+ }
363
+ if ( validTypes & 0x0040 && /^(3)/.test( value ) ) { // Jcb
364
+ return value.length === 16;
365
+ }
366
+ if ( validTypes & 0x0040 && /^(2131|1800)/.test( value ) ) { // Jcb
367
+ return value.length === 15;
368
+ }
369
+ if ( validTypes & 0x0080 ) { // Unknown
370
+ return true;
371
+ }
372
+ return false;
373
+ }, "Please enter a valid credit card number." );
374
+
375
+ /**
376
+ * Validates currencies with any given symbols by @jameslouiz
377
+ * Symbols can be optional or required. Symbols required by default
378
+ *
379
+ * Usage examples:
380
+ * currency: ["£", false] - Use false for soft currency validation
381
+ * currency: ["$", false]
382
+ * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
383
+ *
384
+ * <input class="currencyInput" name="currencyInput">
385
+ *
386
+ * Soft symbol checking
387
+ * currencyInput: {
274
388
  * currency: ["$", false]
275
389
  * }
276
- *
277
- * Strict symbol checking (default)
278
- * currencyInput: {
390
+ *
391
+ * Strict symbol checking (default)
392
+ * currencyInput: {
279
393
  * currency: "$"
280
394
  * //OR
281
395
  * currency: ["$", true]
282
396
  * }
283
- *
284
- * Multiple Symbols
285
- * currencyInput: {
397
+ *
398
+ * Multiple Symbols
399
+ * currencyInput: {
286
400
  * currency: "$,£,¢"
287
401
  * }
288
- */
289
- $.validator.addMethod("currency", function(value, element, param) {
290
- var isParamString = typeof param === "string",
291
- symbol = isParamString ? param : param[0],
292
- soft = isParamString ? true : param[1],
293
- regex;
294
-
295
- symbol = symbol.replace(/,/g, "");
296
- symbol = soft ? symbol + "]" : symbol + "]?";
297
- 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})?)$";
298
- regex = new RegExp(regex);
299
- return this.optional(element) || regex.test(value);
300
-
301
- }, "Please specify a valid currency");
302
-
303
- $.validator.addMethod("dateFA", function(value, element) {
304
- 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);
305
- }, "Please enter a correct date");
306
-
307
- /**
308
- * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
309
- *
310
- * @example $.validator.methods.date("01/01/1900")
311
- * @result true
312
- *
313
- * @example $.validator.methods.date("01/13/1990")
314
- * @result false
315
- *
316
- * @example $.validator.methods.date("01.01.1900")
317
- * @result false
318
- *
319
- * @example <input name="pippo" class="{dateITA:true}" />
320
- * @desc Declares an optional input element whose value must be a valid date.
321
- *
322
- * @name $.validator.methods.dateITA
323
- * @type Boolean
324
- * @cat Plugins/Validate/Methods
325
- */
326
- $.validator.addMethod("dateITA", function(value, element) {
327
- var check = false,
328
- re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
329
- adata, gg, mm, aaaa, xdata;
330
- if ( re.test(value)) {
331
- adata = value.split("/");
332
- gg = parseInt(adata[0], 10);
333
- mm = parseInt(adata[1], 10);
334
- aaaa = parseInt(adata[2], 10);
335
- xdata = new Date(aaaa, mm - 1, gg, 12, 0, 0, 0);
336
- if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth () === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
337
- check = true;
338
- } else {
339
- check = false;
340
- }
341
- } else {
342
- check = false;
343
- }
344
- return this.optional(element) || check;
345
- }, "Please enter a correct date");
346
-
347
- $.validator.addMethod("dateNL", function(value, element) {
348
- return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
349
- }, "Please enter a correct date");
402
+ */
403
+ $.validator.addMethod( "currency", function( value, element, param ) {
404
+ var isParamString = typeof param === "string",
405
+ symbol = isParamString ? param : param[ 0 ],
406
+ soft = isParamString ? true : param[ 1 ],
407
+ regex;
408
+
409
+ symbol = symbol.replace( /,/g, "" );
410
+ symbol = soft ? symbol + "]" : symbol + "]?";
411
+ 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})?)$";
412
+ regex = new RegExp( regex );
413
+ return this.optional( element ) || regex.test( value );
414
+
415
+ }, "Please specify a valid currency" );
416
+
417
+ $.validator.addMethod( "dateFA", function( value, element ) {
418
+ 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 );
419
+ }, $.validator.messages.date );
420
+
421
+ /**
422
+ * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
423
+ *
424
+ * @example $.validator.methods.date("01/01/1900")
425
+ * @result true
426
+ *
427
+ * @example $.validator.methods.date("01/13/1990")
428
+ * @result false
429
+ *
430
+ * @example $.validator.methods.date("01.01.1900")
431
+ * @result false
432
+ *
433
+ * @example <input name="pippo" class="{dateITA:true}" />
434
+ * @desc Declares an optional input element whose value must be a valid date.
435
+ *
436
+ * @name $.validator.methods.dateITA
437
+ * @type Boolean
438
+ * @cat Plugins/Validate/Methods
439
+ */
440
+ $.validator.addMethod( "dateITA", function( value, element ) {
441
+ var check = false,
442
+ re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
443
+ adata, gg, mm, aaaa, xdata;
444
+ if ( re.test( value ) ) {
445
+ adata = value.split( "/" );
446
+ gg = parseInt( adata[ 0 ], 10 );
447
+ mm = parseInt( adata[ 1 ], 10 );
448
+ aaaa = parseInt( adata[ 2 ], 10 );
449
+ xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) );
450
+ if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
451
+ check = true;
452
+ } else {
453
+ check = false;
454
+ }
455
+ } else {
456
+ check = false;
457
+ }
458
+ return this.optional( element ) || check;
459
+ }, $.validator.messages.date );
460
+
461
+ $.validator.addMethod( "dateNL", function( value, element ) {
462
+ return this.optional( element ) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test( value );
463
+ }, $.validator.messages.date );
350
464
 
351
465
  // Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
352
- $.validator.addMethod("extension", function(value, element, param) {
353
- param = typeof param === "string" ? param.replace(/,/g, "|") : "png|jpe?g|gif";
354
- return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
355
- }, $.validator.format("Please enter a value with a valid extension."));
356
-
357
- /**
358
- * Dutch giro account numbers (not bank numbers) have max 7 digits
359
- */
360
- $.validator.addMethod("giroaccountNL", function(value, element) {
361
- return this.optional(element) || /^[0-9]{1,7}$/.test(value);
362
- }, "Please specify a valid giro account number");
363
-
364
- /**
365
- * IBAN is the international bank account number.
366
- * It has a country - specific format, that is checked here too
367
- */
368
- $.validator.addMethod("iban", function(value, element) {
369
- // some quick simple tests to prevent needless work
370
- if (this.optional(element)) {
371
- return true;
372
- }
373
-
374
- // remove spaces and to upper case
375
- var iban = value.replace(/ /g, "").toUpperCase(),
376
- ibancheckdigits = "",
377
- leadingZeroes = true,
378
- cRest = "",
379
- cOperator = "",
380
- countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
381
-
382
- if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(iban))) {
383
- return false;
384
- }
385
-
386
- // check the country code and find the country specific format
387
- countrycode = iban.substring(0, 2);
388
- bbancountrypatterns = {
389
- "AL": "\\d{8}[\\dA-Z]{16}",
390
- "AD": "\\d{8}[\\dA-Z]{12}",
391
- "AT": "\\d{16}",
392
- "AZ": "[\\dA-Z]{4}\\d{20}",
393
- "BE": "\\d{12}",
394
- "BH": "[A-Z]{4}[\\dA-Z]{14}",
395
- "BA": "\\d{16}",
396
- "BR": "\\d{23}[A-Z][\\dA-Z]",
397
- "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
398
- "CR": "\\d{17}",
399
- "HR": "\\d{17}",
400
- "CY": "\\d{8}[\\dA-Z]{16}",
401
- "CZ": "\\d{20}",
402
- "DK": "\\d{14}",
403
- "DO": "[A-Z]{4}\\d{20}",
404
- "EE": "\\d{16}",
405
- "FO": "\\d{14}",
406
- "FI": "\\d{14}",
407
- "FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
408
- "GE": "[\\dA-Z]{2}\\d{16}",
409
- "DE": "\\d{18}",
410
- "GI": "[A-Z]{4}[\\dA-Z]{15}",
411
- "GR": "\\d{7}[\\dA-Z]{16}",
412
- "GL": "\\d{14}",
413
- "GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
414
- "HU": "\\d{24}",
415
- "IS": "\\d{22}",
416
- "IE": "[\\dA-Z]{4}\\d{14}",
417
- "IL": "\\d{19}",
418
- "IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
419
- "KZ": "\\d{3}[\\dA-Z]{13}",
420
- "KW": "[A-Z]{4}[\\dA-Z]{22}",
421
- "LV": "[A-Z]{4}[\\dA-Z]{13}",
422
- "LB": "\\d{4}[\\dA-Z]{20}",
423
- "LI": "\\d{5}[\\dA-Z]{12}",
424
- "LT": "\\d{16}",
425
- "LU": "\\d{3}[\\dA-Z]{13}",
426
- "MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
427
- "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
428
- "MR": "\\d{23}",
429
- "MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
430
- "MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
431
- "MD": "[\\dA-Z]{2}\\d{18}",
432
- "ME": "\\d{18}",
433
- "NL": "[A-Z]{4}\\d{10}",
434
- "NO": "\\d{11}",
435
- "PK": "[\\dA-Z]{4}\\d{16}",
436
- "PS": "[\\dA-Z]{4}\\d{21}",
437
- "PL": "\\d{24}",
438
- "PT": "\\d{21}",
439
- "RO": "[A-Z]{4}[\\dA-Z]{16}",
440
- "SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
441
- "SA": "\\d{2}[\\dA-Z]{18}",
442
- "RS": "\\d{18}",
443
- "SK": "\\d{20}",
444
- "SI": "\\d{15}",
445
- "ES": "\\d{20}",
446
- "SE": "\\d{20}",
447
- "CH": "\\d{5}[\\dA-Z]{12}",
448
- "TN": "\\d{20}",
449
- "TR": "\\d{5}[\\dA-Z]{17}",
450
- "AE": "\\d{3}\\d{16}",
451
- "GB": "[A-Z]{4}\\d{14}",
452
- "VG": "[\\dA-Z]{4}\\d{16}"
453
- };
454
-
455
- bbanpattern = bbancountrypatterns[countrycode];
456
- // As new countries will start using IBAN in the
457
- // future, we only check if the countrycode is known.
458
- // This prevents false negatives, while almost all
459
- // false positives introduced by this, will be caught
460
- // by the checksum validation below anyway.
461
- // Strict checking should return FALSE for unknown
462
- // countries.
463
- if (typeof bbanpattern !== "undefined") {
464
- ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
465
- if (!(ibanregexp.test(iban))) {
466
- return false; // invalid country specific format
467
- }
468
- }
469
-
470
- // now check the checksum, first convert to digits
471
- ibancheck = iban.substring(4, iban.length) + iban.substring(0, 4);
472
- for (i = 0; i < ibancheck.length; i++) {
473
- charAt = ibancheck.charAt(i);
474
- if (charAt !== "0") {
475
- leadingZeroes = false;
476
- }
477
- if (!leadingZeroes) {
478
- ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(charAt);
479
- }
480
- }
481
-
482
- // calculate the result of: ibancheckdigits % 97
483
- for (p = 0; p < ibancheckdigits.length; p++) {
484
- cChar = ibancheckdigits.charAt(p);
485
- cOperator = "" + cRest + "" + cChar;
486
- cRest = cOperator % 97;
487
- }
488
- return cRest === 1;
489
- }, "Please specify a valid IBAN");
490
-
491
- $.validator.addMethod("integer", function(value, element) {
492
- return this.optional(element) || /^-?\d+$/.test(value);
493
- }, "A positive or negative non-decimal number please");
494
-
495
- $.validator.addMethod("ipv4", function(value, element) {
496
- 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);
497
- }, "Please enter a valid IP v4 address.");
498
-
499
- $.validator.addMethod("ipv6", function(value, element) {
500
- 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);
501
- }, "Please enter a valid IP v6 address.");
502
-
503
- $.validator.addMethod("lettersonly", function(value, element) {
504
- return this.optional(element) || /^[a-z]+$/i.test(value);
505
- }, "Letters only please");
506
-
507
- $.validator.addMethod("letterswithbasicpunc", function(value, element) {
508
- return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value);
509
- }, "Letters or punctuation only please");
510
-
511
- $.validator.addMethod("mobileNL", function(value, element) {
512
- return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
513
- }, "Please specify a valid mobile number");
514
-
515
- /* For UK phone functions, do the following server side processing:
516
- * Compare original input with this RegEx pattern:
517
- * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
518
- * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
519
- * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
520
- * A number of very detailed GB telephone number RegEx patterns can also be found at:
521
- * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
522
- */
523
- $.validator.addMethod("mobileUK", function(phone_number, element) {
524
- phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
525
- return this.optional(element) || phone_number.length > 9 &&
526
- phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/);
527
- }, "Please specify a valid mobile number");
528
-
529
- /*
530
- * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain
531
- */
532
- $.validator.addMethod( "nieES", function( value ) {
533
- "use strict";
534
-
535
- value = value.toUpperCase();
536
-
537
- // Basic format test
538
- 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}$)" ) ) {
539
- return false;
540
- }
541
-
542
- // Test NIE
543
- //T
544
- if ( /^[T]{1}/.test( value ) ) {
545
- return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );
546
- }
547
-
548
- //XYZ
549
- if ( /^[XYZ]{1}/.test( value ) ) {
550
- return (
551
- value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt(
552
- value.replace( "X", "0" )
553
- .replace( "Y", "1" )
554
- .replace( "Z", "2" )
555
- .substring( 0, 8 ) % 23
556
- )
557
- );
558
- }
559
-
560
- return false;
561
-
562
- }, "Please specify a valid NIE number." );
563
-
564
- /*
565
- * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
566
- */
567
- $.validator.addMethod( "nifES", function( value ) {
568
- "use strict";
569
-
570
- value = value.toUpperCase();
571
-
572
- // Basic format test
573
- 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}$)") ) {
574
- return false;
575
- }
576
-
577
- // Test NIF
578
- if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
579
- return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
580
- }
581
- // Test specials NIF (starts with K, L or M)
582
- if ( /^[KLM]{1}/.test( value ) ) {
583
- return ( value[ 8 ] === String.fromCharCode( 64 ) );
584
- }
585
-
586
- return false;
587
-
588
- }, "Please specify a valid NIF number." );
589
-
590
- $.validator.addMethod("nowhitespace", function(value, element) {
591
- return this.optional(element) || /^\S+$/i.test(value);
592
- }, "No white space please");
593
-
594
- /**
595
- * Return true if the field value matches the given format RegExp
596
- *
597
- * @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
598
- * @result true
599
- *
600
- * @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
601
- * @result false
602
- *
603
- * @name $.validator.methods.pattern
604
- * @type Boolean
605
- * @cat Plugins/Validate/Methods
606
- */
607
- $.validator.addMethod("pattern", function(value, element, param) {
608
- if (this.optional(element)) {
609
- return true;
610
- }
611
- if (typeof param === "string") {
612
- param = new RegExp("^(?:" + param + ")$");
613
- }
614
- return param.test(value);
615
- }, "Invalid format.");
616
-
617
- /**
618
- * Dutch phone numbers have 10 digits (or 11 and start with +31).
619
- */
620
- $.validator.addMethod("phoneNL", function(value, element) {
621
- 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);
622
- }, "Please specify a valid phone number.");
623
-
624
- /* For UK phone functions, do the following server side processing:
625
- * Compare original input with this RegEx pattern:
626
- * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
627
- * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
628
- * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
629
- * A number of very detailed GB telephone number RegEx patterns can also be found at:
630
- * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
631
- */
632
- $.validator.addMethod("phoneUK", function(phone_number, element) {
633
- phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
634
- return this.optional(element) || phone_number.length > 9 &&
635
- 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})$/);
636
- }, "Please specify a valid phone number");
637
-
638
- /**
639
- * matches US phone number format
640
- *
641
- * where the area code may not start with 1 and the prefix may not start with 1
642
- * allows '-' or ' ' as a separator and allows parens around area code
643
- * some people may want to put a '1' in front of their number
644
- *
645
- * 1(212)-999-2345 or
646
- * 212 999 2344 or
647
- * 212-999-0983
648
- *
649
- * but not
650
- * 111-123-5434
651
- * and not
652
- * 212 123 4567
653
- */
654
- $.validator.addMethod("phoneUS", function(phone_number, element) {
655
- phone_number = phone_number.replace(/\s+/g, "");
656
- return this.optional(element) || phone_number.length > 9 &&
657
- phone_number.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/);
658
- }, "Please specify a valid phone number");
659
-
660
- /* For UK phone functions, do the following server side processing:
661
- * Compare original input with this RegEx pattern:
662
- * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
663
- * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
664
- * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
665
- * A number of very detailed GB telephone number RegEx patterns can also be found at:
666
- * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
667
- */
668
- //Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
669
- $.validator.addMethod("phonesUK", function(phone_number, element) {
670
- phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
671
- return this.optional(element) || phone_number.length > 9 &&
672
- phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/);
673
- }, "Please specify a valid uk phone number");
674
-
675
- /**
676
- * Matches a valid Canadian Postal Code
677
- *
678
- * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
679
- * @result true
680
- *
681
- * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
682
- * @result false
683
- *
684
- * @name jQuery.validator.methods.postalCodeCA
685
- * @type Boolean
686
- * @cat Plugins/Validate/Methods
687
- */
688
- $.validator.addMethod( "postalCodeCA", function( value, element ) {
689
- return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test( value );
690
- }, "Please specify a valid postal code" );
691
-
692
- /*
693
- * Valida CEPs do brasileiros:
694
- *
695
- * Formatos aceitos:
696
- * 99999-999
697
- * 99.999-999
698
- * 99999999
699
- */
700
- $.validator.addMethod("postalcodeBR", function(cep_value, element) {
701
- return this.optional(element) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
702
- }, "Informe um CEP válido.");
703
-
704
- /* Matches Italian postcode (CAP) */
705
- $.validator.addMethod("postalcodeIT", function(value, element) {
706
- return this.optional(element) || /^\d{5}$/.test(value);
707
- }, "Please specify a valid postal code");
708
-
709
- $.validator.addMethod("postalcodeNL", function(value, element) {
710
- return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
711
- }, "Please specify a valid postal code");
466
+ $.validator.addMethod( "extension", function( value, element, param ) {
467
+ param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif";
468
+ return this.optional( element ) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) );
469
+ }, $.validator.format( "Please enter a value with a valid extension." ) );
470
+
471
+ /**
472
+ * Dutch giro account numbers (not bank numbers) have max 7 digits
473
+ */
474
+ $.validator.addMethod( "giroaccountNL", function( value, element ) {
475
+ return this.optional( element ) || /^[0-9]{1,7}$/.test( value );
476
+ }, "Please specify a valid giro account number" );
477
+
478
+ /**
479
+ * IBAN is the international bank account number.
480
+ * It has a country - specific format, that is checked here too
481
+ *
482
+ * Validation is case-insensitive. Please make sure to normalize input yourself.
483
+ */
484
+ $.validator.addMethod( "iban", function( value, element ) {
485
+
486
+ // Some quick simple tests to prevent needless work
487
+ if ( this.optional( element ) ) {
488
+ return true;
489
+ }
490
+
491
+ // Remove spaces and to upper case
492
+ var iban = value.replace( / /g, "" ).toUpperCase(),
493
+ ibancheckdigits = "",
494
+ leadingZeroes = true,
495
+ cRest = "",
496
+ cOperator = "",
497
+ countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
498
+
499
+ // Check the country code and find the country specific format
500
+ countrycode = iban.substring( 0, 2 );
501
+ bbancountrypatterns = {
502
+ "AL": "\\d{8}[\\dA-Z]{16}",
503
+ "AD": "\\d{8}[\\dA-Z]{12}",
504
+ "AT": "\\d{16}",
505
+ "AZ": "[\\dA-Z]{4}\\d{20}",
506
+ "BE": "\\d{12}",
507
+ "BH": "[A-Z]{4}[\\dA-Z]{14}",
508
+ "BA": "\\d{16}",
509
+ "BR": "\\d{23}[A-Z][\\dA-Z]",
510
+ "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
511
+ "CR": "\\d{17}",
512
+ "HR": "\\d{17}",
513
+ "CY": "\\d{8}[\\dA-Z]{16}",
514
+ "CZ": "\\d{20}",
515
+ "DK": "\\d{14}",
516
+ "DO": "[A-Z]{4}\\d{20}",
517
+ "EE": "\\d{16}",
518
+ "FO": "\\d{14}",
519
+ "FI": "\\d{14}",
520
+ "FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
521
+ "GE": "[\\dA-Z]{2}\\d{16}",
522
+ "DE": "\\d{18}",
523
+ "GI": "[A-Z]{4}[\\dA-Z]{15}",
524
+ "GR": "\\d{7}[\\dA-Z]{16}",
525
+ "GL": "\\d{14}",
526
+ "GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
527
+ "HU": "\\d{24}",
528
+ "IS": "\\d{22}",
529
+ "IE": "[\\dA-Z]{4}\\d{14}",
530
+ "IL": "\\d{19}",
531
+ "IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
532
+ "KZ": "\\d{3}[\\dA-Z]{13}",
533
+ "KW": "[A-Z]{4}[\\dA-Z]{22}",
534
+ "LV": "[A-Z]{4}[\\dA-Z]{13}",
535
+ "LB": "\\d{4}[\\dA-Z]{20}",
536
+ "LI": "\\d{5}[\\dA-Z]{12}",
537
+ "LT": "\\d{16}",
538
+ "LU": "\\d{3}[\\dA-Z]{13}",
539
+ "MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
540
+ "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
541
+ "MR": "\\d{23}",
542
+ "MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
543
+ "MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
544
+ "MD": "[\\dA-Z]{2}\\d{18}",
545
+ "ME": "\\d{18}",
546
+ "NL": "[A-Z]{4}\\d{10}",
547
+ "NO": "\\d{11}",
548
+ "PK": "[\\dA-Z]{4}\\d{16}",
549
+ "PS": "[\\dA-Z]{4}\\d{21}",
550
+ "PL": "\\d{24}",
551
+ "PT": "\\d{21}",
552
+ "RO": "[A-Z]{4}[\\dA-Z]{16}",
553
+ "SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
554
+ "SA": "\\d{2}[\\dA-Z]{18}",
555
+ "RS": "\\d{18}",
556
+ "SK": "\\d{20}",
557
+ "SI": "\\d{15}",
558
+ "ES": "\\d{20}",
559
+ "SE": "\\d{20}",
560
+ "CH": "\\d{5}[\\dA-Z]{12}",
561
+ "TN": "\\d{20}",
562
+ "TR": "\\d{5}[\\dA-Z]{17}",
563
+ "AE": "\\d{3}\\d{16}",
564
+ "GB": "[A-Z]{4}\\d{14}",
565
+ "VG": "[\\dA-Z]{4}\\d{16}"
566
+ };
567
+
568
+ bbanpattern = bbancountrypatterns[ countrycode ];
569
+
570
+ // As new countries will start using IBAN in the
571
+ // future, we only check if the countrycode is known.
572
+ // This prevents false negatives, while almost all
573
+ // false positives introduced by this, will be caught
574
+ // by the checksum validation below anyway.
575
+ // Strict checking should return FALSE for unknown
576
+ // countries.
577
+ if ( typeof bbanpattern !== "undefined" ) {
578
+ ibanregexp = new RegExp( "^[A-Z]{2}\\d{2}" + bbanpattern + "$", "" );
579
+ if ( !( ibanregexp.test( iban ) ) ) {
580
+ return false; // Invalid country specific format
581
+ }
582
+ }
583
+
584
+ // Now check the checksum, first convert to digits
585
+ ibancheck = iban.substring( 4, iban.length ) + iban.substring( 0, 4 );
586
+ for ( i = 0; i < ibancheck.length; i++ ) {
587
+ charAt = ibancheck.charAt( i );
588
+ if ( charAt !== "0" ) {
589
+ leadingZeroes = false;
590
+ }
591
+ if ( !leadingZeroes ) {
592
+ ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf( charAt );
593
+ }
594
+ }
595
+
596
+ // Calculate the result of: ibancheckdigits % 97
597
+ for ( p = 0; p < ibancheckdigits.length; p++ ) {
598
+ cChar = ibancheckdigits.charAt( p );
599
+ cOperator = "" + cRest + "" + cChar;
600
+ cRest = cOperator % 97;
601
+ }
602
+ return cRest === 1;
603
+ }, "Please specify a valid IBAN" );
604
+
605
+ $.validator.addMethod( "integer", function( value, element ) {
606
+ return this.optional( element ) || /^-?\d+$/.test( value );
607
+ }, "A positive or negative non-decimal number please" );
608
+
609
+ $.validator.addMethod( "ipv4", function( value, element ) {
610
+ 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 );
611
+ }, "Please enter a valid IP v4 address." );
612
+
613
+ $.validator.addMethod( "ipv6", function( value, element ) {
614
+ 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 );
615
+ }, "Please enter a valid IP v6 address." );
616
+
617
+ $.validator.addMethod( "lettersonly", function( value, element ) {
618
+ return this.optional( element ) || /^[a-z]+$/i.test( value );
619
+ }, "Letters only please" );
620
+
621
+ $.validator.addMethod( "letterswithbasicpunc", function( value, element ) {
622
+ return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value );
623
+ }, "Letters or punctuation only please" );
624
+
625
+ $.validator.addMethod( "mobileNL", function( value, element ) {
626
+ return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
627
+ }, "Please specify a valid mobile number" );
628
+
629
+ /* For UK phone functions, do the following server side processing:
630
+ * Compare original input with this RegEx pattern:
631
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
632
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
633
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
634
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
635
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
636
+ */
637
+ $.validator.addMethod( "mobileUK", function( phone_number, element ) {
638
+ phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
639
+ return this.optional( element ) || phone_number.length > 9 &&
640
+ phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ );
641
+ }, "Please specify a valid mobile number" );
642
+
643
+ /*
644
+ * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain
645
+ */
646
+ $.validator.addMethod( "nieES", function( value ) {
647
+ "use strict";
648
+
649
+ value = value.toUpperCase();
650
+
651
+ // Basic format test
652
+ 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}$)" ) ) {
653
+ return false;
654
+ }
655
+
656
+ // Test NIE
657
+ //T
658
+ if ( /^[T]{1}/.test( value ) ) {
659
+ return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );
660
+ }
661
+
662
+ //XYZ
663
+ if ( /^[XYZ]{1}/.test( value ) ) {
664
+ return (
665
+ value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt(
666
+ value.replace( "X", "0" )
667
+ .replace( "Y", "1" )
668
+ .replace( "Z", "2" )
669
+ .substring( 0, 8 ) % 23
670
+ )
671
+ );
672
+ }
673
+
674
+ return false;
675
+
676
+ }, "Please specify a valid NIE number." );
677
+
678
+ /*
679
+ * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
680
+ */
681
+ $.validator.addMethod( "nifES", function( value ) {
682
+ "use strict";
683
+
684
+ value = value.toUpperCase();
685
+
686
+ // Basic format test
687
+ 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}$)" ) ) {
688
+ return false;
689
+ }
690
+
691
+ // Test NIF
692
+ if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
693
+ return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
694
+ }
695
+
696
+ // Test specials NIF (starts with K, L or M)
697
+ if ( /^[KLM]{1}/.test( value ) ) {
698
+ return ( value[ 8 ] === String.fromCharCode( 64 ) );
699
+ }
700
+
701
+ return false;
702
+
703
+ }, "Please specify a valid NIF number." );
704
+
705
+ jQuery.validator.addMethod( "notEqualTo", function( value, element, param ) {
706
+ return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param );
707
+ }, "Please enter a different value, values must not be the same." );
708
+
709
+ $.validator.addMethod( "nowhitespace", function( value, element ) {
710
+ return this.optional( element ) || /^\S+$/i.test( value );
711
+ }, "No white space please" );
712
+
713
+ /**
714
+ * Return true if the field value matches the given format RegExp
715
+ *
716
+ * @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
717
+ * @result true
718
+ *
719
+ * @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
720
+ * @result false
721
+ *
722
+ * @name $.validator.methods.pattern
723
+ * @type Boolean
724
+ * @cat Plugins/Validate/Methods
725
+ */
726
+ $.validator.addMethod( "pattern", function( value, element, param ) {
727
+ if ( this.optional( element ) ) {
728
+ return true;
729
+ }
730
+ if ( typeof param === "string" ) {
731
+ param = new RegExp( "^(?:" + param + ")$" );
732
+ }
733
+ return param.test( value );
734
+ }, "Invalid format." );
735
+
736
+ /**
737
+ * Dutch phone numbers have 10 digits (or 11 and start with +31).
738
+ */
739
+ $.validator.addMethod( "phoneNL", function( value, element ) {
740
+ 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 );
741
+ }, "Please specify a valid phone number." );
742
+
743
+ /* For UK phone functions, do the following server side processing:
744
+ * Compare original input with this RegEx pattern:
745
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
746
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
747
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
748
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
749
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
750
+ */
751
+ $.validator.addMethod( "phoneUK", function( phone_number, element ) {
752
+ phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
753
+ return this.optional( element ) || phone_number.length > 9 &&
754
+ 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})$/ );
755
+ }, "Please specify a valid phone number" );
756
+
757
+ /**
758
+ * Matches US phone number format
759
+ *
760
+ * where the area code may not start with 1 and the prefix may not start with 1
761
+ * allows '-' or ' ' as a separator and allows parens around area code
762
+ * some people may want to put a '1' in front of their number
763
+ *
764
+ * 1(212)-999-2345 or
765
+ * 212 999 2344 or
766
+ * 212-999-0983
767
+ *
768
+ * but not
769
+ * 111-123-5434
770
+ * and not
771
+ * 212 123 4567
772
+ */
773
+ $.validator.addMethod( "phoneUS", function( phone_number, element ) {
774
+ phone_number = phone_number.replace( /\s+/g, "" );
775
+ return this.optional( element ) || phone_number.length > 9 &&
776
+ phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/ );
777
+ }, "Please specify a valid phone number" );
778
+
779
+ /* For UK phone functions, do the following server side processing:
780
+ * Compare original input with this RegEx pattern:
781
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
782
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
783
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
784
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
785
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
786
+ */
787
+
788
+ // Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
789
+ $.validator.addMethod( "phonesUK", function( phone_number, element ) {
790
+ phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
791
+ return this.optional( element ) || phone_number.length > 9 &&
792
+ phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ );
793
+ }, "Please specify a valid uk phone number" );
794
+
795
+ /**
796
+ * Matches a valid Canadian Postal Code
797
+ *
798
+ * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
799
+ * @result true
800
+ *
801
+ * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
802
+ * @result false
803
+ *
804
+ * @name jQuery.validator.methods.postalCodeCA
805
+ * @type Boolean
806
+ * @cat Plugins/Validate/Methods
807
+ */
808
+ $.validator.addMethod( "postalCodeCA", function( value, element ) {
809
+ return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value );
810
+ }, "Please specify a valid postal code" );
811
+
812
+ /*
813
+ * Valida CEPs do brasileiros:
814
+ *
815
+ * Formatos aceitos:
816
+ * 99999-999
817
+ * 99.999-999
818
+ * 99999999
819
+ */
820
+ $.validator.addMethod( "postalcodeBR", function( cep_value, element ) {
821
+ return this.optional( element ) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
822
+ }, "Informe um CEP válido." );
823
+
824
+ /* Matches Italian postcode (CAP) */
825
+ $.validator.addMethod( "postalcodeIT", function( value, element ) {
826
+ return this.optional( element ) || /^\d{5}$/.test( value );
827
+ }, "Please specify a valid postal code" );
828
+
829
+ $.validator.addMethod( "postalcodeNL", function( value, element ) {
830
+ return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value );
831
+ }, "Please specify a valid postal code" );
712
832
 
713
833
  // Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
714
- $.validator.addMethod("postcodeUK", function(value, element) {
715
- 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);
716
- }, "Please specify a valid UK postcode");
717
-
718
- /*
719
- * Lets you say "at least X inputs that match selector Y must be filled."
720
- *
721
- * The end result is that neither of these inputs:
722
- *
723
- * <input class="productinfo" name="partnumber">
724
- * <input class="productinfo" name="description">
725
- *
726
- * ...will validate unless at least one of them is filled.
727
- *
728
- * partnumber: {require_from_group: [1,".productinfo"]},
729
- * description: {require_from_group: [1,".productinfo"]}
730
- *
731
- * options[0]: number of fields that must be filled in the group
732
- * options[1]: CSS selector that defines the group of conditionally required fields
733
- */
734
- $.validator.addMethod("require_from_group", function(value, element, options) {
735
- var $fields = $(options[1], element.form),
736
- $fieldsFirst = $fields.eq(0),
737
- validator = $fieldsFirst.data("valid_req_grp") ? $fieldsFirst.data("valid_req_grp") : $.extend({}, this),
738
- isValid = $fields.filter(function() {
739
- return validator.elementValue(this);
740
- }).length >= options[0];
741
-
742
- // Store the cloned validator for future validation
743
- $fieldsFirst.data("valid_req_grp", validator);
744
-
745
- // If element isn't being validated, run each require_from_group field's validation rules
746
- if (!$(element).data("being_validated")) {
747
- $fields.data("being_validated", true);
748
- $fields.each(function() {
749
- validator.element(this);
750
- });
751
- $fields.data("being_validated", false);
752
- }
753
- return isValid;
754
- }, $.validator.format("Please fill at least {0} of these fields."));
755
-
756
- /*
757
- * Lets you say "either at least X inputs that match selector Y must be filled,
758
- * OR they must all be skipped (left blank)."
759
- *
760
- * The end result, is that none of these inputs:
761
- *
762
- * <input class="productinfo" name="partnumber">
763
- * <input class="productinfo" name="description">
764
- * <input class="productinfo" name="color">
765
- *
766
- * ...will validate unless either at least two of them are filled,
767
- * OR none of them are.
768
- *
769
- * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
770
- * description: {skip_or_fill_minimum: [2,".productinfo"]},
771
- * color: {skip_or_fill_minimum: [2,".productinfo"]}
772
- *
773
- * options[0]: number of fields that must be filled in the group
774
- * options[1]: CSS selector that defines the group of conditionally required fields
775
- *
776
- */
777
- $.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
778
- var $fields = $(options[1], element.form),
779
- $fieldsFirst = $fields.eq(0),
780
- validator = $fieldsFirst.data("valid_skip") ? $fieldsFirst.data("valid_skip") : $.extend({}, this),
781
- numberFilled = $fields.filter(function() {
782
- return validator.elementValue(this);
783
- }).length,
784
- isValid = numberFilled === 0 || numberFilled >= options[0];
785
-
786
- // Store the cloned validator for future validation
787
- $fieldsFirst.data("valid_skip", validator);
788
-
789
- // If element isn't being validated, run each skip_or_fill_minimum field's validation rules
790
- if (!$(element).data("being_validated")) {
791
- $fields.data("being_validated", true);
792
- $fields.each(function() {
793
- validator.element(this);
794
- });
795
- $fields.data("being_validated", false);
796
- }
797
- return isValid;
798
- }, $.validator.format("Please either skip these fields or fill at least {0} of them."));
799
-
800
- /* Validates US States and/or Territories by @jdforsythe
801
- * Can be case insensitive or require capitalization - default is case insensitive
802
- * Can include US Territories or not - default does not
803
- * Can include US Military postal abbreviations (AA, AE, AP) - default does not
804
- *
805
- * Note: "States" always includes DC (District of Colombia)
806
- *
807
- * Usage examples:
808
- *
809
- * This is the default - case insensitive, no territories, no military zones
810
- * stateInput: {
811
- * caseSensitive: false,
812
- * includeTerritories: false,
813
- * includeMilitary: false
814
- * }
815
- *
816
- * Only allow capital letters, no territories, no military zones
817
- * stateInput: {
818
- * caseSensitive: false
819
- * }
820
- *
821
- * Case insensitive, include territories but not military zones
822
- * stateInput: {
823
- * includeTerritories: true
824
- * }
825
- *
826
- * Only allow capital letters, include territories and military zones
827
- * stateInput: {
828
- * caseSensitive: true,
829
- * includeTerritories: true,
830
- * includeMilitary: true
831
- * }
832
- *
833
- *
834
- *
835
- */
836
-
837
- jQuery.validator.addMethod("stateUS", function(value, element, options) {
838
- var isDefault = typeof options === "undefined",
839
- caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
840
- includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
841
- includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
842
- regex;
843
-
844
- if (!includeTerritories && !includeMilitary) {
845
- 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])$";
846
- } else if (includeTerritories && includeMilitary) {
847
- 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])$";
848
- } else if (includeTerritories) {
849
- 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])$";
850
- } else {
851
- 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])$";
852
- }
853
-
854
- regex = caseSensitive ? new RegExp(regex) : new RegExp(regex, "i");
855
- return this.optional(element) || regex.test(value);
856
- },
857
- "Please specify a valid state");
834
+ $.validator.addMethod( "postcodeUK", function( value, element ) {
835
+ 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 );
836
+ }, "Please specify a valid UK postcode" );
837
+
838
+ /*
839
+ * Lets you say "at least X inputs that match selector Y must be filled."
840
+ *
841
+ * The end result is that neither of these inputs:
842
+ *
843
+ * <input class="productinfo" name="partnumber">
844
+ * <input class="productinfo" name="description">
845
+ *
846
+ * ...will validate unless at least one of them is filled.
847
+ *
848
+ * partnumber: {require_from_group: [1,".productinfo"]},
849
+ * description: {require_from_group: [1,".productinfo"]}
850
+ *
851
+ * options[0]: number of fields that must be filled in the group
852
+ * options[1]: CSS selector that defines the group of conditionally required fields
853
+ */
854
+ $.validator.addMethod( "require_from_group", function( value, element, options ) {
855
+ var $fields = $( options[ 1 ], element.form ),
856
+ $fieldsFirst = $fields.eq( 0 ),
857
+ validator = $fieldsFirst.data( "valid_req_grp" ) ? $fieldsFirst.data( "valid_req_grp" ) : $.extend( {}, this ),
858
+ isValid = $fields.filter( function() {
859
+ return validator.elementValue( this );
860
+ } ).length >= options[ 0 ];
861
+
862
+ // Store the cloned validator for future validation
863
+ $fieldsFirst.data( "valid_req_grp", validator );
864
+
865
+ // If element isn't being validated, run each require_from_group field's validation rules
866
+ if ( !$( element ).data( "being_validated" ) ) {
867
+ $fields.data( "being_validated", true );
868
+ $fields.each( function() {
869
+ validator.element( this );
870
+ } );
871
+ $fields.data( "being_validated", false );
872
+ }
873
+ return isValid;
874
+ }, $.validator.format( "Please fill at least {0} of these fields." ) );
875
+
876
+ /*
877
+ * Lets you say "either at least X inputs that match selector Y must be filled,
878
+ * OR they must all be skipped (left blank)."
879
+ *
880
+ * The end result, is that none of these inputs:
881
+ *
882
+ * <input class="productinfo" name="partnumber">
883
+ * <input class="productinfo" name="description">
884
+ * <input class="productinfo" name="color">
885
+ *
886
+ * ...will validate unless either at least two of them are filled,
887
+ * OR none of them are.
888
+ *
889
+ * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
890
+ * description: {skip_or_fill_minimum: [2,".productinfo"]},
891
+ * color: {skip_or_fill_minimum: [2,".productinfo"]}
892
+ *
893
+ * options[0]: number of fields that must be filled in the group
894
+ * options[1]: CSS selector that defines the group of conditionally required fields
895
+ *
896
+ */
897
+ $.validator.addMethod( "skip_or_fill_minimum", function( value, element, options ) {
898
+ var $fields = $( options[ 1 ], element.form ),
899
+ $fieldsFirst = $fields.eq( 0 ),
900
+ validator = $fieldsFirst.data( "valid_skip" ) ? $fieldsFirst.data( "valid_skip" ) : $.extend( {}, this ),
901
+ numberFilled = $fields.filter( function() {
902
+ return validator.elementValue( this );
903
+ } ).length,
904
+ isValid = numberFilled === 0 || numberFilled >= options[ 0 ];
905
+
906
+ // Store the cloned validator for future validation
907
+ $fieldsFirst.data( "valid_skip", validator );
908
+
909
+ // If element isn't being validated, run each skip_or_fill_minimum field's validation rules
910
+ if ( !$( element ).data( "being_validated" ) ) {
911
+ $fields.data( "being_validated", true );
912
+ $fields.each( function() {
913
+ validator.element( this );
914
+ } );
915
+ $fields.data( "being_validated", false );
916
+ }
917
+ return isValid;
918
+ }, $.validator.format( "Please either skip these fields or fill at least {0} of them." ) );
919
+
920
+ /* Validates US States and/or Territories by @jdforsythe
921
+ * Can be case insensitive or require capitalization - default is case insensitive
922
+ * Can include US Territories or not - default does not
923
+ * Can include US Military postal abbreviations (AA, AE, AP) - default does not
924
+ *
925
+ * Note: "States" always includes DC (District of Colombia)
926
+ *
927
+ * Usage examples:
928
+ *
929
+ * This is the default - case insensitive, no territories, no military zones
930
+ * stateInput: {
931
+ * caseSensitive: false,
932
+ * includeTerritories: false,
933
+ * includeMilitary: false
934
+ * }
935
+ *
936
+ * Only allow capital letters, no territories, no military zones
937
+ * stateInput: {
938
+ * caseSensitive: false
939
+ * }
940
+ *
941
+ * Case insensitive, include territories but not military zones
942
+ * stateInput: {
943
+ * includeTerritories: true
944
+ * }
945
+ *
946
+ * Only allow capital letters, include territories and military zones
947
+ * stateInput: {
948
+ * caseSensitive: true,
949
+ * includeTerritories: true,
950
+ * includeMilitary: true
951
+ * }
952
+ *
953
+ */
954
+ $.validator.addMethod( "stateUS", function( value, element, options ) {
955
+ var isDefault = typeof options === "undefined",
956
+ caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
957
+ includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
958
+ includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
959
+ regex;
960
+
961
+ if ( !includeTerritories && !includeMilitary ) {
962
+ 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])$";
963
+ } else if ( includeTerritories && includeMilitary ) {
964
+ 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])$";
965
+ } else if ( includeTerritories ) {
966
+ 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])$";
967
+ } else {
968
+ 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])$";
969
+ }
970
+
971
+ regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" );
972
+ return this.optional( element ) || regex.test( value );
973
+ }, "Please specify a valid state" );
858
974
 
859
975
  // TODO check if value starts with <, otherwise don't try stripping anything
860
- $.validator.addMethod("strippedminlength", function(value, element, param) {
861
- return $(value).text().length >= param;
862
- }, $.validator.format("Please enter at least {0} characters"));
863
-
864
- $.validator.addMethod("time", function(value, element) {
865
- return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(value);
866
- }, "Please enter a valid time, between 00:00 and 23:59");
867
-
868
- $.validator.addMethod("time12h", function(value, element) {
869
- return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
870
- }, "Please enter a valid time in 12-hour am/pm format");
871
-
872
- // same as url, but TLD is optional
873
- $.validator.addMethod("url2", function(value, element) {
874
- return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([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])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
875
- }, $.validator.messages.url);
876
-
877
- /**
878
- * Return true, if the value is a valid vehicle identification number (VIN).
879
- *
880
- * Works with all kind of text inputs.
881
- *
882
- * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
883
- * @desc Declares a required input element whose value must be a valid vehicle identification number.
884
- *
885
- * @name $.validator.methods.vinUS
886
- * @type Boolean
887
- * @cat Plugins/Validate/Methods
888
- */
889
- $.validator.addMethod("vinUS", function(v) {
890
- if (v.length !== 17) {
891
- return false;
892
- }
893
-
894
- 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" ],
895
- VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
896
- FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
897
- rs = 0,
898
- i, n, d, f, cd, cdv;
899
-
900
- for (i = 0; i < 17; i++) {
901
- f = FL[i];
902
- d = v.slice(i, i + 1);
903
- if (i === 8) {
904
- cdv = d;
905
- }
906
- if (!isNaN(d)) {
907
- d *= f;
908
- } else {
909
- for (n = 0; n < LL.length; n++) {
910
- if (d.toUpperCase() === LL[n]) {
911
- d = VL[n];
912
- d *= f;
913
- if (isNaN(cdv) && n === 8) {
914
- cdv = LL[n];
915
- }
916
- break;
917
- }
918
- }
919
- }
920
- rs += d;
921
- }
922
- cd = rs % 11;
923
- if (cd === 10) {
924
- cd = "X";
925
- }
926
- if (cd === cdv) {
927
- return true;
928
- }
929
- return false;
930
- }, "The specified vehicle identification number (VIN) is invalid.");
931
-
932
- $.validator.addMethod("zipcodeUS", function(value, element) {
933
- return this.optional(element) || /^\d{5}(-\d{4})?$/.test(value);
934
- }, "The specified US ZIP Code is invalid");
935
-
936
- $.validator.addMethod("ziprange", function(value, element) {
937
- return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value);
938
- }, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx");
976
+ $.validator.addMethod( "strippedminlength", function( value, element, param ) {
977
+ return $( value ).text().length >= param;
978
+ }, $.validator.format( "Please enter at least {0} characters" ) );
979
+
980
+ $.validator.addMethod( "time", function( value, element ) {
981
+ return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value );
982
+ }, "Please enter a valid time, between 00:00 and 23:59" );
983
+
984
+ $.validator.addMethod( "time12h", function( value, element ) {
985
+ return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
986
+ }, "Please enter a valid time in 12-hour am/pm format" );
987
+
988
+ // Same as url, but TLD is optional
989
+ $.validator.addMethod( "url2", function( value, element ) {
990
+ return this.optional( element ) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([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])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value );
991
+ }, $.validator.messages.url );
992
+
993
+ /**
994
+ * Return true, if the value is a valid vehicle identification number (VIN).
995
+ *
996
+ * Works with all kind of text inputs.
997
+ *
998
+ * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
999
+ * @desc Declares a required input element whose value must be a valid vehicle identification number.
1000
+ *
1001
+ * @name $.validator.methods.vinUS
1002
+ * @type Boolean
1003
+ * @cat Plugins/Validate/Methods
1004
+ */
1005
+ $.validator.addMethod( "vinUS", function( v ) {
1006
+ if ( v.length !== 17 ) {
1007
+ return false;
1008
+ }
1009
+
1010
+ 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" ],
1011
+ VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
1012
+ FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
1013
+ rs = 0,
1014
+ i, n, d, f, cd, cdv;
1015
+
1016
+ for ( i = 0; i < 17; i++ ) {
1017
+ f = FL[ i ];
1018
+ d = v.slice( i, i + 1 );
1019
+ if ( i === 8 ) {
1020
+ cdv = d;
1021
+ }
1022
+ if ( !isNaN( d ) ) {
1023
+ d *= f;
1024
+ } else {
1025
+ for ( n = 0; n < LL.length; n++ ) {
1026
+ if ( d.toUpperCase() === LL[ n ] ) {
1027
+ d = VL[ n ];
1028
+ d *= f;
1029
+ if ( isNaN( cdv ) && n === 8 ) {
1030
+ cdv = LL[ n ];
1031
+ }
1032
+ break;
1033
+ }
1034
+ }
1035
+ }
1036
+ rs += d;
1037
+ }
1038
+ cd = rs % 11;
1039
+ if ( cd === 10 ) {
1040
+ cd = "X";
1041
+ }
1042
+ if ( cd === cdv ) {
1043
+ return true;
1044
+ }
1045
+ return false;
1046
+ }, "The specified vehicle identification number (VIN) is invalid." );
1047
+
1048
+ $.validator.addMethod( "zipcodeUS", function( value, element ) {
1049
+ return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value );
1050
+ }, "The specified US ZIP Code is invalid" );
1051
+
1052
+ $.validator.addMethod( "ziprange", function( value, element ) {
1053
+ return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value );
1054
+ }, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx" );
939
1055
 
940
1056
  }));