jquery-validation-rails 1.11.1.1 → 1.12.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/app/assets/javascripts/jquery.validate.additional-methods.js +634 -418
  4. data/app/assets/javascripts/jquery.validate.js +202 -140
  5. data/app/assets/javascripts/jquery.validate.localization/messages_ar.js +3 -3
  6. data/app/assets/javascripts/jquery.validate.localization/messages_bg.js +4 -4
  7. data/app/assets/javascripts/jquery.validate.localization/messages_ca.js +3 -3
  8. data/app/assets/javascripts/jquery.validate.localization/messages_cs.js +3 -3
  9. data/app/assets/javascripts/jquery.validate.localization/messages_da.js +2 -2
  10. data/app/assets/javascripts/jquery.validate.localization/messages_de.js +2 -2
  11. data/app/assets/javascripts/jquery.validate.localization/messages_el.js +3 -3
  12. data/app/assets/javascripts/jquery.validate.localization/messages_es.js +8 -5
  13. data/app/assets/javascripts/jquery.validate.localization/messages_es_AR.js +29 -0
  14. data/app/assets/javascripts/jquery.validate.localization/messages_et.js +2 -2
  15. data/app/assets/javascripts/jquery.validate.localization/messages_eu.js +3 -3
  16. data/app/assets/javascripts/jquery.validate.localization/messages_fa.js +3 -3
  17. data/app/assets/javascripts/jquery.validate.localization/messages_fi.js +1 -1
  18. data/app/assets/javascripts/jquery.validate.localization/messages_fr.js +8 -5
  19. data/app/assets/javascripts/jquery.validate.localization/messages_he.js +3 -3
  20. data/app/assets/javascripts/jquery.validate.localization/messages_hr.js +3 -3
  21. data/app/assets/javascripts/jquery.validate.localization/messages_hu.js +2 -2
  22. data/app/assets/javascripts/jquery.validate.localization/messages_id.js +24 -0
  23. data/app/assets/javascripts/jquery.validate.localization/messages_is.js +23 -0
  24. data/app/assets/javascripts/jquery.validate.localization/messages_it.js +7 -4
  25. data/app/assets/javascripts/jquery.validate.localization/messages_ja.js +9 -9
  26. data/app/assets/javascripts/jquery.validate.localization/messages_ka.js +3 -3
  27. data/app/assets/javascripts/jquery.validate.localization/messages_kk.js +9 -9
  28. data/app/assets/javascripts/jquery.validate.localization/messages_ko.js +13 -13
  29. data/app/assets/javascripts/jquery.validate.localization/messages_lt.js +9 -9
  30. data/app/assets/javascripts/jquery.validate.localization/messages_lv.js +3 -3
  31. data/app/assets/javascripts/jquery.validate.localization/messages_my.js +3 -3
  32. data/app/assets/javascripts/jquery.validate.localization/messages_nl.js +3 -3
  33. data/app/assets/javascripts/jquery.validate.localization/messages_no.js +2 -2
  34. data/app/assets/javascripts/jquery.validate.localization/messages_pl.js +3 -3
  35. data/app/assets/javascripts/jquery.validate.localization/messages_pt_BR.js +8 -5
  36. data/app/assets/javascripts/jquery.validate.localization/messages_pt_PT.js +6 -3
  37. data/app/assets/javascripts/jquery.validate.localization/messages_ro.js +3 -3
  38. data/app/assets/javascripts/jquery.validate.localization/messages_ru.js +3 -3
  39. data/app/assets/javascripts/jquery.validate.localization/messages_si.js +2 -2
  40. data/app/assets/javascripts/jquery.validate.localization/messages_sk.js +2 -2
  41. data/app/assets/javascripts/jquery.validate.localization/messages_sl.js +3 -3
  42. data/app/assets/javascripts/jquery.validate.localization/messages_sr.js +5 -5
  43. data/app/assets/javascripts/jquery.validate.localization/messages_sr_lat.js +25 -0
  44. data/app/assets/javascripts/jquery.validate.localization/messages_sv.js +1 -1
  45. data/app/assets/javascripts/jquery.validate.localization/messages_th.js +3 -3
  46. data/app/assets/javascripts/jquery.validate.localization/messages_tj.js +25 -0
  47. data/app/assets/javascripts/jquery.validate.localization/messages_tr.js +3 -3
  48. data/app/assets/javascripts/jquery.validate.localization/messages_uk.js +3 -3
  49. data/app/assets/javascripts/jquery.validate.localization/messages_vi.js +9 -9
  50. data/app/assets/javascripts/jquery.validate.localization/messages_zh.js +19 -19
  51. data/app/assets/javascripts/jquery.validate.localization/messages_zh_TW.js +15 -15
  52. data/app/assets/javascripts/jquery.validate.localization/methods_de.js +1 -1
  53. data/app/assets/javascripts/jquery.validate.localization/methods_es_CL.js +12 -0
  54. data/app/assets/javascripts/jquery.validate.localization/methods_nl.js +1 -1
  55. data/app/assets/javascripts/jquery.validate.localization/methods_pt.js +1 -1
  56. data/lib/jquery/validation/rails/version.rb +1 -1
  57. metadata +20 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 520e04ab8b6d08cb8f46ae6bb98c468d48e8df69
4
- data.tar.gz: 8319b15b00eb005a2caa02c4d28df9e64a2a01a6
3
+ metadata.gz: 55f9e31badb7154b56ce386a3e8644de647583ac
4
+ data.tar.gz: 70216628f38ad1d2556f0021954b1f89d778baa9
5
5
  SHA512:
6
- metadata.gz: 1c661ca28ae072be68fd40b88705034e3efbedde0284473519f278ae9497024707f2cae3772f81ffe722df07a54a661fa47c6fd882e2dedeede1c949edae1391
7
- data.tar.gz: c08d96648d65aa88ddec6e525cf50768411a41083f6afbe209a73f60aba05c673370338cda55de6404e7065a94c795fc883c4454b8402c166a4afa11ee22a0f6
6
+ metadata.gz: 9f9086a2a76137bc12e03cc50100c538b02489b4c99f93086efb5fca346a53421e2120ddd737f27edfe7ad5b125275bedaa52997cc7e3107be3b5138261ac7c7
7
+ data.tar.gz: 4cbe6f1e9b6fb205fbec648850ef1412e105433888a998714d607bc9025c5e8c64400b896d358f5e3fed61a0d077d8da51c35d42e11573d7000062b90e171dd6
@@ -1,3 +1,7 @@
1
+ ## 1.12.0
2
+
3
+ * Update included jquery.validation files to 1.12.0
4
+
1
5
  ## 1.11.1.1
2
6
 
3
7
  * Update gemspec to allow Rails >= 4.0 to use gem
@@ -1,22 +1,20 @@
1
1
  /*!
2
- * jQuery Validation Plugin 1.11.1
2
+ * jQuery Validation Plugin v1.12.0
3
3
  *
4
- * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
5
- * http://docs.jquery.com/Plugins/Validation
4
+ * http://jqueryvalidation.org/
6
5
  *
7
- * Copyright 2013 Jörn Zaefferer
8
- * Released under the MIT license:
9
- * http://www.opensource.org/licenses/mit-license.php
6
+ * Copyright (c) 2014 Jörn Zaefferer
7
+ * Released under the MIT license
10
8
  */
11
-
12
9
  (function() {
13
10
 
14
11
  function stripHtml(value) {
15
12
  // remove html tags and space chars
16
- return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ')
13
+ return value.replace(/<.[^<>]*?>/g, " ").replace(/&nbsp;|&#160;/gi, " ")
17
14
  // remove punctuation
18
- .replace(/[.(),;:!?%#$'"_+=\/\-]*/g,'');
15
+ .replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "");
19
16
  }
17
+
20
18
  jQuery.validator.addMethod("maxWords", function(value, element, params) {
21
19
  return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params;
22
20
  }, jQuery.validator.format("Please enter {0} words or less."));
@@ -26,93 +24,273 @@
26
24
  }, jQuery.validator.format("Please enter at least {0} words."));
27
25
 
28
26
  jQuery.validator.addMethod("rangeWords", function(value, element, params) {
29
- var valueStripped = stripHtml(value);
30
- var regex = /\b\w+\b/g;
27
+ var valueStripped = stripHtml(value),
28
+ regex = /\b\w+\b/g;
31
29
  return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];
32
30
  }, jQuery.validator.format("Please enter between {0} and {1} words."));
33
31
 
34
32
  }());
35
33
 
36
- jQuery.validator.addMethod("letterswithbasicpunc", function(value, element) {
37
- return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value);
38
- }, "Letters or punctuation only please");
34
+ // Accept a value from a file input based on a required mimetype
35
+ jQuery.validator.addMethod("accept", function(value, element, param) {
36
+ // Split mime on commas in case we have multiple types we can accept
37
+ var typeParam = typeof param === "string" ? param.replace(/\s/g, "").replace(/,/g, "|") : "image/*",
38
+ optionalValue = this.optional(element),
39
+ i, file;
39
40
 
40
- jQuery.validator.addMethod("alphanumeric", function(value, element) {
41
- return this.optional(element) || /^\w+$/i.test(value);
42
- }, "Letters, numbers, and underscores only please");
41
+ // Element is optional
42
+ if (optionalValue) {
43
+ return optionalValue;
44
+ }
43
45
 
44
- jQuery.validator.addMethod("lettersonly", function(value, element) {
45
- return this.optional(element) || /^[a-z]+$/i.test(value);
46
- }, "Letters only please");
46
+ if (jQuery(element).attr("type") === "file") {
47
+ // If we are using a wildcard, make it regex friendly
48
+ typeParam = typeParam.replace(/\*/g, ".*");
47
49
 
48
- jQuery.validator.addMethod("nowhitespace", function(value, element) {
49
- return this.optional(element) || /^\S+$/i.test(value);
50
- }, "No white space please");
50
+ // Check if the element has a FileList before checking each file
51
+ if (element.files && element.files.length) {
52
+ for (i = 0; i < element.files.length; i++) {
53
+ file = element.files[i];
51
54
 
52
- jQuery.validator.addMethod("ziprange", function(value, element) {
53
- return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value);
54
- }, "Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");
55
+ // Grab the mimetype from the loaded file, verify it matches
56
+ if (!file.type.match(new RegExp( ".?(" + typeParam + ")$", "i"))) {
57
+ return false;
58
+ }
59
+ }
60
+ }
61
+ }
55
62
 
56
- jQuery.validator.addMethod("zipcodeUS", function(value, element) {
57
- return this.optional(element) || /\d{5}-\d{4}$|^\d{5}$/.test(value);
58
- }, "The specified US ZIP Code is invalid");
63
+ // Either return true because we've validated each file, or because the
64
+ // browser does not support element.files and the FileList feature
65
+ return true;
66
+ }, jQuery.validator.format("Please enter a value with a valid mimetype."));
59
67
 
60
- jQuery.validator.addMethod("integer", function(value, element) {
61
- return this.optional(element) || /^-?\d+$/.test(value);
62
- }, "A positive or negative non-decimal number please");
68
+ jQuery.validator.addMethod("alphanumeric", function(value, element) {
69
+ return this.optional(element) || /^\w+$/i.test(value);
70
+ }, "Letters, numbers, and underscores only please");
71
+
72
+ /*
73
+ * Dutch bank account numbers (not 'giro' numbers) have 9 digits
74
+ * and pass the '11 check'.
75
+ * We accept the notation with spaces, as that is common.
76
+ * acceptable: 123456789 or 12 34 56 789
77
+ */
78
+ jQuery.validator.addMethod("bankaccountNL", function(value, element) {
79
+ if (this.optional(element)) {
80
+ return true;
81
+ }
82
+ if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {
83
+ return false;
84
+ }
85
+ // now '11 check'
86
+ var account = value.replace(/ /g, ""), // remove spaces
87
+ sum = 0,
88
+ len = account.length,
89
+ pos, factor, digit;
90
+ for ( pos = 0; pos < len; pos++ ) {
91
+ factor = len - pos;
92
+ digit = account.substring(pos, pos + 1);
93
+ sum = sum + factor * digit;
94
+ }
95
+ return sum % 11 === 0;
96
+ }, "Please specify a valid bank account number");
97
+
98
+ jQuery.validator.addMethod("bankorgiroaccountNL", function(value, element) {
99
+ return this.optional(element) ||
100
+ ($.validator.methods.bankaccountNL.call(this, value, element)) ||
101
+ ($.validator.methods.giroaccountNL.call(this, value, element));
102
+ }, "Please specify a valid bank or giro account number");
63
103
 
64
104
  /**
65
- * Return true, if the value is a valid vehicle identification number (VIN).
66
- *
67
- * Works with all kind of text inputs.
105
+ * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
68
106
  *
69
- * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
70
- * @desc Declares a required input element whose value must be a valid vehicle identification number.
107
+ * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
71
108
  *
72
- * @name jQuery.validator.methods.vinUS
73
- * @type Boolean
74
- * @cat Plugins/Validate/Methods
109
+ * BIC definition in detail:
110
+ * - First 4 characters - bank code (only letters)
111
+ * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
112
+ * - Next 2 characters - location code (letters and digits)
113
+ * a. shall not start with '0' or '1'
114
+ * 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)
115
+ * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
75
116
  */
76
- jQuery.validator.addMethod("vinUS", function(v) {
77
- if (v.length !== 17) {
117
+ jQuery.validator.addMethod("bic", function(value, element) {
118
+ 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 );
119
+ }, "Please specify a valid BIC code");
120
+
121
+ /*
122
+ * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
123
+ * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
124
+ */
125
+ jQuery.validator.addMethod( "cifES", function( value ) {
126
+ "use strict";
127
+
128
+ var num = [],
129
+ controlDigit, sum, i, count, tmp, secondDigit;
130
+
131
+ value = value.toUpperCase();
132
+
133
+ // Quick format test
134
+ 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}$)" ) ) {
78
135
  return false;
79
136
  }
80
- var i, n, d, f, cd, cdv;
81
- 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"];
82
- var VL = [1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9];
83
- var FL = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];
84
- var rs = 0;
85
- for(i = 0; i < 17; i++){
86
- f = FL[i];
87
- d = v.slice(i,i+1);
88
- if (i === 8) {
89
- cdv = d;
90
- }
91
- if (!isNaN(d)) {
92
- d *= f;
93
- } else {
94
- for (n = 0; n < LL.length; n++) {
95
- if (d.toUpperCase() === LL[n]) {
96
- d = VL[n];
97
- d *= f;
98
- if (isNaN(cdv) && n === 8) {
99
- cdv = LL[n];
100
- }
101
- break;
102
- }
103
- }
104
- }
105
- rs += d;
137
+
138
+ for ( i = 0; i < 9; i++ ) {
139
+ num[ i ] = parseInt( value.charAt( i ), 10 );
140
+ }
141
+
142
+ // Algorithm for checking CIF codes
143
+ sum = num[ 2 ] + num[ 4 ] + num[ 6 ];
144
+ for ( count = 1; count < 8; count += 2 ) {
145
+ tmp = ( 2 * num[ count ] ).toString();
146
+ secondDigit = tmp.charAt( 1 );
147
+
148
+ sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) );
149
+ }
150
+
151
+ /* The first (position 1) is a letter following the following criteria:
152
+ * A. Corporations
153
+ * B. LLCs
154
+ * C. General partnerships
155
+ * D. Companies limited partnerships
156
+ * E. Communities of goods
157
+ * F. Cooperative Societies
158
+ * G. Associations
159
+ * H. Communities of homeowners in horizontal property regime
160
+ * J. Civil Societies
161
+ * K. Old format
162
+ * L. Old format
163
+ * M. Old format
164
+ * N. Nonresident entities
165
+ * P. Local authorities
166
+ * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
167
+ * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
168
+ * S. Organs of State Administration and regions
169
+ * V. Agrarian Transformation
170
+ * W. Permanent establishments of non-resident in Spain
171
+ */
172
+ if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {
173
+ sum += "";
174
+ controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );
175
+ value += controlDigit;
176
+ return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );
106
177
  }
107
- cd = rs % 11;
108
- if (cd === 10) {
109
- cd = "X";
178
+
179
+ return false;
180
+
181
+ }, "Please specify a valid CIF number." );
182
+
183
+ /* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
184
+ * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
185
+ * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
186
+ */
187
+ jQuery.validator.addMethod("creditcardtypes", function(value, element, param) {
188
+ if (/[^0-9\-]+/.test(value)) {
189
+ return false;
110
190
  }
111
- if (cd === cdv) {
191
+
192
+ value = value.replace(/\D/g, "");
193
+
194
+ var validTypes = 0x0000;
195
+
196
+ if (param.mastercard) {
197
+ validTypes |= 0x0001;
198
+ }
199
+ if (param.visa) {
200
+ validTypes |= 0x0002;
201
+ }
202
+ if (param.amex) {
203
+ validTypes |= 0x0004;
204
+ }
205
+ if (param.dinersclub) {
206
+ validTypes |= 0x0008;
207
+ }
208
+ if (param.enroute) {
209
+ validTypes |= 0x0010;
210
+ }
211
+ if (param.discover) {
212
+ validTypes |= 0x0020;
213
+ }
214
+ if (param.jcb) {
215
+ validTypes |= 0x0040;
216
+ }
217
+ if (param.unknown) {
218
+ validTypes |= 0x0080;
219
+ }
220
+ if (param.all) {
221
+ validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
222
+ }
223
+ if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard
224
+ return value.length === 16;
225
+ }
226
+ if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa
227
+ return value.length === 16;
228
+ }
229
+ if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex
230
+ return value.length === 15;
231
+ }
232
+ if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub
233
+ return value.length === 14;
234
+ }
235
+ if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute
236
+ return value.length === 15;
237
+ }
238
+ if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover
239
+ return value.length === 16;
240
+ }
241
+ if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb
242
+ return value.length === 16;
243
+ }
244
+ if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb
245
+ return value.length === 15;
246
+ }
247
+ if (validTypes & 0x0080) { //unknown
112
248
  return true;
113
249
  }
114
250
  return false;
115
- }, "The specified vehicle identification number (VIN) is invalid.");
251
+ }, "Please enter a valid credit card number.");
252
+
253
+ /**
254
+ * Validates currencies with any given symbols by @jameslouiz
255
+ * Symbols can be optional or required. Symbols required by default
256
+ *
257
+ * Usage examples:
258
+ * currency: ["£", false] - Use false for soft currency validation
259
+ * currency: ["$", false]
260
+ * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
261
+ *
262
+ * <input class="currencyInput" name="currencyInput">
263
+ *
264
+ * Soft symbol checking
265
+ * currencyInput: {
266
+ * currency: ["$", false]
267
+ * }
268
+ *
269
+ * Strict symbol checking (default)
270
+ * currencyInput: {
271
+ * currency: "$"
272
+ * //OR
273
+ * currency: ["$", true]
274
+ * }
275
+ *
276
+ * Multiple Symbols
277
+ * currencyInput: {
278
+ * currency: "$,£,¢"
279
+ * }
280
+ */
281
+ jQuery.validator.addMethod("currency", function(value, element, param) {
282
+ var isParamString = typeof param === "string",
283
+ symbol = isParamString ? param : param[0],
284
+ soft = isParamString ? true : param[1],
285
+ regex;
286
+
287
+ symbol = symbol.replace(/,/g, "");
288
+ symbol = soft ? symbol + "]" : symbol + "]?";
289
+ 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})?)$";
290
+ regex = new RegExp(regex);
291
+ return this.optional(element) || regex.test(value);
292
+
293
+ }, "Please specify a valid currency");
116
294
 
117
295
  /**
118
296
  * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
@@ -134,14 +312,15 @@ jQuery.validator.addMethod("vinUS", function(v) {
134
312
  * @cat Plugins/Validate/Methods
135
313
  */
136
314
  jQuery.validator.addMethod("dateITA", function(value, element) {
137
- var check = false;
138
- var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
139
- if( re.test(value)) {
140
- var adata = value.split('/');
141
- var gg = parseInt(adata[0],10);
142
- var mm = parseInt(adata[1],10);
143
- var aaaa = parseInt(adata[2],10);
144
- var xdata = new Date(aaaa,mm-1,gg);
315
+ var check = false,
316
+ re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
317
+ adata, gg, mm, aaaa, xdata;
318
+ if ( re.test(value)) {
319
+ adata = value.split("/");
320
+ gg = parseInt(adata[0],10);
321
+ mm = parseInt(adata[1],10);
322
+ aaaa = parseInt(adata[2],10);
323
+ xdata = new Date(aaaa, mm - 1, gg, 12, 0, 0, 0);
145
324
  if ( ( xdata.getFullYear() === aaaa ) && ( xdata.getMonth() === mm - 1 ) && ( xdata.getDate() === gg ) ){
146
325
  check = true;
147
326
  } else {
@@ -153,6 +332,23 @@ jQuery.validator.addMethod("dateITA", function(value, element) {
153
332
  return this.optional(element) || check;
154
333
  }, "Please enter a correct date");
155
334
 
335
+ jQuery.validator.addMethod("dateNL", function(value, element) {
336
+ return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
337
+ }, "Please enter a correct date");
338
+
339
+ // Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
340
+ jQuery.validator.addMethod("extension", function(value, element, param) {
341
+ param = typeof param === "string" ? param.replace(/,/g, "|") : "png|jpe?g|gif";
342
+ return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
343
+ }, jQuery.validator.format("Please enter a value with a valid extension."));
344
+
345
+ /**
346
+ * Dutch giro account numbers (not bank numbers) have max 7 digits
347
+ */
348
+ jQuery.validator.addMethod("giroaccountNL", function(value, element) {
349
+ return this.optional(element) || /^[0-9]{1,7}$/.test(value);
350
+ }, "Please specify a valid giro account number");
351
+
156
352
  /**
157
353
  * IBAN is the international bank account number.
158
354
  * It has a country - specific format, that is checked here too
@@ -162,80 +358,89 @@ jQuery.validator.addMethod("iban", function(value, element) {
162
358
  if (this.optional(element)) {
163
359
  return true;
164
360
  }
165
- if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(value))) {
361
+
362
+ // remove spaces and to upper case
363
+ var iban = value.replace(/ /g,"").toUpperCase(),
364
+ ibancheckdigits = "",
365
+ leadingZeroes = true,
366
+ cRest = "",
367
+ cOperator = "",
368
+ countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
369
+
370
+ if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(iban))) {
166
371
  return false;
167
372
  }
168
373
 
169
374
  // check the country code and find the country specific format
170
- var iban = value.replace(/ /g,'').toUpperCase(); // remove spaces and to upper case
171
- var countrycode = iban.substring(0,2);
172
- var bbancountrypatterns = {
173
- 'AL': "\\d{8}[\\dA-Z]{16}",
174
- 'AD': "\\d{8}[\\dA-Z]{12}",
175
- 'AT': "\\d{16}",
176
- 'AZ': "[\\dA-Z]{4}\\d{20}",
177
- 'BE': "\\d{12}",
178
- 'BH': "[A-Z]{4}[\\dA-Z]{14}",
179
- 'BA': "\\d{16}",
180
- 'BR': "\\d{23}[A-Z][\\dA-Z]",
181
- 'BG': "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
182
- 'CR': "\\d{17}",
183
- 'HR': "\\d{17}",
184
- 'CY': "\\d{8}[\\dA-Z]{16}",
185
- 'CZ': "\\d{20}",
186
- 'DK': "\\d{14}",
187
- 'DO': "[A-Z]{4}\\d{20}",
188
- 'EE': "\\d{16}",
189
- 'FO': "\\d{14}",
190
- 'FI': "\\d{14}",
191
- 'FR': "\\d{10}[\\dA-Z]{11}\\d{2}",
192
- 'GE': "[\\dA-Z]{2}\\d{16}",
193
- 'DE': "\\d{18}",
194
- 'GI': "[A-Z]{4}[\\dA-Z]{15}",
195
- 'GR': "\\d{7}[\\dA-Z]{16}",
196
- 'GL': "\\d{14}",
197
- 'GT': "[\\dA-Z]{4}[\\dA-Z]{20}",
198
- 'HU': "\\d{24}",
199
- 'IS': "\\d{22}",
200
- 'IE': "[\\dA-Z]{4}\\d{14}",
201
- 'IL': "\\d{19}",
202
- 'IT': "[A-Z]\\d{10}[\\dA-Z]{12}",
203
- 'KZ': "\\d{3}[\\dA-Z]{13}",
204
- 'KW': "[A-Z]{4}[\\dA-Z]{22}",
205
- 'LV': "[A-Z]{4}[\\dA-Z]{13}",
206
- 'LB': "\\d{4}[\\dA-Z]{20}",
207
- 'LI': "\\d{5}[\\dA-Z]{12}",
208
- 'LT': "\\d{16}",
209
- 'LU': "\\d{3}[\\dA-Z]{13}",
210
- 'MK': "\\d{3}[\\dA-Z]{10}\\d{2}",
211
- 'MT': "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
212
- 'MR': "\\d{23}",
213
- 'MU': "[A-Z]{4}\\d{19}[A-Z]{3}",
214
- 'MC': "\\d{10}[\\dA-Z]{11}\\d{2}",
215
- 'MD': "[\\dA-Z]{2}\\d{18}",
216
- 'ME': "\\d{18}",
217
- 'NL': "[A-Z]{4}\\d{10}",
218
- 'NO': "\\d{11}",
219
- 'PK': "[\\dA-Z]{4}\\d{16}",
220
- 'PS': "[\\dA-Z]{4}\\d{21}",
221
- 'PL': "\\d{24}",
222
- 'PT': "\\d{21}",
223
- 'RO': "[A-Z]{4}[\\dA-Z]{16}",
224
- 'SM': "[A-Z]\\d{10}[\\dA-Z]{12}",
225
- 'SA': "\\d{2}[\\dA-Z]{18}",
226
- 'RS': "\\d{18}",
227
- 'SK': "\\d{20}",
228
- 'SI': "\\d{15}",
229
- 'ES': "\\d{20}",
230
- 'SE': "\\d{20}",
231
- 'CH': "\\d{5}[\\dA-Z]{12}",
232
- 'TN': "\\d{20}",
233
- 'TR': "\\d{5}[\\dA-Z]{17}",
234
- 'AE': "\\d{3}\\d{16}",
235
- 'GB': "[A-Z]{4}\\d{14}",
236
- 'VG': "[\\dA-Z]{4}\\d{16}"
375
+ countrycode = iban.substring(0,2);
376
+ bbancountrypatterns = {
377
+ "AL": "\\d{8}[\\dA-Z]{16}",
378
+ "AD": "\\d{8}[\\dA-Z]{12}",
379
+ "AT": "\\d{16}",
380
+ "AZ": "[\\dA-Z]{4}\\d{20}",
381
+ "BE": "\\d{12}",
382
+ "BH": "[A-Z]{4}[\\dA-Z]{14}",
383
+ "BA": "\\d{16}",
384
+ "BR": "\\d{23}[A-Z][\\dA-Z]",
385
+ "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
386
+ "CR": "\\d{17}",
387
+ "HR": "\\d{17}",
388
+ "CY": "\\d{8}[\\dA-Z]{16}",
389
+ "CZ": "\\d{20}",
390
+ "DK": "\\d{14}",
391
+ "DO": "[A-Z]{4}\\d{20}",
392
+ "EE": "\\d{16}",
393
+ "FO": "\\d{14}",
394
+ "FI": "\\d{14}",
395
+ "FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
396
+ "GE": "[\\dA-Z]{2}\\d{16}",
397
+ "DE": "\\d{18}",
398
+ "GI": "[A-Z]{4}[\\dA-Z]{15}",
399
+ "GR": "\\d{7}[\\dA-Z]{16}",
400
+ "GL": "\\d{14}",
401
+ "GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
402
+ "HU": "\\d{24}",
403
+ "IS": "\\d{22}",
404
+ "IE": "[\\dA-Z]{4}\\d{14}",
405
+ "IL": "\\d{19}",
406
+ "IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
407
+ "KZ": "\\d{3}[\\dA-Z]{13}",
408
+ "KW": "[A-Z]{4}[\\dA-Z]{22}",
409
+ "LV": "[A-Z]{4}[\\dA-Z]{13}",
410
+ "LB": "\\d{4}[\\dA-Z]{20}",
411
+ "LI": "\\d{5}[\\dA-Z]{12}",
412
+ "LT": "\\d{16}",
413
+ "LU": "\\d{3}[\\dA-Z]{13}",
414
+ "MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
415
+ "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
416
+ "MR": "\\d{23}",
417
+ "MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
418
+ "MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
419
+ "MD": "[\\dA-Z]{2}\\d{18}",
420
+ "ME": "\\d{18}",
421
+ "NL": "[A-Z]{4}\\d{10}",
422
+ "NO": "\\d{11}",
423
+ "PK": "[\\dA-Z]{4}\\d{16}",
424
+ "PS": "[\\dA-Z]{4}\\d{21}",
425
+ "PL": "\\d{24}",
426
+ "PT": "\\d{21}",
427
+ "RO": "[A-Z]{4}[\\dA-Z]{16}",
428
+ "SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
429
+ "SA": "\\d{2}[\\dA-Z]{18}",
430
+ "RS": "\\d{18}",
431
+ "SK": "\\d{20}",
432
+ "SI": "\\d{15}",
433
+ "ES": "\\d{20}",
434
+ "SE": "\\d{20}",
435
+ "CH": "\\d{5}[\\dA-Z]{12}",
436
+ "TN": "\\d{20}",
437
+ "TR": "\\d{5}[\\dA-Z]{17}",
438
+ "AE": "\\d{3}\\d{16}",
439
+ "GB": "[A-Z]{4}\\d{14}",
440
+ "VG": "[\\dA-Z]{4}\\d{16}"
237
441
  };
238
- var bbanpattern = bbancountrypatterns[countrycode];
442
+
443
+ bbanpattern = bbancountrypatterns[countrycode];
239
444
  // As new countries will start using IBAN in the
240
445
  // future, we only check if the countrycode is known.
241
446
  // This prevents false negatives, while almost all
@@ -243,19 +448,16 @@ jQuery.validator.addMethod("iban", function(value, element) {
243
448
  // by the checksum validation below anyway.
244
449
  // Strict checking should return FALSE for unknown
245
450
  // countries.
246
- if (typeof bbanpattern !== 'undefined') {
247
- var ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
451
+ if (typeof bbanpattern !== "undefined") {
452
+ ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
248
453
  if (!(ibanregexp.test(iban))) {
249
454
  return false; // invalid country specific format
250
455
  }
251
456
  }
252
457
 
253
458
  // now check the checksum, first convert to digits
254
- var ibancheck = iban.substring(4,iban.length) + iban.substring(0,4);
255
- var ibancheckdigits = "";
256
- var leadingZeroes = true;
257
- var charAt;
258
- for (var i =0; i<ibancheck.length; i++) {
459
+ ibancheck = iban.substring(4,iban.length) + iban.substring(0,4);
460
+ for (i = 0; i < ibancheck.length; i++) {
259
461
  charAt = ibancheck.charAt(i);
260
462
  if (charAt !== "0") {
261
463
  leadingZeroes = false;
@@ -266,225 +468,116 @@ jQuery.validator.addMethod("iban", function(value, element) {
266
468
  }
267
469
 
268
470
  // calculate the result of: ibancheckdigits % 97
269
- var cRest = '';
270
- var cOperator = '';
271
- for (var p=0; p<ibancheckdigits.length; p++) {
272
- var cChar = ibancheckdigits.charAt(p);
273
- cOperator = '' + cRest + '' + cChar;
471
+ for (p = 0; p < ibancheckdigits.length; p++) {
472
+ cChar = ibancheckdigits.charAt(p);
473
+ cOperator = "" + cRest + "" + cChar;
274
474
  cRest = cOperator % 97;
275
- }
475
+ }
276
476
  return cRest === 1;
277
477
  }, "Please specify a valid IBAN");
278
478
 
279
- jQuery.validator.addMethod("dateNL", function(value, element) {
280
- return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
281
- }, "Please enter a correct date");
479
+ jQuery.validator.addMethod("integer", function(value, element) {
480
+ return this.optional(element) || /^-?\d+$/.test(value);
481
+ }, "A positive or negative non-decimal number please");
282
482
 
283
- /**
284
- * Dutch phone numbers have 10 digits (or 11 and start with +31).
285
- */
286
- jQuery.validator.addMethod("phoneNL", function(value, element) {
287
- 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);
288
- }, "Please specify a valid phone number.");
483
+ jQuery.validator.addMethod("ipv4", function(value, element) {
484
+ 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);
485
+ }, "Please enter a valid IP v4 address.");
486
+
487
+ jQuery.validator.addMethod("ipv6", function(value, element) {
488
+ 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);
489
+ }, "Please enter a valid IP v6 address.");
490
+
491
+ jQuery.validator.addMethod("lettersonly", function(value, element) {
492
+ return this.optional(element) || /^[a-z]+$/i.test(value);
493
+ }, "Letters only please");
494
+
495
+ jQuery.validator.addMethod("letterswithbasicpunc", function(value, element) {
496
+ return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value);
497
+ }, "Letters or punctuation only please");
289
498
 
290
499
  jQuery.validator.addMethod("mobileNL", function(value, element) {
291
500
  return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
292
501
  }, "Please specify a valid mobile number");
293
502
 
294
- jQuery.validator.addMethod("postalcodeNL", function(value, element) {
295
- return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
296
- }, "Please specify a valid postal code");
503
+ /* For UK phone functions, do the following server side processing:
504
+ * Compare original input with this RegEx pattern:
505
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
506
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
507
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
508
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
509
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
510
+ */
511
+ jQuery.validator.addMethod("mobileUK", function(phone_number, element) {
512
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
513
+ return this.optional(element) || phone_number.length > 9 &&
514
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/);
515
+ }, "Please specify a valid mobile number");
297
516
 
298
517
  /*
299
- * Dutch bank account numbers (not 'giro' numbers) have 9 digits
300
- * and pass the '11 check'.
301
- * We accept the notation with spaces, as that is common.
302
- * acceptable: 123456789 or 12 34 56 789
518
+ * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain
303
519
  */
304
- jQuery.validator.addMethod("bankaccountNL", function(value, element) {
305
- if (this.optional(element)) {
306
- return true;
307
- }
308
- if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {
520
+ jQuery.validator.addMethod( "nieES", function( value ) {
521
+ "use strict";
522
+
523
+ value = value.toUpperCase();
524
+
525
+ // Basic format test
526
+ 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}$)" ) ) {
309
527
  return false;
310
528
  }
311
- // now '11 check'
312
- var account = value.replace(/ /g,''); // remove spaces
313
- var sum = 0;
314
- var len = account.length;
315
- for (var pos=0; pos<len; pos++) {
316
- var factor = len - pos;
317
- var digit = account.substring(pos, pos+1);
318
- sum = sum + factor * digit;
319
- }
320
- return sum % 11 === 0;
321
- }, "Please specify a valid bank account number");
322
529
 
323
- /**
324
- * Dutch giro account numbers (not bank numbers) have max 7 digits
325
- */
326
- jQuery.validator.addMethod("giroaccountNL", function(value, element) {
327
- return this.optional(element) || /^[0-9]{1,7}$/.test(value);
328
- }, "Please specify a valid giro account number");
530
+ // Test NIE
531
+ //T
532
+ if ( /^[T]{1}/.test( value ) ) {
533
+ return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );
534
+ }
329
535
 
330
- jQuery.validator.addMethod("bankorgiroaccountNL", function(value, element) {
331
- return this.optional(element) ||
332
- ($.validator.methods["bankaccountNL"].call(this, value, element)) ||
333
- ($.validator.methods["giroaccountNL"].call(this, value, element));
334
- }, "Please specify a valid bank or giro account number");
536
+ //XYZ
537
+ if ( /^[XYZ]{1}/.test( value ) ) {
538
+ return (
539
+ value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt(
540
+ value.replace( "X", "0" )
541
+ .replace( "Y", "1" )
542
+ .replace( "Z", "2" )
543
+ .substring( 0, 8 ) % 23
544
+ )
545
+ );
546
+ }
335
547
 
548
+ return false;
336
549
 
337
- jQuery.validator.addMethod("time", function(value, element) {
338
- return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(value);
339
- }, "Please enter a valid time, between 00:00 and 23:59");
340
- jQuery.validator.addMethod("time12h", function(value, element) {
341
- return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
342
- }, "Please enter a valid time in 12-hour am/pm format");
550
+ }, "Please specify a valid NIE number." );
343
551
 
344
- /**
345
- * matches US phone number format
346
- *
347
- * where the area code may not start with 1 and the prefix may not start with 1
348
- * allows '-' or ' ' as a separator and allows parens around area code
349
- * some people may want to put a '1' in front of their number
350
- *
351
- * 1(212)-999-2345 or
352
- * 212 999 2344 or
353
- * 212-999-0983
354
- *
355
- * but not
356
- * 111-123-5434
357
- * and not
358
- * 212 123 4567
552
+ /*
553
+ * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
359
554
  */
360
- jQuery.validator.addMethod("phoneUS", function(phone_number, element) {
361
- phone_number = phone_number.replace(/\s+/g, "");
362
- return this.optional(element) || phone_number.length > 9 &&
363
- phone_number.match(/^(\+?1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
364
- }, "Please specify a valid phone number");
365
-
366
- jQuery.validator.addMethod('phoneUK', function(phone_number, element) {
367
- phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
368
- return this.optional(element) || phone_number.length > 9 &&
369
- 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})$/);
370
- }, 'Please specify a valid phone number');
371
-
372
- jQuery.validator.addMethod('mobileUK', function(phone_number, element) {
373
- phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
374
- return this.optional(element) || phone_number.length > 9 &&
375
- phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[45789]\d{2}|624)\s?\d{3}\s?\d{3})$/);
376
- }, 'Please specify a valid mobile number');
377
-
378
- //Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
379
- jQuery.validator.addMethod('phonesUK', function(phone_number, element) {
380
- phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
381
- return this.optional(element) || phone_number.length > 9 &&
382
- phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[45789]\d{8}|624\d{6})))$/);
383
- }, 'Please specify a valid uk phone number');
384
- // On the above three UK functions, do the following server side processing:
385
- // Compare original input with this RegEx pattern:
386
- // ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
387
- // Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
388
- // Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
389
- // A number of very detailed GB telephone number RegEx patterns can also be found at:
390
- // http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
391
-
392
- // Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
393
- jQuery.validator.addMethod('postcodeUK', function(value, element) {
394
- 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);
395
- }, 'Please specify a valid UK postcode');
396
-
397
- // TODO check if value starts with <, otherwise don't try stripping anything
398
- jQuery.validator.addMethod("strippedminlength", function(value, element, param) {
399
- return jQuery(value).text().length >= param;
400
- }, jQuery.validator.format("Please enter at least {0} characters"));
555
+ jQuery.validator.addMethod( "nifES", function( value ) {
556
+ "use strict";
401
557
 
402
- // same as email, but TLD is optional
403
- jQuery.validator.addMethod("email2", function(value, element, param) {
404
- return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
405
- }, jQuery.validator.messages.email);
406
-
407
- // same as url, but TLD is optional
408
- jQuery.validator.addMethod("url2", function(value, element, param) {
409
- 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);
410
- }, jQuery.validator.messages.url);
558
+ value = value.toUpperCase();
411
559
 
412
- // NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
413
- // Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
414
- // Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
415
- jQuery.validator.addMethod("creditcardtypes", function(value, element, param) {
416
- if (/[^0-9\-]+/.test(value)) {
560
+ // Basic format test
561
+ 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}$)") ) {
417
562
  return false;
418
563
  }
419
564
 
420
- value = value.replace(/\D/g, "");
421
-
422
- var validTypes = 0x0000;
423
-
424
- if (param.mastercard) {
425
- validTypes |= 0x0001;
426
- }
427
- if (param.visa) {
428
- validTypes |= 0x0002;
429
- }
430
- if (param.amex) {
431
- validTypes |= 0x0004;
432
- }
433
- if (param.dinersclub) {
434
- validTypes |= 0x0008;
435
- }
436
- if (param.enroute) {
437
- validTypes |= 0x0010;
438
- }
439
- if (param.discover) {
440
- validTypes |= 0x0020;
441
- }
442
- if (param.jcb) {
443
- validTypes |= 0x0040;
444
- }
445
- if (param.unknown) {
446
- validTypes |= 0x0080;
447
- }
448
- if (param.all) {
449
- validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
450
- }
451
- if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard
452
- return value.length === 16;
453
- }
454
- if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa
455
- return value.length === 16;
565
+ // Test NIF
566
+ if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
567
+ return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
456
568
  }
457
- if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex
458
- return value.length === 15;
459
- }
460
- if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub
461
- return value.length === 14;
462
- }
463
- if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute
464
- return value.length === 15;
465
- }
466
- if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover
467
- return value.length === 16;
468
- }
469
- if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb
470
- return value.length === 16;
471
- }
472
- if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb
473
- return value.length === 15;
474
- }
475
- if (validTypes & 0x0080) { //unknown
476
- return true;
569
+ // Test specials NIF (starts with K, L or M)
570
+ if ( /^[KLM]{1}/.test( value ) ) {
571
+ return ( value[ 8 ] === String.fromCharCode( 64 ) );
477
572
  }
573
+
478
574
  return false;
479
- }, "Please enter a valid credit card number.");
480
575
 
481
- jQuery.validator.addMethod("ipv4", function(value, element, param) {
482
- 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);
483
- }, "Please enter a valid IP v4 address.");
576
+ }, "Please specify a valid NIF number." );
484
577
 
485
- jQuery.validator.addMethod("ipv6", function(value, element, param) {
486
- 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);
487
- }, "Please enter a valid IP v6 address.");
578
+ jQuery.validator.addMethod("nowhitespace", function(value, element) {
579
+ return this.optional(element) || /^\S+$/i.test(value);
580
+ }, "No white space please");
488
581
 
489
582
  /**
490
583
  * Return true if the field value matches the given format RegExp
@@ -503,42 +596,116 @@ jQuery.validator.addMethod("pattern", function(value, element, param) {
503
596
  if (this.optional(element)) {
504
597
  return true;
505
598
  }
506
- if (typeof param === 'string') {
507
- param = new RegExp('^(?:' + param + ')$');
599
+ if (typeof param === "string") {
600
+ param = new RegExp(param);
508
601
  }
509
602
  return param.test(value);
510
603
  }, "Invalid format.");
511
604
 
605
+ /**
606
+ * Dutch phone numbers have 10 digits (or 11 and start with +31).
607
+ */
608
+ jQuery.validator.addMethod("phoneNL", function(value, element) {
609
+ 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);
610
+ }, "Please specify a valid phone number.");
611
+
612
+ /* For UK phone functions, do the following server side processing:
613
+ * Compare original input with this RegEx pattern:
614
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
615
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
616
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
617
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
618
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
619
+ */
620
+ jQuery.validator.addMethod("phoneUK", function(phone_number, element) {
621
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
622
+ return this.optional(element) || phone_number.length > 9 &&
623
+ 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})$/);
624
+ }, "Please specify a valid phone number");
625
+
626
+ /**
627
+ * matches US phone number format
628
+ *
629
+ * where the area code may not start with 1 and the prefix may not start with 1
630
+ * allows '-' or ' ' as a separator and allows parens around area code
631
+ * some people may want to put a '1' in front of their number
632
+ *
633
+ * 1(212)-999-2345 or
634
+ * 212 999 2344 or
635
+ * 212-999-0983
636
+ *
637
+ * but not
638
+ * 111-123-5434
639
+ * and not
640
+ * 212 123 4567
641
+ */
642
+ jQuery.validator.addMethod("phoneUS", function(phone_number, element) {
643
+ phone_number = phone_number.replace(/\s+/g, "");
644
+ return this.optional(element) || phone_number.length > 9 &&
645
+ 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}$/);
646
+ }, "Please specify a valid phone number");
647
+
648
+ /* For UK phone functions, do the following server side processing:
649
+ * Compare original input with this RegEx pattern:
650
+ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
651
+ * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
652
+ * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
653
+ * A number of very detailed GB telephone number RegEx patterns can also be found at:
654
+ * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
655
+ */
656
+ //Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
657
+ jQuery.validator.addMethod("phonesUK", function(phone_number, element) {
658
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g, "");
659
+ return this.optional(element) || phone_number.length > 9 &&
660
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/);
661
+ }, "Please specify a valid uk phone number");
662
+
663
+ jQuery.validator.addMethod("postalcodeNL", function(value, element) {
664
+ return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
665
+ }, "Please specify a valid postal code");
666
+
667
+ // Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
668
+ jQuery.validator.addMethod("postcodeUK", function(value, element) {
669
+ 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);
670
+ }, "Please specify a valid UK postcode");
512
671
 
513
672
  /*
514
673
  * Lets you say "at least X inputs that match selector Y must be filled."
515
674
  *
516
675
  * The end result is that neither of these inputs:
517
676
  *
518
- * <input class="productinfo" name="partnumber">
519
- * <input class="productinfo" name="description">
677
+ * <input class="productinfo" name="partnumber">
678
+ * <input class="productinfo" name="description">
520
679
  *
521
- * ...will validate unless at least one of them is filled.
680
+ * ...will validate unless at least one of them is filled.
522
681
  *
523
- * partnumber: {require_from_group: [1,".productinfo"]},
682
+ * partnumber: {require_from_group: [1,".productinfo"]},
524
683
  * description: {require_from_group: [1,".productinfo"]}
525
684
  *
685
+ * options[0]: number of fields that must be filled in the group
686
+ * options[1]: CSS selector that defines the group of conditionally required fields
526
687
  */
527
688
  jQuery.validator.addMethod("require_from_group", function(value, element, options) {
528
- var validator = this;
529
- var selector = options[1];
530
- var validOrNot = $(selector, element.form).filter(function() {
531
- return validator.elementValue(this);
532
- }).length >= options[0];
533
-
534
- if(!$(element).data('being_validated')) {
535
- var fields = $(selector, element.form);
536
- fields.data('being_validated', true);
537
- fields.valid();
538
- fields.data('being_validated', false);
539
- }
540
- return validOrNot;
541
- }, jQuery.format("Please fill at least {0} of these fields."));
689
+ var $fields = $(options[1], element.form),
690
+ $fieldsFirst = $fields.eq(0),
691
+ validator = $fieldsFirst.data("valid_req_grp") ? $fieldsFirst.data("valid_req_grp") : $.extend({}, this),
692
+ isValid = $fields.filter(function() {
693
+ return validator.elementValue(this);
694
+ }).length >= options[0];
695
+
696
+ // Store the cloned validator for future validation
697
+ $fieldsFirst.data("valid_req_grp", validator);
698
+
699
+ // If element isn't being validated, run each require_from_group field's validation rules
700
+ if (!$(element).data("being_validated")) {
701
+ $fields.data("being_validated", true);
702
+ $fields.each(function() {
703
+ validator.element(this);
704
+ });
705
+ $fields.data("being_validated", false);
706
+ }
707
+ return isValid;
708
+ }, jQuery.validator.format("Please fill at least {0} of these fields."));
542
709
 
543
710
  /*
544
711
  * Lets you say "either at least X inputs that match selector Y must be filled,
@@ -546,72 +713,121 @@ jQuery.validator.addMethod("require_from_group", function(value, element, option
546
713
  *
547
714
  * The end result, is that none of these inputs:
548
715
  *
549
- * <input class="productinfo" name="partnumber">
550
- * <input class="productinfo" name="description">
551
- * <input class="productinfo" name="color">
716
+ * <input class="productinfo" name="partnumber">
717
+ * <input class="productinfo" name="description">
718
+ * <input class="productinfo" name="color">
552
719
  *
553
- * ...will validate unless either at least two of them are filled,
554
- * OR none of them are.
720
+ * ...will validate unless either at least two of them are filled,
721
+ * OR none of them are.
555
722
  *
556
- * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
557
- * description: {skip_or_fill_minimum: [2,".productinfo"]},
558
- * color: {skip_or_fill_minimum: [2,".productinfo"]}
723
+ * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
724
+ * description: {skip_or_fill_minimum: [2,".productinfo"]},
725
+ * color: {skip_or_fill_minimum: [2,".productinfo"]}
726
+ *
727
+ * options[0]: number of fields that must be filled in the group
728
+ * options[1]: CSS selector that defines the group of conditionally required fields
559
729
  *
560
730
  */
561
731
  jQuery.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
562
- var validator = this,
563
- numberRequired = options[0],
564
- selector = options[1];
565
- var numberFilled = $(selector, element.form).filter(function() {
566
- return validator.elementValue(this);
567
- }).length;
568
- var valid = numberFilled >= numberRequired || numberFilled === 0;
569
-
570
- if(!$(element).data('being_validated')) {
571
- var fields = $(selector, element.form);
572
- fields.data('being_validated', true);
573
- fields.valid();
574
- fields.data('being_validated', false);
575
- }
576
- return valid;
577
- }, jQuery.format("Please either skip these fields or fill at least {0} of them."));
732
+ var $fields = $(options[1], element.form),
733
+ $fieldsFirst = $fields.eq(0),
734
+ validator = $fieldsFirst.data("valid_skip") ? $fieldsFirst.data("valid_skip") : $.extend({}, this),
735
+ numberFilled = $fields.filter(function() {
736
+ return validator.elementValue(this);
737
+ }).length,
738
+ isValid = numberFilled === 0 || numberFilled >= options[0];
739
+
740
+ // Store the cloned validator for future validation
741
+ $fieldsFirst.data("valid_skip", validator);
742
+
743
+ // If element isn't being validated, run each skip_or_fill_minimum field's validation rules
744
+ if (!$(element).data("being_validated")) {
745
+ $fields.data("being_validated", true);
746
+ $fields.each(function() {
747
+ validator.element(this);
748
+ });
749
+ $fields.data("being_validated", false);
750
+ }
751
+ return isValid;
752
+ }, jQuery.validator.format("Please either skip these fields or fill at least {0} of them."));
578
753
 
579
- // Accept a value from a file input based on a required mimetype
580
- jQuery.validator.addMethod("accept", function(value, element, param) {
581
- // Split mime on commas in case we have multiple types we can accept
582
- var typeParam = typeof param === "string" ? param.replace(/\s/g, '').replace(/,/g, '|') : "image/*",
583
- optionalValue = this.optional(element),
584
- i, file;
754
+ // TODO check if value starts with <, otherwise don't try stripping anything
755
+ jQuery.validator.addMethod("strippedminlength", function(value, element, param) {
756
+ return jQuery(value).text().length >= param;
757
+ }, jQuery.validator.format("Please enter at least {0} characters"));
585
758
 
586
- // Element is optional
587
- if (optionalValue) {
588
- return optionalValue;
589
- }
759
+ jQuery.validator.addMethod("time", function(value, element) {
760
+ return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(value);
761
+ }, "Please enter a valid time, between 00:00 and 23:59");
590
762
 
591
- if ($(element).attr("type") === "file") {
592
- // If we are using a wildcard, make it regex friendly
593
- typeParam = typeParam.replace(/\*/g, ".*");
763
+ jQuery.validator.addMethod("time12h", function(value, element) {
764
+ return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
765
+ }, "Please enter a valid time in 12-hour am/pm format");
594
766
 
595
- // Check if the element has a FileList before checking each file
596
- if (element.files && element.files.length) {
597
- for (i = 0; i < element.files.length; i++) {
598
- file = element.files[i];
767
+ // same as url, but TLD is optional
768
+ jQuery.validator.addMethod("url2", function(value, element) {
769
+ 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);
770
+ }, jQuery.validator.messages.url);
599
771
 
600
- // Grab the mimetype from the loaded file, verify it matches
601
- if (!file.type.match(new RegExp( ".?(" + typeParam + ")$", "i"))) {
602
- return false;
772
+ /**
773
+ * Return true, if the value is a valid vehicle identification number (VIN).
774
+ *
775
+ * Works with all kind of text inputs.
776
+ *
777
+ * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
778
+ * @desc Declares a required input element whose value must be a valid vehicle identification number.
779
+ *
780
+ * @name jQuery.validator.methods.vinUS
781
+ * @type Boolean
782
+ * @cat Plugins/Validate/Methods
783
+ */
784
+ jQuery.validator.addMethod("vinUS", function(v) {
785
+ if (v.length !== 17) {
786
+ return false;
787
+ }
788
+
789
+ 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" ],
790
+ VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
791
+ FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
792
+ rs = 0,
793
+ i, n, d, f, cd, cdv;
794
+
795
+ for (i = 0; i < 17; i++){
796
+ f = FL[i];
797
+ d = v.slice(i,i + 1);
798
+ if (i === 8) {
799
+ cdv = d;
800
+ }
801
+ if (!isNaN(d)) {
802
+ d *= f;
803
+ } else {
804
+ for (n = 0; n < LL.length; n++) {
805
+ if (d.toUpperCase() === LL[n]) {
806
+ d = VL[n];
807
+ d *= f;
808
+ if (isNaN(cdv) && n === 8) {
809
+ cdv = LL[n];
810
+ }
811
+ break;
603
812
  }
604
813
  }
605
814
  }
815
+ rs += d;
816
+ }
817
+ cd = rs % 11;
818
+ if (cd === 10) {
819
+ cd = "X";
606
820
  }
821
+ if (cd === cdv) {
822
+ return true;
823
+ }
824
+ return false;
825
+ }, "The specified vehicle identification number (VIN) is invalid.");
607
826
 
608
- // Either return true because we've validated each file, or because the
609
- // browser does not support element.files and the FileList feature
610
- return true;
611
- }, jQuery.format("Please enter a value with a valid mimetype."));
827
+ jQuery.validator.addMethod("zipcodeUS", function(value, element) {
828
+ return this.optional(element) || /^\d{5}-\d{4}$|^\d{5}$/.test(value);
829
+ }, "The specified US ZIP Code is invalid");
612
830
 
613
- // Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
614
- jQuery.validator.addMethod("extension", function(value, element, param) {
615
- param = typeof param === "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
616
- return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
617
- }, jQuery.format("Please enter a value with a valid extension."));
831
+ jQuery.validator.addMethod("ziprange", function(value, element) {
832
+ return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value);
833
+ }, "Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");