ajax_validation 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +101 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/ajax_validation.js +14 -0
  6. data/app/assets/javascripts/ajax_validation/jquery.validate.additional-methods.js +617 -0
  7. data/app/assets/javascripts/ajax_validation/jquery.validate.js +2 -0
  8. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ar.js +25 -0
  9. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_bg.js +25 -0
  10. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ca.js +25 -0
  11. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_cs.js +25 -0
  12. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_da.js +22 -0
  13. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_de.js +22 -0
  14. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_el.js +25 -0
  15. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_es.js +28 -0
  16. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_es_AR.js +29 -0
  17. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_et.js +23 -0
  18. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_eu.js +25 -0
  19. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_fa.js +25 -0
  20. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_fi.js +23 -0
  21. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_fr.js +50 -0
  22. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_he.js +25 -0
  23. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_hr.js +25 -0
  24. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_hu.js +24 -0
  25. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_id.js +24 -0
  26. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_is.js +23 -0
  27. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_it.js +28 -0
  28. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ja.js +25 -0
  29. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ka.js +25 -0
  30. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_kk.js +25 -0
  31. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ko.js +25 -0
  32. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_lt.js +25 -0
  33. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_lv.js +25 -0
  34. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_my.js +25 -0
  35. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_nl.js +35 -0
  36. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_no.js +25 -0
  37. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_pl.js +25 -0
  38. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_pt_BR.js +29 -0
  39. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_pt_PT.js +29 -0
  40. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ro.js +25 -0
  41. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_ru.js +25 -0
  42. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_si.js +25 -0
  43. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_sk.js +22 -0
  44. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_sl.js +25 -0
  45. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_sr.js +25 -0
  46. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_sr_lat.js +25 -0
  47. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_sv.js +23 -0
  48. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_th.js +25 -0
  49. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_tj.js +25 -0
  50. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_tr.js +25 -0
  51. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_uk.js +25 -0
  52. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_vi.js +25 -0
  53. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_zh.js +25 -0
  54. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/messages_zh_TW.js +26 -0
  55. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/methods_de.js +12 -0
  56. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/methods_es_CL.js +12 -0
  57. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/methods_nl.js +9 -0
  58. data/app/assets/javascripts/ajax_validation/jquery.validate.localization/methods_pt.js +9 -0
  59. data/app/assets/javascripts/ajax_validation/theme_bootstrap3.js +17 -0
  60. data/app/controllers/ajax_validation/application_controller.rb +41 -0
  61. data/config/routes.rb +3 -0
  62. data/lib/ajax_validation.rb +4 -0
  63. data/lib/ajax_validation/engine.rb +6 -0
  64. data/lib/ajax_validation/version.rb +3 -0
  65. data/lib/tasks/ajax_validation_tasks.rake +4 -0
  66. metadata +136 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f501f2918b3de2b407bfc8ff163f21d385cd163
4
+ data.tar.gz: 00c3f5db71008297c18c016d3422c3a000793626
5
+ SHA512:
6
+ metadata.gz: a78039659b6b547e0144ecfdf7b09128912586bfbd4826afd65e8fc04c4a791e1f58659b66afb80da6342b6dff9159b4a17853a87cc320c5bdb67ccad642d63a
7
+ data.tar.gz: 571cfaa97b7b24d26f3f5160a3134e8352ee4afa589a3ae732f4237e8975fcf0e6df52e82a48718c50f2f5f0f11cebabaf43dfc227701ad16981f832aa7be327
@@ -0,0 +1,20 @@
1
+ Copyright 2015 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,101 @@
1
+ # AjaxValidation
2
+
3
+ AjaxValidation allows easy client side form validation for Rails 4.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ajax_validation'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install ajax_validation
23
+ ```
24
+
25
+ ### Include ajax_validation javascript assets
26
+
27
+ Add the following to your `app/assets/javascripts/application.js`:
28
+
29
+ ```
30
+ //= require ajax_validation
31
+ ```
32
+
33
+ Localization:
34
+
35
+ ```
36
+ //= require ajax_validation/jquery.validate.localization/messages_xx
37
+ ```
38
+
39
+ Theme:
40
+
41
+ ```
42
+ //= require ajax_validation/theme_bootstrap3
43
+ ```
44
+
45
+ ### Mount the engine in your routes file, as follows:
46
+
47
+ ```ruby
48
+ # config/routes.rb
49
+ mount AjaxValidation::Engine => "/ajax_validation"
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ ### Add a simple validation to your model.
55
+
56
+ ```ruby
57
+ # app/models/project.rb
58
+ class Project < ActiveRecord::Base
59
+ validates :name, :presence => true, uniqueness: { case_sensitive: false }, :length => { maximum: 10 }
60
+ end
61
+ ```
62
+
63
+ ### app/assets/javascripts/validate.js.coffee
64
+
65
+ ```
66
+ jQuery ->
67
+
68
+ token = $('meta[name="csrf-token"]').attr('content')
69
+ $.ajaxPrefilter((options, originalOptions, xhr)->
70
+ xhr.setRequestHeader('X-CSRF-Token', token)
71
+ )
72
+
73
+ validate_url = '/ajax_validation/validate'
74
+ id = null
75
+
76
+ form = $('#new_project, [id^=edit_project_]')
77
+ action = form.attr('action')
78
+ id = action.split('/')[2] if typeof action != "undefined"
79
+ form.validate(
80
+ debug: false
81
+ onkeyup: false
82
+ rules:
83
+ 'project[name]':
84
+ required: true
85
+ remote:
86
+ url: validate_url
87
+ data:
88
+ id: id
89
+ type: 'post'
90
+ )
91
+
92
+ ```
93
+
94
+
95
+ ## Contributing
96
+
97
+ 1. Fork it
98
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
99
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
100
+ 4. Push to the branch (`git push origin my-new-feature`)
101
+ 5. Create new Pull Request
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AjaxValidation'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,14 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require ajax_validation/jquery.validate
14
+ //= require ajax_validation/jquery.validate.additional-methods
@@ -0,0 +1,617 @@
1
+ /*!
2
+ * jQuery Validation Plugin 1.12.0pre
3
+ *
4
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
5
+ * http://docs.jquery.com/Plugins/Validation
6
+ *
7
+ * Copyright 2013 Jörn Zaefferer
8
+ * Released under the MIT license:
9
+ * http://www.opensource.org/licenses/mit-license.php
10
+ */
11
+
12
+ (function() {
13
+
14
+ function stripHtml(value) {
15
+ // remove html tags and space chars
16
+ return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ')
17
+ // remove punctuation
18
+ .replace(/[.(),;:!?%#$'"_+=\/\-]*/g,'');
19
+ }
20
+ jQuery.validator.addMethod("maxWords", function(value, element, params) {
21
+ return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params;
22
+ }, jQuery.validator.format("Please enter {0} words or less."));
23
+
24
+ jQuery.validator.addMethod("minWords", function(value, element, params) {
25
+ return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params;
26
+ }, jQuery.validator.format("Please enter at least {0} words."));
27
+
28
+ jQuery.validator.addMethod("rangeWords", function(value, element, params) {
29
+ var valueStripped = stripHtml(value);
30
+ var regex = /\b\w+\b/g;
31
+ return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];
32
+ }, jQuery.validator.format("Please enter between {0} and {1} words."));
33
+
34
+ }());
35
+
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");
39
+
40
+ jQuery.validator.addMethod("alphanumeric", function(value, element) {
41
+ return this.optional(element) || /^\w+$/i.test(value);
42
+ }, "Letters, numbers, and underscores only please");
43
+
44
+ jQuery.validator.addMethod("lettersonly", function(value, element) {
45
+ return this.optional(element) || /^[a-z]+$/i.test(value);
46
+ }, "Letters only please");
47
+
48
+ jQuery.validator.addMethod("nowhitespace", function(value, element) {
49
+ return this.optional(element) || /^\S+$/i.test(value);
50
+ }, "No white space please");
51
+
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
+
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");
59
+
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");
63
+
64
+ /**
65
+ * Return true, if the value is a valid vehicle identification number (VIN).
66
+ *
67
+ * Works with all kind of text inputs.
68
+ *
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.
71
+ *
72
+ * @name jQuery.validator.methods.vinUS
73
+ * @type Boolean
74
+ * @cat Plugins/Validate/Methods
75
+ */
76
+ jQuery.validator.addMethod("vinUS", function(v) {
77
+ if (v.length !== 17) {
78
+ return false;
79
+ }
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;
106
+ }
107
+ cd = rs % 11;
108
+ if (cd === 10) {
109
+ cd = "X";
110
+ }
111
+ if (cd === cdv) {
112
+ return true;
113
+ }
114
+ return false;
115
+ }, "The specified vehicle identification number (VIN) is invalid.");
116
+
117
+ /**
118
+ * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
119
+ *
120
+ * @example jQuery.validator.methods.date("01/01/1900")
121
+ * @result true
122
+ *
123
+ * @example jQuery.validator.methods.date("01/13/1990")
124
+ * @result false
125
+ *
126
+ * @example jQuery.validator.methods.date("01.01.1900")
127
+ * @result false
128
+ *
129
+ * @example <input name="pippo" class="{dateITA:true}" />
130
+ * @desc Declares an optional input element whose value must be a valid date.
131
+ *
132
+ * @name jQuery.validator.methods.dateITA
133
+ * @type Boolean
134
+ * @cat Plugins/Validate/Methods
135
+ */
136
+ 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);
145
+ if ( ( xdata.getFullYear() === aaaa ) && ( xdata.getMonth() === mm - 1 ) && ( xdata.getDate() === gg ) ){
146
+ check = true;
147
+ } else {
148
+ check = false;
149
+ }
150
+ } else {
151
+ check = false;
152
+ }
153
+ return this.optional(element) || check;
154
+ }, "Please enter a correct date");
155
+
156
+ /**
157
+ * IBAN is the international bank account number.
158
+ * It has a country - specific format, that is checked here too
159
+ */
160
+ jQuery.validator.addMethod("iban", function(value, element) {
161
+ // some quick simple tests to prevent needless work
162
+ if (this.optional(element)) {
163
+ return true;
164
+ }
165
+ if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(value))) {
166
+ return false;
167
+ }
168
+
169
+ // 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}"
237
+ };
238
+ var bbanpattern = bbancountrypatterns[countrycode];
239
+ // As new countries will start using IBAN in the
240
+ // future, we only check if the countrycode is known.
241
+ // This prevents false negatives, while almost all
242
+ // false positives introduced by this, will be caught
243
+ // by the checksum validation below anyway.
244
+ // Strict checking should return FALSE for unknown
245
+ // countries.
246
+ if (typeof bbanpattern !== 'undefined') {
247
+ var ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
248
+ if (!(ibanregexp.test(iban))) {
249
+ return false; // invalid country specific format
250
+ }
251
+ }
252
+
253
+ // 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++) {
259
+ charAt = ibancheck.charAt(i);
260
+ if (charAt !== "0") {
261
+ leadingZeroes = false;
262
+ }
263
+ if (!leadingZeroes) {
264
+ ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(charAt);
265
+ }
266
+ }
267
+
268
+ // 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;
274
+ cRest = cOperator % 97;
275
+ }
276
+ return cRest === 1;
277
+ }, "Please specify a valid IBAN");
278
+
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");
282
+
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.");
289
+
290
+ jQuery.validator.addMethod("mobileNL", function(value, element) {
291
+ 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
+ }, "Please specify a valid mobile number");
293
+
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");
297
+
298
+ /*
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
303
+ */
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))) {
309
+ return false;
310
+ }
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
+
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");
329
+
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");
335
+
336
+
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");
343
+
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
359
+ */
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"));
401
+
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);
411
+
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)) {
417
+ return false;
418
+ }
419
+
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;
456
+ }
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;
477
+ }
478
+ return false;
479
+ }, "Please enter a valid credit card number.");
480
+
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.");
484
+
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.");
488
+
489
+ /**
490
+ * Return true if the field value matches the given format RegExp
491
+ *
492
+ * @example jQuery.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
493
+ * @result true
494
+ *
495
+ * @example jQuery.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
496
+ * @result false
497
+ *
498
+ * @name jQuery.validator.methods.pattern
499
+ * @type Boolean
500
+ * @cat Plugins/Validate/Methods
501
+ */
502
+ jQuery.validator.addMethod("pattern", function(value, element, param) {
503
+ if (this.optional(element)) {
504
+ return true;
505
+ }
506
+ if (typeof param === 'string') {
507
+ param = new RegExp('^(?:' + param + ')$');
508
+ }
509
+ return param.test(value);
510
+ }, "Invalid format.");
511
+
512
+
513
+ /*
514
+ * Lets you say "at least X inputs that match selector Y must be filled."
515
+ *
516
+ * The end result is that neither of these inputs:
517
+ *
518
+ * <input class="productinfo" name="partnumber">
519
+ * <input class="productinfo" name="description">
520
+ *
521
+ * ...will validate unless at least one of them is filled.
522
+ *
523
+ * partnumber: {require_from_group: [1,".productinfo"]},
524
+ * description: {require_from_group: [1,".productinfo"]}
525
+ *
526
+ */
527
+ 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."));
542
+
543
+ /*
544
+ * Lets you say "either at least X inputs that match selector Y must be filled,
545
+ * OR they must all be skipped (left blank)."
546
+ *
547
+ * The end result, is that none of these inputs:
548
+ *
549
+ * <input class="productinfo" name="partnumber">
550
+ * <input class="productinfo" name="description">
551
+ * <input class="productinfo" name="color">
552
+ *
553
+ * ...will validate unless either at least two of them are filled,
554
+ * OR none of them are.
555
+ *
556
+ * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
557
+ * description: {skip_or_fill_minimum: [2,".productinfo"]},
558
+ * color: {skip_or_fill_minimum: [2,".productinfo"]}
559
+ *
560
+ */
561
+ 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."));
578
+
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;
585
+
586
+ // Element is optional
587
+ if (optionalValue) {
588
+ return optionalValue;
589
+ }
590
+
591
+ if ($(element).attr("type") === "file") {
592
+ // If we are using a wildcard, make it regex friendly
593
+ typeParam = typeParam.replace(/\*/g, ".*");
594
+
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];
599
+
600
+ // Grab the mimetype from the loaded file, verify it matches
601
+ if (!file.type.match(new RegExp( ".?(" + typeParam + ")$", "i"))) {
602
+ return false;
603
+ }
604
+ }
605
+ }
606
+ }
607
+
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."));
612
+
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."));