client_side_validations 3.2.5 → 4.2.12

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +558 -0
  3. data/lib/client_side_validations/action_view/form_builder.rb +102 -84
  4. data/lib/client_side_validations/action_view/form_helper.rb +106 -111
  5. data/lib/client_side_validations/action_view/form_tag_helper.rb +13 -9
  6. data/lib/client_side_validations/action_view.rb +4 -3
  7. data/lib/client_side_validations/active_model/absence.rb +11 -0
  8. data/lib/client_side_validations/active_model/acceptance.rb +7 -6
  9. data/lib/client_side_validations/active_model/conditionals.rb +41 -0
  10. data/lib/client_side_validations/active_model/exclusion.rb +4 -24
  11. data/lib/client_side_validations/active_model/format.rb +14 -19
  12. data/lib/client_side_validations/active_model/inclusion.rb +4 -23
  13. data/lib/client_side_validations/active_model/length.rb +15 -15
  14. data/lib/client_side_validations/active_model/numericality.rb +25 -27
  15. data/lib/client_side_validations/active_model/presence.rb +7 -6
  16. data/lib/client_side_validations/active_model.rb +90 -82
  17. data/lib/client_side_validations/active_record/middleware.rb +48 -42
  18. data/lib/client_side_validations/active_record/uniqueness.rb +25 -21
  19. data/lib/client_side_validations/active_record.rb +5 -6
  20. data/lib/client_side_validations/config.rb +1 -1
  21. data/lib/client_side_validations/core_ext/range.rb +1 -2
  22. data/lib/client_side_validations/core_ext/regexp.rb +6 -4
  23. data/lib/client_side_validations/engine.rb +0 -1
  24. data/lib/client_side_validations/generators/rails_validations.rb +2 -3
  25. data/lib/client_side_validations/generators.rb +6 -3
  26. data/lib/client_side_validations/middleware.rb +37 -28
  27. data/lib/client_side_validations/version.rb +2 -1
  28. data/lib/client_side_validations.rb +0 -1
  29. data/lib/generators/client_side_validations/copy_assets_generator.rb +21 -25
  30. data/lib/generators/client_side_validations/install_generator.rb +0 -4
  31. data/lib/generators/templates/client_side_validations/initializer.rb +5 -2
  32. data/vendor/assets/javascripts/rails.validations.js +120 -100
  33. metadata +175 -62
  34. data/client_side_validations.gemspec +0 -32
@@ -1,6 +1,13 @@
1
+
2
+ /*!
3
+ * Client Side Validations - v4.2.12 (https://github.com/DavyJonesLocker/client_side_validations)
4
+ * Copyright (c) 2017 Geremia Taglialatela, Brian Cardarella
5
+ * Licensed under MIT (http://opensource.org/licenses/mit-license.php)
6
+ */
7
+
1
8
  (function() {
2
9
  var $, validateElement, validateForm, validatorsFor,
3
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
10
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
4
11
 
5
12
  $ = jQuery;
6
13
 
@@ -44,7 +51,15 @@
44
51
  };
45
52
 
46
53
  validatorsFor = function(name, validators) {
47
- name = name.replace(/_attributes\]\[\w+\]\[(\w+)\]/g, "_attributes][][$1]");
54
+ var captures, validator, validator_name;
55
+ if (captures = name.match(/\[(\w+_attributes)\].*\[(\w+)\]$/)) {
56
+ for (validator_name in validators) {
57
+ validator = validators[validator_name];
58
+ if (validator_name.match("\\[" + captures[1] + "\\].*\\[\\]\\[" + captures[2] + "\\]$")) {
59
+ name = name.replace(/\[[\da-z_]+\]\[(\w+)\]$/g, '[][$1]');
60
+ }
61
+ }
62
+ }
48
63
  return validators[name] || {};
49
64
  };
50
65
 
@@ -81,14 +96,14 @@
81
96
  return element.trigger('element:validate:after.ClientSideValidations').data('valid') !== false;
82
97
  };
83
98
  executeValidators = function(context) {
84
- var fn, kind, message, valid, validator, _i, _len, _ref;
99
+ var fn, i, kind, len, message, ref, valid, validator;
85
100
  valid = true;
86
101
  for (kind in context) {
87
102
  fn = context[kind];
88
103
  if (validators[kind]) {
89
- _ref = validators[kind];
90
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
91
- validator = _ref[_i];
104
+ ref = validators[kind];
105
+ for (i = 0, len = ref.length; i < len; i++) {
106
+ validator = ref[i];
92
107
  if (message = fn.call(context, element, validator)) {
93
108
  valid = failElement(message);
94
109
  break;
@@ -101,10 +116,12 @@
101
116
  }
102
117
  return valid;
103
118
  };
104
- destroyInputName = element.attr('name').replace(/\[([^\]]*?)\]$/, '[_destroy]');
105
- if ($("input[name='" + destroyInputName + "']").val() === "1") {
106
- passElement();
107
- return afterValidate();
119
+ if (element.attr('name').search(/\[([^\]]*?)\]$/) >= 0) {
120
+ destroyInputName = element.attr('name').replace(/\[([^\]]*?)\]$/, '[_destroy]');
121
+ if ($("input[name='" + destroyInputName + "']").val() === '1') {
122
+ passElement();
123
+ return afterValidate();
124
+ }
108
125
  }
109
126
  if (element.data('changed') === false) {
110
127
  return afterValidate();
@@ -159,7 +176,7 @@
159
176
 
160
177
  window.ClientSideValidations.enablers = {
161
178
  form: function(form) {
162
- var $form, binding, event, _ref;
179
+ var $form, binding, event, ref;
163
180
  $form = $(form);
164
181
  form.ClientSideValidations = {
165
182
  settings: window.ClientSideValidations.forms[$form.attr('id')],
@@ -170,33 +187,33 @@
170
187
  return ClientSideValidations.formBuilders[form.ClientSideValidations.settings.type].remove(element, form.ClientSideValidations.settings);
171
188
  }
172
189
  };
173
- _ref = {
190
+ ref = {
174
191
  'submit.ClientSideValidations': function(eventData) {
175
192
  if (!$form.isValid(form.ClientSideValidations.settings.validators)) {
176
193
  eventData.preventDefault();
177
- return eventData.stopImmediatePropagation();
194
+ eventData.stopImmediatePropagation();
178
195
  }
179
196
  },
180
197
  'ajax:beforeSend.ClientSideValidations': function(eventData) {
181
198
  if (eventData.target === this) {
182
- return $form.isValid(form.ClientSideValidations.settings.validators);
199
+ $form.isValid(form.ClientSideValidations.settings.validators);
183
200
  }
184
201
  },
185
202
  'form:validate:after.ClientSideValidations': function(eventData) {
186
- return ClientSideValidations.callbacks.form.after($form, eventData);
203
+ ClientSideValidations.callbacks.form.after($form, eventData);
187
204
  },
188
205
  'form:validate:before.ClientSideValidations': function(eventData) {
189
- return ClientSideValidations.callbacks.form.before($form, eventData);
206
+ ClientSideValidations.callbacks.form.before($form, eventData);
190
207
  },
191
208
  'form:validate:fail.ClientSideValidations': function(eventData) {
192
- return ClientSideValidations.callbacks.form.fail($form, eventData);
209
+ ClientSideValidations.callbacks.form.fail($form, eventData);
193
210
  },
194
211
  'form:validate:pass.ClientSideValidations': function(eventData) {
195
- return ClientSideValidations.callbacks.form.pass($form, eventData);
212
+ ClientSideValidations.callbacks.form.pass($form, eventData);
196
213
  }
197
214
  };
198
- for (event in _ref) {
199
- binding = _ref[event];
215
+ for (event in ref) {
216
+ binding = ref[event];
200
217
  $form.on(event, binding);
201
218
  }
202
219
  return $form.find(ClientSideValidations.selectors.inputs).each(function() {
@@ -204,67 +221,66 @@
204
221
  });
205
222
  },
206
223
  input: function(input) {
207
- var $form, $input, binding, event, form, _ref;
224
+ var $form, $input, binding, event, form, ref;
208
225
  $input = $(input);
209
226
  form = input.form;
210
227
  $form = $(form);
211
- _ref = {
228
+ ref = {
212
229
  'focusout.ClientSideValidations': function() {
213
- return $(this).isValid(form.ClientSideValidations.settings.validators);
230
+ $(this).isValid(form.ClientSideValidations.settings.validators);
214
231
  },
215
232
  'change.ClientSideValidations': function() {
216
- return $(this).data('changed', true);
233
+ $(this).data('changed', true);
217
234
  },
218
235
  'element:validate:after.ClientSideValidations': function(eventData) {
219
- return ClientSideValidations.callbacks.element.after($(this), eventData);
236
+ ClientSideValidations.callbacks.element.after($(this), eventData);
220
237
  },
221
238
  'element:validate:before.ClientSideValidations': function(eventData) {
222
- return ClientSideValidations.callbacks.element.before($(this), eventData);
239
+ ClientSideValidations.callbacks.element.before($(this), eventData);
223
240
  },
224
241
  'element:validate:fail.ClientSideValidations': function(eventData, message) {
225
242
  var element;
226
243
  element = $(this);
227
- return ClientSideValidations.callbacks.element.fail(element, message, function() {
244
+ ClientSideValidations.callbacks.element.fail(element, message, function() {
228
245
  return form.ClientSideValidations.addError(element, message);
229
246
  }, eventData);
230
247
  },
231
248
  'element:validate:pass.ClientSideValidations': function(eventData) {
232
249
  var element;
233
250
  element = $(this);
234
- return ClientSideValidations.callbacks.element.pass(element, function() {
251
+ ClientSideValidations.callbacks.element.pass(element, function() {
235
252
  return form.ClientSideValidations.removeError(element);
236
253
  }, eventData);
237
254
  }
238
255
  };
239
- for (event in _ref) {
240
- binding = _ref[event];
256
+ for (event in ref) {
257
+ binding = ref[event];
241
258
  $input.filter(':not(:radio):not([id$=_confirmation])').each(function() {
242
259
  return $(this).attr('data-validate', true);
243
260
  }).on(event, binding);
244
261
  }
245
- $input.filter(':checkbox').on('click.ClientSideValidations', function() {
262
+ $input.filter(':checkbox').on('change.ClientSideValidations', function() {
246
263
  $(this).isValid(form.ClientSideValidations.settings.validators);
247
- return true;
248
264
  });
249
265
  return $input.filter('[id$=_confirmation]').each(function() {
250
- var confirmationElement, element, _ref1, _results;
266
+ var confirmationElement, element, ref1, results;
251
267
  confirmationElement = $(this);
252
268
  element = $form.find("#" + (this.id.match(/(.+)_confirmation/)[1]) + ":input");
253
269
  if (element[0]) {
254
- _ref1 = {
270
+ ref1 = {
255
271
  'focusout.ClientSideValidations': function() {
256
- return element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
272
+ element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
257
273
  },
258
274
  'keyup.ClientSideValidations': function() {
259
- return element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
275
+ element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
260
276
  }
261
277
  };
262
- _results = [];
263
- for (event in _ref1) {
264
- binding = _ref1[event];
265
- _results.push($("#" + (confirmationElement.attr('id'))).on(event, binding));
278
+ results = [];
279
+ for (event in ref1) {
280
+ binding = ref1[event];
281
+ results.push($("#" + (confirmationElement.attr('id'))).on(event, binding));
266
282
  }
267
- return _results;
283
+ return results;
268
284
  }
269
285
  });
270
286
  }
@@ -272,16 +288,21 @@
272
288
 
273
289
  window.ClientSideValidations.validators = {
274
290
  all: function() {
275
- return jQuery.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote);
291
+ return $.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote);
276
292
  },
277
293
  local: {
294
+ absence: function(element, options) {
295
+ if (!/^\s*$/.test(element.val() || '')) {
296
+ return options.message;
297
+ }
298
+ },
278
299
  presence: function(element, options) {
279
300
  if (/^\s*$/.test(element.val() || '')) {
280
301
  return options.message;
281
302
  }
282
303
  },
283
304
  acceptance: function(element, options) {
284
- var _ref;
305
+ var ref;
285
306
  switch (element.attr('type')) {
286
307
  case 'checkbox':
287
308
  if (!element.prop('checked')) {
@@ -289,7 +310,7 @@
289
310
  }
290
311
  break;
291
312
  case 'text':
292
- if (element.val() !== (((_ref = options.accept) != null ? _ref.toString() : void 0) || '1')) {
313
+ if (element.val() !== (((ref = options.accept) != null ? ref.toString() : void 0) || '1')) {
293
314
  return options.message;
294
315
  }
295
316
  }
@@ -303,16 +324,16 @@
303
324
  }
304
325
  return message;
305
326
  }
306
- if (options["with"] && !options["with"].test(element.val())) {
327
+ if (options["with"] && !new RegExp(options["with"].source, options["with"].options).test(element.val())) {
307
328
  return options.message;
308
329
  }
309
- if (options.without && options.without.test(element.val())) {
330
+ if (options.without && new RegExp(options.without.source, options.without.options).test(element.val())) {
310
331
  return options.message;
311
332
  }
312
333
  },
313
334
  numericality: function(element, options) {
314
- var CHECKS, check, check_value, fn, form, operator, val;
315
- val = jQuery.trim(element.val());
335
+ var CHECKS, check, checkValue, fn, form, operator, val;
336
+ val = $.trim(element.val());
316
337
  if (!ClientSideValidations.patterns.numericality.test(val)) {
317
338
  if (options.allow_blank === true && this.presence(element, {
318
339
  message: options.messages.numericality
@@ -321,7 +342,7 @@
321
342
  }
322
343
  return options.messages.numericality;
323
344
  }
324
- val = val.replace(new RegExp("\\" + ClientSideValidations.number_format.delimiter, 'g'), "").replace(new RegExp("\\" + ClientSideValidations.number_format.separator, 'g'), ".");
345
+ val = val.replace(new RegExp("\\" + ClientSideValidations.number_format.delimiter, 'g'), '').replace(new RegExp("\\" + ClientSideValidations.number_format.separator, 'g'), '.');
325
346
  if (options.only_integer && !/^[+-]?\d+$/.test(val)) {
326
347
  return options.messages.only_integer;
327
348
  }
@@ -338,14 +359,11 @@
338
359
  if (!(options[check] != null)) {
339
360
  continue;
340
361
  }
341
- if (!isNaN(parseFloat(options[check])) && isFinite(options[check])) {
342
- check_value = options[check];
343
- } else if (form.find("[name*=" + options[check] + "]").size() === 1) {
344
- check_value = form.find("[name*=" + options[check] + "]").val();
345
- } else {
362
+ checkValue = !isNaN(parseFloat(options[check])) && isFinite(options[check]) ? options[check] : form.find("[name*=" + options[check] + "]").length === 1 ? form.find("[name*=" + options[check] + "]").val() : void 0;
363
+ if ((checkValue == null) || checkValue === '') {
346
364
  return;
347
365
  }
348
- fn = new Function("return " + val + " " + operator + " " + check_value);
366
+ fn = new Function("return " + val + " " + operator + " " + checkValue);
349
367
  if (!fn()) {
350
368
  return options.messages[check];
351
369
  }
@@ -387,7 +405,7 @@
387
405
  }
388
406
  },
389
407
  exclusion: function(element, options) {
390
- var lower, message, option, upper, _ref;
408
+ var lower, message, option, ref, upper;
391
409
  message = this.presence(element, options);
392
410
  if (message) {
393
411
  if (options.allow_blank === true) {
@@ -396,16 +414,16 @@
396
414
  return message;
397
415
  }
398
416
  if (options["in"]) {
399
- if (_ref = element.val(), __indexOf.call((function() {
400
- var _i, _len, _ref1, _results;
401
- _ref1 = options["in"];
402
- _results = [];
403
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
404
- option = _ref1[_i];
405
- _results.push(option.toString());
417
+ if (ref = element.val(), indexOf.call((function() {
418
+ var i, len, ref1, results;
419
+ ref1 = options["in"];
420
+ results = [];
421
+ for (i = 0, len = ref1.length; i < len; i++) {
422
+ option = ref1[i];
423
+ results.push(option.toString());
406
424
  }
407
- return _results;
408
- })(), _ref) >= 0) {
425
+ return results;
426
+ })(), ref) >= 0) {
409
427
  return options.message;
410
428
  }
411
429
  }
@@ -418,7 +436,7 @@
418
436
  }
419
437
  },
420
438
  inclusion: function(element, options) {
421
- var lower, message, option, upper, _ref;
439
+ var lower, message, option, ref, upper;
422
440
  message = this.presence(element, options);
423
441
  if (message) {
424
442
  if (options.allow_blank === true) {
@@ -427,16 +445,16 @@
427
445
  return message;
428
446
  }
429
447
  if (options["in"]) {
430
- if (_ref = element.val(), __indexOf.call((function() {
431
- var _i, _len, _ref1, _results;
432
- _ref1 = options["in"];
433
- _results = [];
434
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
435
- option = _ref1[_i];
436
- _results.push(option.toString());
448
+ if (ref = element.val(), indexOf.call((function() {
449
+ var i, len, ref1, results;
450
+ ref1 = options["in"];
451
+ results = [];
452
+ for (i = 0, len = ref1.length; i < len; i++) {
453
+ option = ref1[i];
454
+ results.push(option.toString());
437
455
  }
438
- return _results;
439
- })(), _ref) >= 0) {
456
+ return results;
457
+ })(), ref) >= 0) {
440
458
  return;
441
459
  }
442
460
  return options.message;
@@ -451,7 +469,7 @@
451
469
  }
452
470
  },
453
471
  confirmation: function(element, options) {
454
- if (element.val() !== jQuery("#" + (element.attr('id')) + "_confirmation").val()) {
472
+ if (element.val() !== $("#" + (element.attr('id')) + "_confirmation").val()) {
455
473
  return options.message;
456
474
  }
457
475
  },
@@ -466,7 +484,7 @@
466
484
  if (name_prefix && name_suffix) {
467
485
  form = element.closest('form');
468
486
  valid = true;
469
- form.find(':input[name^="' + name_prefix + '"][name$="' + name_suffix + '"]').each(function() {
487
+ form.find(":input[name^=\"" + name_prefix + "\"][name$=\"" + name_suffix + "\"]").each(function() {
470
488
  if ($(this).attr('name') !== name) {
471
489
  if ($(this).val() === value) {
472
490
  valid = false;
@@ -487,7 +505,7 @@
487
505
  },
488
506
  remote: {
489
507
  uniqueness: function(element, options) {
490
- var data, key, message, name, scope_value, scoped_element, scoped_name, _ref;
508
+ var data, key, message, name, ref, scope_value, scoped_element, scoped_name;
491
509
  message = ClientSideValidations.validators.local.presence(element, options);
492
510
  if (message) {
493
511
  if (options.allow_blank === true) {
@@ -502,12 +520,12 @@
502
520
  }
503
521
  if (options.scope) {
504
522
  data.scope = {};
505
- _ref = options.scope;
506
- for (key in _ref) {
507
- scope_value = _ref[key];
523
+ ref = options.scope;
524
+ for (key in ref) {
525
+ scope_value = ref[key];
508
526
  scoped_name = element.attr('name').replace(/\[\w+\]$/, "[" + key + "]");
509
- scoped_element = jQuery("[name='" + scoped_name + "']");
510
- jQuery("[name='" + scoped_name + "']:checkbox").each(function() {
527
+ scoped_element = $("[name='" + scoped_name + "']");
528
+ $("[name='" + scoped_name + "']:checkbox").each(function() {
511
529
  if (this.checked) {
512
530
  return scoped_element = this;
513
531
  }
@@ -530,10 +548,10 @@
530
548
  name = element.attr('name');
531
549
  }
532
550
  if (options['class']) {
533
- name = options['class'] + '[' + name.split('[')[1];
551
+ name = options['class'] + "[" + (name.split('[')[1]);
534
552
  }
535
553
  data[name] = element.val();
536
- if (jQuery.ajax({
554
+ if ($.ajax({
537
555
  url: ClientSideValidations.remote_validators_url_for('uniqueness'),
538
556
  data: data,
539
557
  async: false,
@@ -554,21 +572,21 @@
554
572
  };
555
573
 
556
574
  window.ClientSideValidations.disableValidators = function() {
557
- var func, validator, _ref, _results;
575
+ var func, ref, results, validator;
558
576
  if (window.ClientSideValidations.disabled_validators === void 0) {
559
577
  return;
560
578
  }
561
- _ref = window.ClientSideValidations.validators.remote;
562
- _results = [];
563
- for (validator in _ref) {
564
- func = _ref[validator];
565
- if (window.ClientSideValidations.disabled_validators.indexOf(validator) !== -1) {
566
- _results.push(delete window.ClientSideValidations.validators.remote[validator]);
579
+ ref = window.ClientSideValidations.validators.remote;
580
+ results = [];
581
+ for (validator in ref) {
582
+ func = ref[validator];
583
+ if (indexOf.call(window.ClientSideValidations.disabled_validators, validator) >= 0) {
584
+ results.push(delete window.ClientSideValidations.validators.remote[validator]);
567
585
  } else {
568
- _results.push(void 0);
586
+ results.push(void 0);
569
587
  }
570
588
  }
571
- return _results;
589
+ return results;
572
590
  };
573
591
 
574
592
  window.ClientSideValidations.formBuilders = {
@@ -576,9 +594,9 @@
576
594
  add: function(element, settings, message) {
577
595
  var form, inputErrorField, label, labelErrorField;
578
596
  form = $(element[0].form);
579
- if (element.data('valid') !== false && !(form.find("label.message[for='" + (element.attr('id')) + "']")[0] != null)) {
580
- inputErrorField = jQuery(settings.input_tag);
581
- labelErrorField = jQuery(settings.label_tag);
597
+ if (element.data('valid') !== false && (form.find("label.message[for='" + (element.attr('id')) + "']")[0] == null)) {
598
+ inputErrorField = $(settings.input_tag);
599
+ labelErrorField = $(settings.label_tag);
582
600
  label = form.find("label[for='" + (element.attr('id')) + "']:not(.message)");
583
601
  if (element.attr('autofocus')) {
584
602
  element.attr('autofocus', false);
@@ -595,8 +613,8 @@
595
613
  remove: function(element, settings) {
596
614
  var errorFieldClass, form, inputErrorField, label, labelErrorField;
597
615
  form = $(element[0].form);
598
- errorFieldClass = jQuery(settings.input_tag).attr('class');
599
- inputErrorField = element.closest("." + (errorFieldClass.replace(" ", ".")));
616
+ errorFieldClass = $(settings.input_tag).attr('class');
617
+ inputErrorField = element.closest("." + (errorFieldClass.replace(/\ /g, ".")));
600
618
  label = form.find("label[for='" + (element.attr('id')) + "']:not(.message)");
601
619
  labelErrorField = label.closest("." + errorFieldClass);
602
620
  if (inputErrorField[0]) {
@@ -632,7 +650,9 @@
632
650
  }
633
651
  };
634
652
 
635
- $(function() {
653
+ window.ClientSideValidations.event = (window.Turbolinks != null) && window.Turbolinks.supported ? window.Turbolinks.EVENTS != null ? 'page:change' : 'turbolinks:load' : 'ready';
654
+
655
+ $(document).bind(window.ClientSideValidations.event, function() {
636
656
  ClientSideValidations.disableValidators();
637
657
  return $(ClientSideValidations.selectors.forms).validate();
638
658
  });