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