client_side_validations 3.0.5 → 3.0.14

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Rails 3 Client Side Validations - v3.0.5
2
+ * Rails 3 Client Side Validations - v3.0.13
3
3
  * https://github.com/bcardarlela/client_side_validations
4
4
  *
5
5
  * Copyright (c) 2011 Brian Cardarella
@@ -7,77 +7,76 @@
7
7
  * http://www.opensource.org/licenses/mit-license.php
8
8
  */
9
9
 
10
- (function($) {
11
- $.fn.validate = function() {
12
- return this.filter('form[data-validate]').each(function() {
13
- var form = $(this);
14
- var settings = window[form.attr('id')];
10
+ (function ($) {
11
+ $.fn.validate = function () {
12
+ return this.filter('form[data-validate]').each(function () {
13
+ var form = $(this),
14
+ settings = window[form.attr('id')],
15
+ addError = function (element, message) {
16
+ clientSideValidations.formBuilders[settings.type].add(element, settings, message);
17
+ },
18
+ removeError = function (element) {
19
+ clientSideValidations.formBuilders[settings.type].remove(element, settings);
20
+ };
15
21
 
16
22
  // Set up the events for the form
17
23
  form
18
- .submit(function() { return form.isValid(settings.validators); })
19
- .bind('ajax:beforeSend', function() { return form.isValid(settings.validators); })
24
+ .submit(function () { return form.isValid(settings.validators); })
25
+ .bind('ajax:beforeSend', function () { return form.isValid(settings.validators); } )
20
26
  // Callbacks
21
- .bind('form:validate:after', function(eventData) { clientSideValidations.callbacks.form.after( form, eventData); })
22
- .bind('form:validate:before', function(eventData) { clientSideValidations.callbacks.form.before(form, eventData); })
23
- .bind('form:validate:fail', function(eventData) { clientSideValidations.callbacks.form.fail( form, eventData); })
24
- .bind('form:validate:pass', function(eventData) { clientSideValidations.callbacks.form.pass( form, eventData); })
27
+ .bind('form:validate:after', function (eventData) { clientSideValidations.callbacks.form.after( form, eventData); } )
28
+ .bind('form:validate:before', function (eventData) { clientSideValidations.callbacks.form.before(form, eventData); } )
29
+ .bind('form:validate:fail', function (eventData) { clientSideValidations.callbacks.form.fail( form, eventData); } )
30
+ .bind('form:validate:pass', function (eventData) { clientSideValidations.callbacks.form.pass( form, eventData); } )
25
31
 
26
32
  // Set up the events for each validatable form element
27
- .find('[data-validate]:input')
28
- .live('focusout', function() { $(this).isValid(settings.validators); })
29
- .live('change', function() { $(this).data('changed', true); })
33
+ .find('[data-validate]:input:not(:radio)')
34
+ .live('focusout', function () { $(this).isValid(settings.validators); })
35
+ .live('change', function () { $(this).data('changed', true); })
30
36
  // Callbacks
31
- .live('element:validate:after', function(eventData) { clientSideValidations.callbacks.element.after( $(this), eventData); })
32
- .live('element:validate:before', function(eventData) { clientSideValidations.callbacks.element.before($(this), eventData); })
33
- .live('element:validate:fail', function(eventData, message) {
37
+ .live('element:validate:after', function (eventData) { clientSideValidations.callbacks.element.after( $(this), eventData); })
38
+ .live('element:validate:before', function (eventData) { clientSideValidations.callbacks.element.before($(this), eventData); })
39
+ .live('element:validate:fail', function (eventData, message) {
34
40
  var element = $(this);
35
- clientSideValidations.callbacks.element.fail(element, message, function() {
41
+ clientSideValidations.callbacks.element.fail(element, message, function () {
36
42
  addError(element, message);
37
- }, eventData) })
38
- .live('element:validate:pass', function(eventData) {
43
+ }, eventData); })
44
+ .live('element:validate:pass', function (eventData) {
39
45
  var element = $(this);
40
- clientSideValidations.callbacks.element.pass(element, function() {
46
+ clientSideValidations.callbacks.element.pass(element, function () {
41
47
  removeError(element);
42
- }, eventData) })
48
+ }, eventData); })
43
49
  // Checkboxes - Live events don't support filter
44
50
  .end().find('[data-validate]:checkbox')
45
- .live('click', function() { $(this).isValid(settings.validators); })
51
+ .live('click', function () { $(this).isValid(settings.validators); })
46
52
  // Inputs for confirmations
47
- .end().find('[id*=_confirmation]').each(function() {
53
+ .end().find('[id*=_confirmation]').each(function () {
48
54
  var confirmationElement = $(this),
49
55
  element = form.find('#' + this.id.match(/(.+)_confirmation/)[1] + '[data-validate]:input');
50
56
 
51
57
  if (element[0]) {
52
58
  $('#' + confirmationElement.attr('id'))
53
- .live('focusout', function() {
59
+ .live('focusout', function () {
54
60
  element.data('changed', true).isValid(settings.validators);
55
61
  })
56
- .live('keyup', function() {
62
+ .live('keyup', function () {
57
63
  element.data('changed', true).isValid(settings.validators);
58
- })
64
+ });
59
65
  }
60
66
  });
61
67
 
62
- var addError = function(element, message) {
63
- clientSideValidations.formBuilders[settings.type].add(element, settings, message);
64
- }
65
-
66
- var removeError = function(element) {
67
- clientSideValidations.formBuilders[settings.type].remove(element, settings);
68
- }
69
68
  });
70
- }
69
+ };
71
70
 
72
- $.fn.isValid = function(validators) {
71
+ $.fn.isValid = function (validators) {
73
72
  if ($(this[0]).is('form')) {
74
73
  return validateForm($(this[0]), validators);
75
74
  } else {
76
75
  return validateElement($(this[0]), validators[this[0].name]);
77
76
  }
78
- }
77
+ };
79
78
 
80
- var validateForm = function(form, validators) {
79
+ var validateForm = function (form, validators) {
81
80
  var valid = true;
82
81
 
83
82
  form.trigger('form:validate:before').find('[data-validate]:input').each(function() {
@@ -92,48 +91,47 @@
92
91
 
93
92
  form.trigger('form:validate:after');
94
93
  return valid;
95
- }
96
-
97
- var validateElement = function(element, validators) {
98
- element.trigger('element:validate:before');
99
-
100
- if (element.data('changed') !== false) {
101
- var valid = true;
102
- element.data('changed', false);
103
-
104
- // Because 'length' is defined on the list of validators we cannot call jQuery.each on
105
- // the clientSideValidations.validators.all() object
106
- for (kind in clientSideValidations.validators.all()) {
107
- if (validators[kind] && (message = clientSideValidations.validators.all()[kind](element, validators[kind]))) {
108
- element.trigger('element:validate:fail', message).data('valid', false);
109
- valid = false;
110
- break;
94
+ },
95
+ validateElement = function (element, validators) {
96
+ element.trigger('element:validate:before');
97
+
98
+ if (element.data('changed') !== false) {
99
+ var valid = true;
100
+ element.data('changed', false);
101
+
102
+ // Because 'length' is defined on the list of validators we cannot call jQuery.each on
103
+ // the clientSideValidations.validators.all() object
104
+ for (kind in clientSideValidations.validators.all()) {
105
+ if (validators[kind] && (message = clientSideValidations.validators.all()[kind](element, validators[kind]))) {
106
+ element.trigger('element:validate:fail', message).data('valid', false);
107
+ valid = false;
108
+ break;
109
+ }
111
110
  }
112
- }
113
111
 
114
- if (valid) { element.data('valid', null); element.trigger('element:validate:pass'); }
115
- }
112
+ if (valid) { element.data('valid', null); element.trigger('element:validate:pass'); }
113
+ }
116
114
 
117
- element.trigger('element:validate:after');
118
- return element.data('valid') === false ? false : true;
119
- }
115
+ element.trigger('element:validate:after');
116
+ return element.data('valid') === false ? false : true;
117
+ };
120
118
 
121
119
  // Main hook
122
120
  // If new forms are dynamically introduced into the DOM the .validate() method
123
121
  // must be invoked on that form
124
- $(function() { $('form[data-validate]').validate(); })
122
+ $(function () { $('form[data-validate]').validate(); });
125
123
  })(jQuery);
126
124
 
127
125
  var clientSideValidations = {
128
126
  validators: {
129
- all: function() { return jQuery.extend({}, clientSideValidations.validators.local, clientSideValidations.validators.remote) },
127
+ all: function() { return jQuery.extend({}, clientSideValidations.validators.local, clientSideValidations.validators.remote); },
130
128
  local: {
131
- presence: function(element, options) {
129
+ presence: function (element, options) {
132
130
  if (/^\s*$/.test(element.val() || "")) {
133
131
  return options.message;
134
132
  }
135
133
  },
136
- acceptance: function(element, options) {
134
+ acceptance: function (element, options) {
137
135
  switch (element.attr('type')) {
138
136
  case 'checkbox':
139
137
  if (!element.attr('checked')) {
@@ -147,8 +145,8 @@ var clientSideValidations = {
147
145
  break;
148
146
  }
149
147
  },
150
- format: function(element, options) {
151
- if ((message = this.presence(element, options)) && options.allow_blank == true) {
148
+ format: function (element, options) {
149
+ if ((message = this.presence(element, options)) && options.allow_blank === true) {
152
150
  return;
153
151
  } else if (message) {
154
152
  return message;
@@ -160,7 +158,7 @@ var clientSideValidations = {
160
158
  }
161
159
  }
162
160
  },
163
- numericality: function(element, options) {
161
+ numericality: function (element, options) {
164
162
  if (!/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/.test(element.val())) {
165
163
  return options.messages.numericality;
166
164
  }
@@ -170,82 +168,83 @@ var clientSideValidations = {
170
168
  }
171
169
 
172
170
  var CHECKS = { greater_than: '>', greater_than_or_equal_to: '>=',
173
- equal_to: '==', less_than: '<', less_than_or_equal_to: '<=' }
171
+ equal_to: '==', less_than: '<', less_than_or_equal_to: '<=' };
174
172
 
175
- for (var check in CHECKS) {
176
- if (options[check] != undefined && !(new Function("return " + element.val() + CHECKS[check] + options[check])())) {
173
+ for (check in CHECKS) {
174
+ if (options[check] !== undefined && !(new Function("return " + element.val() + CHECKS[check] + options[check])())) {
177
175
  return options.messages[check];
178
176
  }
179
177
  }
180
178
 
181
- if (options.odd && !(parseInt(element.val()) % 2)) {
179
+ if (options.odd && !(parseInt(element.val(), 10) % 2)) {
182
180
  return options.messages.odd;
183
181
  }
184
182
 
185
- if (options.even && (parseInt(element.val()) % 2)) {
183
+ if (options.even && (parseInt(element.val(), 10) % 2)) {
186
184
  return options.messages.even;
187
185
  }
188
186
  },
189
- length: function(element, options) {
190
- var blankOptions = {};
187
+ length: function (element, options) {
188
+ var blankOptions = {},
189
+ CHECKS = { is: '==', minimum: '>=', maximum: '<=' },
190
+ tokenizer = options.js_tokenizer || "split('')",
191
+ tokenized_length = new Function("element", "return (element.val()." + tokenizer + " || '').length;")(element);
191
192
  if (options.is) {
192
193
  blankOptions.message = options.messages.is;
193
194
  } else if (options.minimum) {
194
195
  blankOptions.message = options.messages.minimum;
195
196
  }
196
- if ((message = this.presence(element, blankOptions)) && options.allow_blank == true) {
197
+ if ((message = this.presence(element, blankOptions)) && options.allow_blank === true) {
197
198
  return;
198
199
  } else if (message) {
199
200
  return message;
200
201
  } else {
201
- var CHECKS = { is: '==', minimum: '>=', maximum: '<=' }
202
- var tokenizer = options.js_tokenizer || "split('')";
203
- var tokenized_length = new Function("element", "return (element.val()." + tokenizer + " || '').length;")(element);
204
-
205
- for (var check in CHECKS) {
202
+ for (check in CHECKS) {
206
203
  if (options[check] && !(new Function("return " + tokenized_length + CHECKS[check] + options[check])())) {
207
204
  return options.messages[check];
208
205
  }
209
206
  }
210
207
  }
211
208
  },
212
- exclusion: function(element, options) {
213
- if ((message = this.presence(element, options)) && options.allow_blank == true) {
209
+ exclusion: function (element, options) {
210
+ var lower = null, upper = null;
211
+ if ((message = this.presence(element, options)) && options.allow_blank === true) {
214
212
  return;
215
213
  } else if (message) {
216
214
  return message;
217
215
  } else {
218
216
  if (options['in']) {
219
- for (var i = 0; i < options['in'].length; i++) {
217
+ for (i = 0; i < options['in'].length; i = i + 1) {
220
218
  if (options['in'][i] == element.val()) {
221
219
  return options.message;
222
220
  }
223
221
  }
224
- } else if (options['range']) {
225
- var lower = options['range'][0],
226
- upper = options['range'][1];
222
+ } else if (options.range) {
223
+ lower = options.range[0];
224
+ upper = options.range[1];
227
225
  if (element.val() >= lower && element.val() <= upper) {
228
226
  return options.message;
229
227
  }
230
228
  }
231
229
  }
232
230
  },
233
- inclusion: function(element, options) {
234
- if ((message = this.presence(element, options)) && options.allow_blank == true) {
231
+ inclusion: function (element, options) {
232
+ var lower = null, upper = null;
233
+ if ((message = this.presence(element, options)) && options.allow_blank === true) {
235
234
  return;
236
235
  } else if (message) {
237
236
  return message;
238
237
  } else {
239
238
  if (options['in']) {
240
- for (var i = 0; i < options['in'].length; i++) {
239
+ for (i = 0; i < options['in'].length; i = i + 1) {
241
240
  if (options['in'][i] == element.val()) {
242
241
  return;
243
242
  }
244
243
  }
245
244
  return options.message;
246
- } else if (options['range']) {
247
- var lower = options['range'][0],
248
- upper = options['range'][1];
245
+ } else if (options.range) {
246
+ lower = options.range[0];
247
+ upper = options.range[1];
249
248
 
250
249
  if (element.val() >= lower && element.val() <= upper) {
251
250
  return;
@@ -255,25 +254,26 @@ var clientSideValidations = {
255
254
  }
256
255
  }
257
256
  },
258
- confirmation: function(element, options) {
259
- if (element.val() != jQuery('#' + element.attr('id') + '_confirmation').val()) {
257
+ confirmation: function (element, options) {
258
+ if (element.val() !== jQuery('#' + element.attr('id') + '_confirmation').val()) {
260
259
  return options.message;
261
260
  }
262
261
  }
263
262
  },
264
263
  remote: {
265
- uniqueness: function(element, options) {
266
- var data = {};
267
- data['case_sensitive'] = !!options.case_sensitive;
264
+ uniqueness: function (element, options) {
265
+ var data = {},
266
+ name = null;
267
+ data.case_sensitive = !!options.case_sensitive;
268
268
  if (options.id) {
269
- data['id'] = options.id;
269
+ data.id = options.id;
270
270
  }
271
271
 
272
272
  if (options.scope) {
273
- data.scope = {}
273
+ data.scope = {};
274
274
  for (key in options.scope) {
275
- var scoped_element = jQuery('[name="' + element.attr('name').replace(/\[\w+]$/, '[' + key + ']' + '"]'));
276
- if (scoped_element[0] && scoped_element.val() != options.scope[key]) {
275
+ var scoped_element = jQuery('[name="' + element.attr('name').replace(/\[\w+\]$/, '[' + key + ']' + '"]'));
276
+ if (scoped_element[0] && scoped_element.val() !== options.scope[key]) {
277
277
  data.scope[key] = scoped_element.val();
278
278
  scoped_element.unbind('change.' + element.id).bind('change.' + element.id, function() { element.trigger('change'); element.trigger('focusout'); });
279
279
  } else {
@@ -286,16 +286,16 @@ var clientSideValidations = {
286
286
  // e.g. user[records_attributes][0][title] => records[title]
287
287
  // e.g. user[record_attributes][title] => record[title]
288
288
  // Server side handles classifying the resource properly
289
- if (/_attributes]/.test(element.attr('name'))) {
290
- var name = element.attr('name').match(/\[\w+_attributes]/g).pop().match(/\[(\w+)_attributes]/).pop();
291
- name += /(\[\w+])$/.exec(element.attr('name'))[1];
289
+ if (/_attributes\]/.test(element.attr('name'))) {
290
+ name = element.attr('name').match(/\[\w+_attributes\]/g).pop().match(/\[(\w+)_attributes\]/).pop();
291
+ name += /(\[\w+\])$/.exec(element.attr('name'))[1];
292
292
  } else {
293
- var name = element.attr('name');
293
+ name = element.attr('name');
294
294
  }
295
295
 
296
296
  // Override the name if a nested module class is passed
297
297
  if (options['class']) {
298
- name = options['class'] + '[' + name.split('[')[1]
298
+ name = options['class'] + '[' + name.split('[')[1];
299
299
  }
300
300
  data[name] = element.val();
301
301
 
@@ -303,7 +303,7 @@ var clientSideValidations = {
303
303
  url: '/validators/uniqueness.json',
304
304
  data: data,
305
305
  async: false
306
- }).status == 200) {
306
+ }).status === 200) {
307
307
  return options.message;
308
308
  }
309
309
  }
@@ -311,13 +311,13 @@ var clientSideValidations = {
311
311
  },
312
312
  formBuilders: {
313
313
  'ActionView::Helpers::FormBuilder': {
314
- add: function(element, settings, message) {
315
- if (element.data('valid') !== false) {
314
+ add: function (element, settings, message) {
315
+ if (element.data('valid') !== false && jQuery('label.message[for="' + element.attr('id') + '"]')[0] === undefined) {
316
316
  var inputErrorField = jQuery(settings.input_tag),
317
317
  labelErrorField = jQuery(settings.label_tag),
318
318
  label = jQuery('label[for="' + element.attr('id') + '"]:not(.message)');
319
319
 
320
- if (element.attr('autofocus')) { element.attr('autofocus', false) };
320
+ if (element.attr('autofocus')) { element.attr('autofocus', false); }
321
321
  element.before(inputErrorField);
322
322
  inputErrorField.find('span#input_tag').replaceWith(element);
323
323
  inputErrorField.find('label.message').attr('for', element.attr('id'));
@@ -327,7 +327,7 @@ var clientSideValidations = {
327
327
  }
328
328
  jQuery('label.message[for="' + element.attr('id') + '"]').text(message);
329
329
  },
330
- remove: function(element, settings) {
330
+ remove: function (element, settings) {
331
331
  var errorFieldClass = jQuery(settings.input_tag).attr('class'),
332
332
  inputErrorField = element.closest('.' + errorFieldClass),
333
333
  label = jQuery('label[for="' + element.attr('id') + '"]:not(.message)'),
@@ -342,63 +342,64 @@ var clientSideValidations = {
342
342
  }
343
343
  },
344
344
  'SimpleForm::FormBuilder': {
345
- add: function(element, settings, message) {
345
+ add: function (element, settings, message) {
346
346
  if (element.data('valid') !== false) {
347
- var wrapper = element.closest(settings.wrapper_tag);
347
+ var wrapper = element.closest(settings.wrapper_tag),
348
+ errorElement = $('<' + settings.error_tag + ' class="' + settings.error_class + '">' + message + '</' + settings.error_tag + '>');
348
349
  wrapper.addClass(settings.wrapper_error_class);
349
- var errorElement = $('<' + settings.error_tag + ' class="' + settings.error_class + '">' + message + '</' + settings.error_tag + '>');
350
350
  wrapper.append(errorElement);
351
351
  } else {
352
352
  element.parent().find(settings.error_tag + '.' + settings.error_class).text(message);
353
353
  }
354
354
  },
355
- remove: function(element, settings) {
356
- var wrapper = element.closest(settings.wrapper_tag + '.' + settings.wrapper_error_class);
355
+ remove: function (element, settings) {
356
+ var wrapper = element.closest(settings.wrapper_tag + '.' + settings.wrapper_error_class),
357
+ errorElement = wrapper.find(settings.error_tag + '.' + settings.error_class);
357
358
  wrapper.removeClass(settings.wrapper_error_class);
358
- var errorElement = wrapper.find(settings.error_tag + '.' + settings.error_class);
359
359
  errorElement.remove();
360
360
  }
361
361
 
362
362
  },
363
363
  'Formtastic::SemanticFormBuilder': {
364
- add: function(element, settings, message) {
364
+ add: function (element, settings, message) {
365
365
  if (element.data('valid') !== false) {
366
- var wrapper = element.closest('li');
366
+ var wrapper = element.closest('li'),
367
+ errorElement = jQuery('<p class="' + settings.inline_error_class + '">' + message + '</p>');
367
368
  wrapper.addClass('error');
368
- var errorElement = $('<p class="' + settings.inline_error_class + '">' + message + '</p>');
369
369
  wrapper.append(errorElement);
370
370
  } else {
371
371
  element.parent().find('p.' + settings.inline_error_class).text(message);
372
372
  }
373
373
  },
374
- remove: function(element, settings) {
375
- var wrapper = element.closest('li.error');
374
+ remove: function (element, settings) {
375
+ var wrapper = element.closest('li.error'),
376
+ errorElement = wrapper.find('p.' + settings.inline_error_class);
376
377
  wrapper.removeClass('error');
377
- var errorElement = wrapper.find('p.' + settings.inline_error_class);
378
378
  errorElement.remove();
379
379
  }
380
380
  },
381
381
  'NestedForm::Builder': {
382
- add: function(element, settings, message) {
382
+ add: function (element, settings, message) {
383
383
  clientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'].add(element, settings, message);
384
384
  },
385
- remove: function(element, settings, message) {
385
+ remove: function (element, settings, message) {
386
386
  clientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'].remove(element, settings, message);
387
387
  }
388
388
  }
389
389
  },
390
390
  callbacks: {
391
391
  element: {
392
- after: function(element, eventData) { },
393
- before: function(element, eventData) { },
394
- fail: function(element, message, addError, eventData) { addError() },
395
- pass: function(element, removeError, eventData) { removeError() }
392
+ after: function (element, eventData) { },
393
+ before: function (element, eventData) { },
394
+ fail: function (element, message, addError, eventData) { addError(); },
395
+ pass: function (element, removeError, eventData) { removeError(); }
396
396
  },
397
397
  form: {
398
- after: function(form, eventData) { },
399
- before: function(form, eventData) { },
400
- fail: function(form, eventData) { },
401
- pass: function(form, eventData) { }
398
+ after: function (form, eventData) { },
399
+ before: function (form, eventData) { },
400
+ fail: function (form, eventData) { },
401
+ pass: function (form, eventData) { }
402
402
  }
403
403
  }
404
- }
404
+ };
405
+