client_side_validations 15.0.0 → 16.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9aae7b42d20afe874b89eacfb409b8f7e0730b58d6d3ddd56f7f3b4fd47573db
4
- data.tar.gz: 0327e5e5af1b22a18a986e51d2471aaf7dfe0407dc61f2dab632456027b7c9a4
3
+ metadata.gz: 43b783baa4ef85e0722508e882ae809de87bc469f480a740f81eff2d7e103e55
4
+ data.tar.gz: 22d4a7022f6403cfeca96a1eca204cd94454135fbf11b196193c196ba0d19344
5
5
  SHA512:
6
- metadata.gz: f0be68614eb80ba98162abe631d7535380146394ff2473f59fae3669199d33deb1ecb3bc835dfdb64f56985d8c964c0d9962b69d5ac33f583625ef9ec42d92ad
7
- data.tar.gz: 849c0989043371872d6626b208120a2ef8a96d31b63501545343a54e91f1c699899c14ea7dd026dd4b3f216c57923fe1d0029309d34d65151c9da8e63333dd3b
6
+ metadata.gz: 3a4fb820cf1b79a10295f504e0a3bf229578d4611d2e2a4aa82e2050735a436da730fb815bcd3db98aaca914c532a5d98b1d7743e671642337eab73d22cf0b3b
7
+ data.tar.gz: 3d2eebecc60968800d8fb9b4b013055658ea0ae100e73012ee50988bd41271a6d23999587bd0e8524c74fb8c17db733197e0b60bcf2c59301cb45acf5ede696e
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 16.0.0 / 2019-08-23
4
+
5
+ * [FEATURE] Move to ES6
6
+ * [FEATURE] Add Webpacker compatibility
7
+ * [BUGFIX] Fix acceptance validator
8
+ * [ENHANCEMENT] Update development dependencies
9
+
3
10
  ## 15.0.0 / 2019-05-14
4
11
 
5
12
  * [FEATURE] Drop Ruby 2.2 support
@@ -163,6 +170,7 @@
163
170
  ## 6.0.0 / 2017-01-20
164
171
 
165
172
  * [FEATURE] Rails 5.0 compatibility
173
+ * [FEATURE] Drop Rails 4.x support
166
174
 
167
175
  ## 4.2.12 / 2017-01-19
168
176
 
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # ClientSideValidations #
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/client_side_validations.svg)](https://badge.fury.io/rb/client_side_validations)
4
+ [![npm version](https://badge.fury.io/js/%40client-side-validations%2Fclient-side-validations.svg)](https://badge.fury.io/js/%40client-side-validations%2Fclient-side-validations)
4
5
  [![Build Status](https://secure.travis-ci.org/DavyJonesLocker/client_side_validations.svg?branch=master)](https://travis-ci.org/DavyJonesLocker/client_side_validations)
5
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/9f9e8bb6edc92615f34e/maintainability)](https://codeclimate.com/github/DavyJonesLocker/client_side_validations/maintainability)
6
7
  [![Coverage Status](https://coveralls.io/repos/github/DavyJonesLocker/client_side_validations/badge.svg?branch=master)](https://coveralls.io/github/DavyJonesLocker/client_side_validations?branch=master)
7
8
 
8
- `ClientSideValidations` made easy for your Rails 5.x / Rails 6 applications!
9
+ `ClientSideValidations` made easy for your Rails 5.x / Rails 6.0 applications!
9
10
 
10
11
  ## Project Goals ##
11
12
 
@@ -49,11 +50,53 @@ This will install the initializer:
49
50
  config/initializers/client_side_validations.rb
50
51
  ```
51
52
 
52
- If you need to copy the asset files from the gem into your project:
53
+ ### JavaScript file ###
54
+
55
+ Instructions depend on your technology stack.
56
+
57
+ Please note that CSV depends on jQuery >= 1.12.4 (jQuery slim is fine).
58
+
59
+ #### When using Webpacker ####
60
+
61
+ Make sure that you are requiring jQuery.
62
+
63
+ Add the following package:
64
+
65
+ ```sh
66
+ yarn add @client-side-validations/client-side-validations
67
+ ```
68
+
69
+ Then add the following line to your `app/javascript/packs/application.js` pack:
70
+
71
+ ```js
72
+ import '@client-side-validations/client-side-validations'
73
+ ```
74
+
75
+ If you are using [Turbolinks](https://github.com/turbolinks/turbolinks),
76
+ make sure that '@client-side-validations/client-side-validations' is imported
77
+ **after** `Turbolinks.start()`, so ClientSideValidations can properly attach its
78
+ event handlers.
79
+
80
+ #### When using Sprockets ####
81
+
82
+ Make sure that you are requiring jQuery.
83
+
84
+ Add the following to your `app/assets/javascripts/application.js` file.
85
+
86
+ ```js
87
+ //= require rails.validations
88
+ ```
89
+
90
+ If you are using [Turbolinks](https://github.com/turbolinks/turbolinks),
91
+ make sure that `rails.validations` is required **after** `turbolinks`, so
92
+ ClientSideValidations can properly attach its event handlers.
93
+
94
+ If you need to copy the asset files from the gem into your project, run:
53
95
 
54
96
  ```
55
97
  rails g client_side_validations:copy_assets
56
98
  ```
99
+
57
100
  Note: If you run `copy_assets`, you will need to run it again each time you update this project.
58
101
 
59
102
  ## Initializer ##
@@ -79,17 +122,6 @@ Rails `FormBuilders`. Please see the [Plugin wiki page](https://github.com/DavyJ
79
122
 
80
123
  ## Usage ##
81
124
 
82
- The javascript file is served up in the asset pipeline. Add the
83
- following to your `app/assets/javascripts/application.js` file.
84
-
85
- ```js
86
- //= require rails.validations
87
- ```
88
-
89
- Note: If you are using [Turbolinks](https://github.com/turbolinks/turbolinks),
90
- make sure that `rails.validations` is required **after** `turbolinks`, so
91
- ClientSideValidations can properly attach its event handler.
92
-
93
125
  In your `FormBuilder` you only need to enable validations:
94
126
 
95
127
  ```erb
@@ -119,9 +151,9 @@ in the form. Given the following model:
119
151
 
120
152
  ```ruby
121
153
  class Person < ActiveRecord::Base
122
- validates :name, :email, presence: true, length: { maximum: 10 }, if: :can_validate?
154
+ validates :name, presence: true, length: { maximum: 10 }, if: :can_validate?
123
155
 
124
- def can_validate
156
+ def can_validate?
125
157
  true
126
158
  end
127
159
  end
@@ -247,7 +279,7 @@ were overwritten by the call to `FormBuilder#validate`
247
279
 
248
280
  If you need to change the markup of how the errors are rendered you can modify that in `config/initializers/client_side_validations.rb`
249
281
 
250
- *Please Note* if you modify the markup, you will also need to modify `ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder']`'s `add` and `remove` functions. You can override the behavior by creating a new javascript file called `rails.validations.actionView.js` that contains the following:
282
+ *Please Note* if you modify the markup, you will also need to modify `ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder']`'s `add` and `remove` functions. You can override the behavior by creating a new JavaScript file called `rails.validations.actionView.js` that contains the following:
251
283
 
252
284
  ```js
253
285
  window.ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'] = {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClientSideValidations
4
- VERSION = '15.0.0'
4
+ VERSION = '16.0.0'
5
5
  end
@@ -1,286 +1,185 @@
1
-
2
1
  /*!
3
- * Client Side Validations - v15.0.0 (https://github.com/DavyJonesLocker/client_side_validations)
2
+ * Client Side Validations JS - v0.0.3 (https://github.com/DavyJonesLocker/client_side_validations)
4
3
  * Copyright (c) 2019 Geremia Taglialatela, Brian Cardarella
5
4
  * Licensed under MIT (https://opensource.org/licenses/mit-license.php)
6
5
  */
7
6
 
8
- (function() {
9
- var $, ClientSideValidations, initializeOnEvent, validateElement, validateForm, validatorsFor,
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; };
11
-
12
- $ = jQuery;
13
-
14
- $.fn.disableClientSideValidations = function() {
15
- ClientSideValidations.disable(this);
16
- return this;
17
- };
18
-
19
- $.fn.enableClientSideValidations = function() {
20
- this.filter(ClientSideValidations.selectors.forms).each(function() {
21
- return ClientSideValidations.enablers.form(this);
22
- });
23
- this.filter(ClientSideValidations.selectors.inputs).each(function() {
24
- return ClientSideValidations.enablers.input(this);
25
- });
26
- return this;
27
- };
28
-
29
- $.fn.resetClientSideValidations = function() {
30
- this.filter(ClientSideValidations.selectors.forms).each(function() {
31
- return ClientSideValidations.reset(this);
32
- });
33
- return this;
34
- };
35
-
36
- $.fn.validate = function() {
37
- this.filter(ClientSideValidations.selectors.forms).each(function() {
38
- return $(this).enableClientSideValidations();
39
- });
40
- return this;
41
- };
42
-
43
- $.fn.isValid = function(validators) {
44
- var obj;
45
- obj = $(this[0]);
46
- if (obj.is('form')) {
47
- return validateForm(obj, validators);
48
- } else {
49
- return validateElement(obj, validatorsFor(this[0].name, validators));
50
- }
51
- };
7
+ (function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :
9
+ typeof define === 'function' && define.amd ? define(['jquery'], factory) :
10
+ (global = global || self, global.clientSideValidations = factory(global.$));
11
+ }(this, function ($) { 'use strict';
52
12
 
53
- validatorsFor = function(name, validators) {
54
- var captures, validator, validator_name;
55
- if (validators.hasOwnProperty(name)) {
56
- return validators[name];
57
- }
58
- name = name.replace(/\[(\w+_attributes)\]\[[\da-z_]+\](?=\[(?:\w+_attributes)\])/g, '[$1][]');
59
- if (captures = name.match(/\[(\w+_attributes)\].*\[(\w+)\]$/)) {
60
- for (validator_name in validators) {
61
- validator = validators[validator_name];
62
- if (validator_name.match("\\[" + captures[1] + "\\].*\\[\\]\\[" + captures[2] + "\\]$")) {
63
- name = name.replace(/\[[\da-z_]+\]\[(\w+)\]$/g, '[][$1]');
64
- }
65
- }
66
- }
67
- return validators[name] || {};
68
- };
13
+ $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
69
14
 
70
- validateForm = function(form, validators) {
71
- var valid;
72
- form.trigger('form:validate:before.ClientSideValidations');
73
- valid = true;
74
- form.find(ClientSideValidations.selectors.validate_inputs).each(function() {
75
- if (!$(this).isValid(validators)) {
76
- valid = false;
77
- }
78
- return true;
79
- });
80
- if (valid) {
81
- form.trigger('form:validate:pass.ClientSideValidations');
15
+ function _typeof(obj) {
16
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
17
+ _typeof = function (obj) {
18
+ return typeof obj;
19
+ };
82
20
  } else {
83
- form.trigger('form:validate:fail.ClientSideValidations');
21
+ _typeof = function (obj) {
22
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
23
+ };
84
24
  }
85
- form.trigger('form:validate:after.ClientSideValidations');
86
- return valid;
87
- };
88
25
 
89
- validateElement = function(element, validators) {
90
- var afterValidate, destroyInputName, executeValidators, failElement, local, passElement, remote;
91
- element.trigger('element:validate:before.ClientSideValidations');
92
- passElement = function() {
93
- return element.trigger('element:validate:pass.ClientSideValidations').data('valid', null);
94
- };
95
- failElement = function(message) {
96
- element.trigger('element:validate:fail.ClientSideValidations', message).data('valid', false);
97
- return false;
98
- };
99
- afterValidate = function() {
100
- return element.trigger('element:validate:after.ClientSideValidations').data('valid') !== false;
101
- };
102
- executeValidators = function(context) {
103
- var fn, i, kind, len, message, ref, valid, validator;
104
- valid = true;
105
- for (kind in context) {
106
- fn = context[kind];
107
- if (validators[kind]) {
108
- ref = validators[kind];
109
- for (i = 0, len = ref.length; i < len; i++) {
110
- validator = ref[i];
111
- if (message = fn.call(context, element, validator)) {
112
- valid = failElement(message);
113
- break;
114
- }
115
- }
116
- if (!valid) {
117
- break;
118
- }
119
- }
120
- }
121
- return valid;
122
- };
123
- if (element.attr('name').search(/\[([^\]]*?)\]$/) >= 0) {
124
- destroyInputName = element.attr('name').replace(/\[([^\]]*?)\]$/, '[_destroy]');
125
- if ($("input[name='" + destroyInputName + "']").val() === '1') {
126
- passElement();
127
- return afterValidate();
128
- }
129
- }
130
- if (element.data('changed') === false) {
131
- return afterValidate();
132
- }
133
- element.data('changed', false);
134
- local = ClientSideValidations.validators.local;
135
- remote = ClientSideValidations.validators.remote;
136
- if (executeValidators(local) && executeValidators(remote)) {
137
- passElement();
138
- }
139
- return afterValidate();
140
- };
26
+ return _typeof(obj);
27
+ }
141
28
 
142
- ClientSideValidations = {
29
+ var ClientSideValidations = {
143
30
  callbacks: {
144
31
  element: {
145
- after: function(element, eventData) {},
146
- before: function(element, eventData) {},
147
- fail: function(element, message, addError, eventData) {
32
+ after: function after(element, eventData) {},
33
+ before: function before(element, eventData) {},
34
+ fail: function fail(element, message, addError, eventData) {
148
35
  return addError();
149
36
  },
150
- pass: function(element, removeError, eventData) {
37
+ pass: function pass(element, removeError, eventData) {
151
38
  return removeError();
152
39
  }
153
40
  },
154
41
  form: {
155
- after: function(form, eventData) {},
156
- before: function(form, eventData) {},
157
- fail: function(form, eventData) {},
158
- pass: function(form, eventData) {}
42
+ after: function after(form, eventData) {},
43
+ before: function before(form, eventData) {},
44
+ fail: function fail(form, eventData) {},
45
+ pass: function pass(form, eventData) {}
159
46
  }
160
47
  },
161
- enablers: {
162
- form: function(form) {
163
- var $form, binding, event, ref;
164
- $form = $(form);
165
- form.ClientSideValidations = {
166
- settings: $form.data('clientSideValidations'),
167
- addError: function(element, message) {
168
- return ClientSideValidations.formBuilders[form.ClientSideValidations.settings.html_settings.type].add(element, form.ClientSideValidations.settings.html_settings, message);
169
- },
170
- removeError: function(element) {
171
- return ClientSideValidations.formBuilders[form.ClientSideValidations.settings.html_settings.type].remove(element, form.ClientSideValidations.settings.html_settings);
172
- }
173
- };
174
- ref = {
175
- 'submit.ClientSideValidations': function(eventData) {
176
- if (!$form.isValid(form.ClientSideValidations.settings.validators)) {
48
+ eventsToBind: {
49
+ form: function form(_form, $form) {
50
+ return {
51
+ 'submit.ClientSideValidations': function submitClientSideValidations(eventData) {
52
+ if (!$form.isValid(_form.ClientSideValidations.settings.validators)) {
177
53
  eventData.preventDefault();
178
54
  eventData.stopImmediatePropagation();
179
55
  }
180
56
  },
181
- 'ajax:beforeSend.ClientSideValidations': function(eventData) {
57
+ 'ajax:beforeSend.ClientSideValidations': function ajaxBeforeSendClientSideValidations(eventData) {
182
58
  if (eventData.target === this) {
183
- $form.isValid(form.ClientSideValidations.settings.validators);
59
+ $form.isValid(_form.ClientSideValidations.settings.validators);
184
60
  }
185
61
  },
186
- 'form:validate:after.ClientSideValidations': function(eventData) {
62
+ 'form:validate:after.ClientSideValidations': function formValidateAfterClientSideValidations(eventData) {
187
63
  ClientSideValidations.callbacks.form.after($form, eventData);
188
64
  },
189
- 'form:validate:before.ClientSideValidations': function(eventData) {
65
+ 'form:validate:before.ClientSideValidations': function formValidateBeforeClientSideValidations(eventData) {
190
66
  ClientSideValidations.callbacks.form.before($form, eventData);
191
67
  },
192
- 'form:validate:fail.ClientSideValidations': function(eventData) {
68
+ 'form:validate:fail.ClientSideValidations': function formValidateFailClientSideValidations(eventData) {
193
69
  ClientSideValidations.callbacks.form.fail($form, eventData);
194
70
  },
195
- 'form:validate:pass.ClientSideValidations': function(eventData) {
71
+ 'form:validate:pass.ClientSideValidations': function formValidatePassClientSideValidations(eventData) {
196
72
  ClientSideValidations.callbacks.form.pass($form, eventData);
197
73
  }
198
74
  };
199
- for (event in ref) {
200
- binding = ref[event];
201
- $form.on(event, binding);
202
- }
203
- return $form.find(ClientSideValidations.selectors.inputs).each(function() {
204
- return ClientSideValidations.enablers.input(this);
205
- });
206
75
  },
207
- input: function(input) {
208
- var $form, $input, binding, event, form, ref;
209
- $input = $(input);
210
- form = input.form;
211
- $form = $(form);
212
- ref = {
213
- 'focusout.ClientSideValidations': function() {
76
+ input: function input(form) {
77
+ return {
78
+ 'focusout.ClientSideValidations': function focusoutClientSideValidations() {
214
79
  $(this).isValid(form.ClientSideValidations.settings.validators);
215
80
  },
216
- 'change.ClientSideValidations': function() {
81
+ 'change.ClientSideValidations': function changeClientSideValidations() {
217
82
  $(this).data('changed', true);
218
83
  },
219
- 'element:validate:after.ClientSideValidations': function(eventData) {
84
+ 'element:validate:after.ClientSideValidations': function elementValidateAfterClientSideValidations(eventData) {
220
85
  ClientSideValidations.callbacks.element.after($(this), eventData);
221
86
  },
222
- 'element:validate:before.ClientSideValidations': function(eventData) {
87
+ 'element:validate:before.ClientSideValidations': function elementValidateBeforeClientSideValidations(eventData) {
223
88
  ClientSideValidations.callbacks.element.before($(this), eventData);
224
89
  },
225
- 'element:validate:fail.ClientSideValidations': function(eventData, message) {
226
- var element;
227
- element = $(this);
228
- ClientSideValidations.callbacks.element.fail(element, message, function() {
229
- return form.ClientSideValidations.addError(element, message);
90
+ 'element:validate:fail.ClientSideValidations': function elementValidateFailClientSideValidations(eventData, message) {
91
+ var $element = $(this);
92
+ ClientSideValidations.callbacks.element.fail($element, message, function () {
93
+ return form.ClientSideValidations.addError($element, message);
230
94
  }, eventData);
231
95
  },
232
- 'element:validate:pass.ClientSideValidations': function(eventData) {
233
- var element;
234
- element = $(this);
235
- ClientSideValidations.callbacks.element.pass(element, function() {
236
- return form.ClientSideValidations.removeError(element);
96
+ 'element:validate:pass.ClientSideValidations': function elementValidatePassClientSideValidations(eventData) {
97
+ var $element = $(this);
98
+ ClientSideValidations.callbacks.element.pass($element, function () {
99
+ return form.ClientSideValidations.removeError($element);
237
100
  }, eventData);
238
101
  }
239
102
  };
240
- for (event in ref) {
241
- binding = ref[event];
242
- $input.filter(':not(:radio):not([id$=_confirmation])').each(function() {
103
+ },
104
+ inputConfirmation: function inputConfirmation(element, form) {
105
+ return {
106
+ 'focusout.ClientSideValidations': function focusoutClientSideValidations() {
107
+ element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
108
+ },
109
+ 'keyup.ClientSideValidations': function keyupClientSideValidations() {
110
+ element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
111
+ }
112
+ };
113
+ }
114
+ },
115
+ enablers: {
116
+ form: function form(_form2) {
117
+ var $form = $(_form2);
118
+ _form2.ClientSideValidations = {
119
+ settings: $form.data('clientSideValidations'),
120
+ addError: function addError(element, message) {
121
+ return ClientSideValidations.formBuilders[_form2.ClientSideValidations.settings.html_settings.type].add(element, _form2.ClientSideValidations.settings.html_settings, message);
122
+ },
123
+ removeError: function removeError(element) {
124
+ return ClientSideValidations.formBuilders[_form2.ClientSideValidations.settings.html_settings.type].remove(element, _form2.ClientSideValidations.settings.html_settings);
125
+ }
126
+ };
127
+ var eventsToBind = ClientSideValidations.eventsToBind.form(_form2, $form);
128
+
129
+ for (var eventName in eventsToBind) {
130
+ var eventFunction = eventsToBind[eventName];
131
+ $form.on(eventName, eventFunction);
132
+ }
133
+
134
+ $form.find(ClientSideValidations.selectors.inputs).each(function () {
135
+ ClientSideValidations.enablers.input(this);
136
+ });
137
+ },
138
+ input: function input(_input) {
139
+ var $input = $(_input);
140
+ var form = _input.form;
141
+ var $form = $(form);
142
+ var eventsToBind = ClientSideValidations.eventsToBind.input(form);
143
+
144
+ for (var eventName in eventsToBind) {
145
+ var eventFunction = eventsToBind[eventName];
146
+ $input.filter(':not(:radio):not([id$=_confirmation])').each(function () {
243
147
  return $(this).attr('data-validate', true);
244
- }).on(event, binding);
148
+ }).on(eventName, eventFunction);
245
149
  }
246
- $input.filter(':checkbox').on('change.ClientSideValidations', function() {
150
+
151
+ $input.filter(':checkbox').on('change.ClientSideValidations', function () {
247
152
  $(this).isValid(form.ClientSideValidations.settings.validators);
248
153
  });
249
- return $input.filter('[id$=_confirmation]').each(function() {
250
- var confirmationElement, element, ref1, results;
251
- confirmationElement = $(this);
252
- element = $form.find("#" + (this.id.match(/(.+)_confirmation/)[1]) + ":input");
253
- if (element[0]) {
254
- ref1 = {
255
- 'focusout.ClientSideValidations': function() {
256
- element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
257
- },
258
- 'keyup.ClientSideValidations': function() {
259
- element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
260
- }
261
- };
262
- results = [];
263
- for (event in ref1) {
264
- binding = ref1[event];
265
- results.push($("#" + (confirmationElement.attr('id'))).on(event, binding));
154
+ $input.filter('[id$=_confirmation]').each(function () {
155
+ var $element = $(this);
156
+ var $elementToConfirm = $form.find('#' + this.id.match(/(.+)_confirmation/)[1] + ':input');
157
+
158
+ if ($elementToConfirm.length) {
159
+ var _eventsToBind = ClientSideValidations.eventsToBind.inputConfirmation($elementToConfirm, form);
160
+
161
+ for (var _eventName in _eventsToBind) {
162
+ var _eventFunction = _eventsToBind[_eventName];
163
+ $('#' + $element.attr('id')).on(_eventName, _eventFunction);
266
164
  }
267
- return results;
268
165
  }
269
166
  });
270
167
  }
271
168
  },
272
169
  formBuilders: {
273
170
  'ActionView::Helpers::FormBuilder': {
274
- add: function(element, settings, message) {
275
- var form, inputErrorField, label, labelErrorField;
276
- form = $(element[0].form);
277
- if (element.data('valid') !== false && (form.find("label.message[for='" + (element.attr('id')) + "']")[0] == null)) {
278
- inputErrorField = $(settings.input_tag);
279
- labelErrorField = $(settings.label_tag);
280
- label = form.find("label[for='" + (element.attr('id')) + "']:not(.message)");
171
+ add: function add(element, settings, message) {
172
+ var form = $(element[0].form);
173
+
174
+ if (element.data('valid') !== false && form.find("label.message[for='" + element.attr('id') + "']")[0] == null) {
175
+ var inputErrorField = $(settings.input_tag);
176
+ var labelErrorField = $(settings.label_tag);
177
+ var label = form.find("label[for='" + element.attr('id') + "']:not(.message)");
178
+
281
179
  if (element.attr('autofocus')) {
282
180
  element.attr('autofocus', false);
283
181
  }
182
+
284
183
  element.before(inputErrorField);
285
184
  inputErrorField.find('span#input_tag').replaceWith(element);
286
185
  inputErrorField.find('label.message').attr('for', element.attr('id'));
@@ -288,20 +187,21 @@
288
187
  labelErrorField.insertAfter(label);
289
188
  labelErrorField.find('label#label_tag').replaceWith(label);
290
189
  }
291
- return form.find("label.message[for='" + (element.attr('id')) + "']").text(message);
190
+
191
+ form.find("label.message[for='" + element.attr('id') + "']").text(message);
292
192
  },
293
- remove: function(element, settings) {
294
- var errorFieldClass, form, inputErrorField, label, labelErrorField;
295
- form = $(element[0].form);
296
- errorFieldClass = $(settings.input_tag).attr('class');
297
- inputErrorField = element.closest("." + (errorFieldClass.replace(/\ /g, ".")));
298
- label = form.find("label[for='" + (element.attr('id')) + "']:not(.message)");
299
- labelErrorField = label.closest("." + errorFieldClass);
193
+ remove: function remove(element, settings) {
194
+ var form = $(element[0].form);
195
+ var errorFieldClass = $(settings.input_tag).attr('class');
196
+ var inputErrorField = element.closest('.' + errorFieldClass.replace(/ /g, '.'));
197
+ var label = form.find("label[for='" + element.attr('id') + "']:not(.message)");
198
+ var labelErrorField = label.closest('.' + errorFieldClass);
199
+
300
200
  if (inputErrorField[0]) {
301
- inputErrorField.find("#" + (element.attr('id'))).detach();
201
+ inputErrorField.find('#' + element.attr('id')).detach();
302
202
  inputErrorField.replaceWith(element);
303
203
  label.detach();
304
- return labelErrorField.replaceWith(label);
204
+ labelErrorField.replaceWith(label);
305
205
  }
306
206
  }
307
207
  }
@@ -318,285 +218,551 @@
318
218
  forms: 'form[data-client-side-validations]'
319
219
  },
320
220
  validators: {
321
- all: function() {
322
- return $.extend({}, local, remote);
323
- },
324
- local: {
325
- absence: function(element, options) {
326
- if (!/^\s*$/.test(element.val() || '')) {
327
- return options.message;
328
- }
329
- },
330
- presence: function(element, options) {
331
- if (/^\s*$/.test(element.val() || '')) {
332
- return options.message;
333
- }
334
- },
335
- acceptance: function(element, options) {
336
- var ref;
337
- switch (element.attr('type')) {
338
- case 'checkbox':
339
- if (!element.prop('checked')) {
340
- return options.message;
341
- }
342
- break;
343
- case 'text':
344
- if (element.val() !== (((ref = options.accept) != null ? ref.toString() : void 0) || '1')) {
345
- return options.message;
346
- }
347
- }
348
- },
349
- format: function(element, options) {
350
- var message;
351
- message = this.presence(element, options);
352
- if (message) {
353
- if (options.allow_blank === true) {
354
- return;
355
- }
356
- return message;
357
- }
358
- if (options["with"] && !new RegExp(options["with"].source, options["with"].options).test(element.val())) {
359
- return options.message;
360
- }
361
- if (options.without && new RegExp(options.without.source, options.without.options).test(element.val())) {
362
- return options.message;
363
- }
364
- },
365
- numericality: function(element, options) {
366
- var $form, NUMERICALITY_CHECKS, check, checkValue, check_function, number_format, val;
367
- if (options.allow_blank === true && this.presence(element, {
368
- message: options.messages.numericality
369
- })) {
370
- return;
371
- }
372
- $form = $(element[0].form);
373
- number_format = $form[0].ClientSideValidations.settings.number_format;
374
- val = $.trim(element.val()).replace(new RegExp("\\" + number_format.separator, 'g'), '.');
375
- if (options.only_integer && !ClientSideValidations.patterns.numericality.only_integer.test(val)) {
376
- return options.messages.only_integer;
377
- }
378
- if (!ClientSideValidations.patterns.numericality["default"].test(val)) {
379
- return options.messages.numericality;
380
- }
381
- NUMERICALITY_CHECKS = {
382
- greater_than: function(a, b) {
383
- return a > b;
384
- },
385
- greater_than_or_equal_to: function(a, b) {
386
- return a >= b;
387
- },
388
- equal_to: function(a, b) {
389
- return a === b;
390
- },
391
- less_than: function(a, b) {
392
- return a < b;
393
- },
394
- less_than_or_equal_to: function(a, b) {
395
- return a <= b;
396
- }
397
- };
398
- for (check in NUMERICALITY_CHECKS) {
399
- check_function = NUMERICALITY_CHECKS[check];
400
- if (!(options[check] != null)) {
401
- continue;
402
- }
403
- 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;
404
- if ((checkValue == null) || checkValue === '') {
405
- return;
406
- }
407
- if (!check_function(parseFloat(val), parseFloat(checkValue))) {
408
- return options.messages[check];
409
- }
410
- }
411
- if (options.odd && !(parseInt(val, 10) % 2)) {
412
- return options.messages.odd;
413
- }
414
- if (options.even && (parseInt(val, 10) % 2)) {
415
- return options.messages.even;
416
- }
417
- },
418
- length: function(element, options) {
419
- var LENGTH_CHECKS, blankOptions, check, check_function, length, message;
420
- length = element.val().length;
421
- LENGTH_CHECKS = {
422
- is: function(a, b) {
423
- return a === b;
424
- },
425
- minimum: function(a, b) {
426
- return a >= b;
427
- },
428
- maximum: function(a, b) {
429
- return a <= b;
430
- }
431
- };
432
- blankOptions = {};
433
- blankOptions.message = options.is ? options.messages.is : options.minimum ? options.messages.minimum : void 0;
434
- message = this.presence(element, blankOptions);
435
- if (message) {
436
- if (options.allow_blank === true) {
437
- return;
438
- }
439
- return message;
440
- }
441
- for (check in LENGTH_CHECKS) {
442
- check_function = LENGTH_CHECKS[check];
443
- if (options[check]) {
444
- if (!check_function(length, parseInt(options[check]))) {
445
- return options.messages[check];
446
- }
447
- }
448
- }
449
- },
450
- exclusion: function(element, options) {
451
- var lower, message, option, ref, upper;
452
- message = this.presence(element, options);
453
- if (message) {
454
- if (options.allow_blank === true) {
455
- return;
456
- }
457
- return message;
458
- }
459
- if (options["in"]) {
460
- if (ref = element.val(), indexOf.call((function() {
461
- var i, len, ref1, results;
462
- ref1 = options["in"];
463
- results = [];
464
- for (i = 0, len = ref1.length; i < len; i++) {
465
- option = ref1[i];
466
- results.push(option.toString());
467
- }
468
- return results;
469
- })(), ref) >= 0) {
470
- return options.message;
471
- }
472
- }
473
- if (options.range) {
474
- lower = options.range[0];
475
- upper = options.range[1];
476
- if (element.val() >= lower && element.val() <= upper) {
477
- return options.message;
478
- }
479
- }
480
- },
481
- inclusion: function(element, options) {
482
- var lower, message, option, ref, upper;
483
- message = this.presence(element, options);
484
- if (message) {
485
- if (options.allow_blank === true) {
486
- return;
487
- }
488
- return message;
489
- }
490
- if (options["in"]) {
491
- if (ref = element.val(), indexOf.call((function() {
492
- var i, len, ref1, results;
493
- ref1 = options["in"];
494
- results = [];
495
- for (i = 0, len = ref1.length; i < len; i++) {
496
- option = ref1[i];
497
- results.push(option.toString());
498
- }
499
- return results;
500
- })(), ref) >= 0) {
501
- return;
502
- }
503
- return options.message;
504
- }
505
- if (options.range) {
506
- lower = options.range[0];
507
- upper = options.range[1];
508
- if (element.val() >= lower && element.val() <= upper) {
509
- return;
510
- }
511
- return options.message;
512
- }
513
- },
514
- confirmation: function(element, options) {
515
- var confirmation_value, value;
516
- value = element.val();
517
- confirmation_value = $("#" + (element.attr('id')) + "_confirmation").val();
518
- if (!options.case_sensitive) {
519
- value = value.toLowerCase();
520
- confirmation_value = confirmation_value.toLowerCase();
521
- }
522
- if (value !== confirmation_value) {
523
- return options.message;
524
- }
525
- },
526
- uniqueness: function(element, options) {
527
- var form, matches, name, name_prefix, name_suffix, valid, value;
528
- name = element.attr('name');
529
- if (/_attributes\]\[\d/.test(name)) {
530
- matches = name.match(/^(.+_attributes\])\[\d+\](.+)$/);
531
- name_prefix = matches[1];
532
- name_suffix = matches[2];
533
- value = element.val();
534
- if (name_prefix && name_suffix) {
535
- form = element.closest('form');
536
- valid = true;
537
- form.find(":input[name^=\"" + name_prefix + "\"][name$=\"" + name_suffix + "\"]").each(function() {
538
- var other_value;
539
- other_value = $(this).val();
540
- if (!options.case_sensitive) {
541
- value = value.toLowerCase();
542
- other_value = other_value.toLowerCase();
543
- }
544
- if ($(this).attr('name') !== name) {
545
- if (other_value === value) {
546
- valid = false;
547
- return $(this).data('notLocallyUnique', true);
548
- } else {
549
- if ($(this).data('notLocallyUnique')) {
550
- return $(this).removeData('notLocallyUnique').data('changed', true);
551
- }
552
- }
553
- }
554
- });
555
- if (!valid) {
556
- return options.message;
557
- }
558
- }
559
- }
560
- }
221
+ all: function all() {
222
+ return $.extend({});
561
223
  },
224
+ local: {},
562
225
  remote: {}
563
226
  },
564
- disable: function(target) {
565
- var $target;
566
- $target = $(target);
227
+ disable: function disable(target) {
228
+ var $target = $(target);
567
229
  $target.off('.ClientSideValidations');
230
+
568
231
  if ($target.is('form')) {
569
- return ClientSideValidations.disable($target.find(':input'));
232
+ ClientSideValidations.disable($target.find(':input'));
570
233
  } else {
571
- $target.removeData('valid');
572
- $target.removeData('changed');
573
- return $target.filter(':input').each(function() {
574
- return $(this).removeAttr('data-validate');
234
+ $target.removeData(['changed', 'valid']);
235
+ $target.filter(':input').each(function () {
236
+ $(this).removeAttr('data-validate');
575
237
  });
576
238
  }
577
239
  },
578
- reset: function(form) {
579
- var $form, key;
580
- $form = $(form);
240
+ reset: function reset(form) {
241
+ var $form = $(form);
581
242
  ClientSideValidations.disable(form);
582
- for (key in form.ClientSideValidations.settings.validators) {
243
+
244
+ for (var key in form.ClientSideValidations.settings.validators) {
583
245
  form.ClientSideValidations.removeError($form.find("[name='" + key + "']"));
584
246
  }
585
- return ClientSideValidations.enablers.form(form);
247
+
248
+ ClientSideValidations.enablers.form(form);
249
+ },
250
+ start: function start() {
251
+ if (window.Turbolinks != null && window.Turbolinks.supported) {
252
+ var initializeOnEvent = window.Turbolinks.EVENTS != null ? 'page:change' : 'turbolinks:load';
253
+ $(document).on(initializeOnEvent, function () {
254
+ return $(ClientSideValidations.selectors.forms).validate();
255
+ });
256
+ } else {
257
+ $(function () {
258
+ return $(ClientSideValidations.selectors.forms).validate();
259
+ });
260
+ }
261
+ }
262
+ };
263
+
264
+ var arrayHasValue = function arrayHasValue(value, otherValues) {
265
+ for (var i = 0, l = otherValues.length; i < l; i++) {
266
+ if (value === otherValues[i]) {
267
+ return true;
268
+ }
269
+ }
270
+
271
+ return false;
272
+ };
273
+ var valueIsPresent = function valueIsPresent(value) {
274
+ return !/^\s*$/.test(value || '');
275
+ };
276
+
277
+ var absenceLocalValidator = function absenceLocalValidator(element, options) {
278
+ if (valueIsPresent(element.val())) {
279
+ return options.message;
280
+ }
281
+ };
282
+ var presenceLocalValidator = function presenceLocalValidator(element, options) {
283
+ if (!valueIsPresent(element.val())) {
284
+ return options.message;
285
+ }
286
+ };
287
+
288
+ var DEFAULT_ACCEPT_OPTION = ['1', true];
289
+ Array.isArray || (Array.isArray = function (a) {
290
+ var object = {};
291
+ return '' + a !== a && object.toString.call(a) === '[object Array]';
292
+ });
293
+
294
+ var isTextAccepted = function isTextAccepted(value, acceptOption) {
295
+ if (!acceptOption) {
296
+ acceptOption = DEFAULT_ACCEPT_OPTION;
297
+ }
298
+
299
+ if (Array.isArray(acceptOption)) {
300
+ return arrayHasValue(value, acceptOption);
301
+ }
302
+
303
+ return value === acceptOption;
304
+ };
305
+
306
+ var acceptanceLocalValidator = function acceptanceLocalValidator(element, options) {
307
+ var valid = true;
308
+
309
+ if (element.attr('type') === 'checkbox') {
310
+ valid = element.prop('checked');
311
+ }
312
+
313
+ if (element.attr('type') === 'text') {
314
+ valid = isTextAccepted(element.val(), options.accept);
315
+ }
316
+
317
+ if (!valid) {
318
+ return options.message;
319
+ }
320
+ };
321
+
322
+ var isMatching = function isMatching(value, regExpOptions) {
323
+ return new RegExp(regExpOptions.source, regExpOptions.options).test(value);
324
+ };
325
+
326
+ var hasValidFormat = function hasValidFormat(value, withOptions, withoutOptions) {
327
+ return withOptions && isMatching(value, withOptions) || withoutOptions && !isMatching(value, withoutOptions);
328
+ };
329
+
330
+ var formatLocalValidator = function formatLocalValidator(element, options) {
331
+ var value = element.val();
332
+
333
+ if (options.allow_blank && !valueIsPresent(value)) {
334
+ return;
335
+ }
336
+
337
+ if (!hasValidFormat(value, options["with"], options.without)) {
338
+ return options.message;
339
+ }
340
+ };
341
+
342
+ var VALIDATIONS = {
343
+ even: function even(a) {
344
+ return parseInt(a, 10) % 2 === 0;
345
+ },
346
+ greater_than: function greater_than(a, b) {
347
+ return parseFloat(a) > parseFloat(b);
348
+ },
349
+ greater_than_or_equal_to: function greater_than_or_equal_to(a, b) {
350
+ return parseFloat(a) >= parseFloat(b);
351
+ },
352
+ equal_to: function equal_to(a, b) {
353
+ return parseFloat(a) === parseFloat(b);
354
+ },
355
+ less_than: function less_than(a, b) {
356
+ return parseFloat(a) < parseFloat(b);
357
+ },
358
+ less_than_or_equal_to: function less_than_or_equal_to(a, b) {
359
+ return parseFloat(a) <= parseFloat(b);
360
+ },
361
+ odd: function odd(a) {
362
+ return parseInt(a, 10) % 2 === 1;
363
+ }
364
+ };
365
+
366
+ var getOtherValue = function getOtherValue(validationOption, $form) {
367
+ if (!isNaN(parseFloat(validationOption))) {
368
+ return validationOption;
369
+ }
370
+
371
+ var validationElement = $form.find('[name*=' + validationOption + ']');
372
+
373
+ if (validationElement.length === 1) {
374
+ var numberFormat = $form[0].ClientSideValidations.settings.number_format;
375
+ var otherFormattedValue = $.trim(validationElement.val()).replace(new RegExp('\\' + numberFormat.separator, 'g'), '.');
376
+
377
+ if (!isNaN(parseFloat(otherFormattedValue))) {
378
+ return otherFormattedValue;
379
+ }
380
+ }
381
+ };
382
+
383
+ var isValid = function isValid(validationFunction, validationOption, formattedValue, $form) {
384
+ if (validationFunction.length === 2) {
385
+ var otherValue = getOtherValue(validationOption, $form);
386
+ return otherValue == null || otherValue === '' || validationFunction(formattedValue, otherValue);
387
+ } else {
388
+ return validationFunction(formattedValue);
389
+ }
390
+ };
391
+
392
+ var runFunctionValidations = function runFunctionValidations(formattedValue, $form, options) {
393
+ for (var validation in VALIDATIONS) {
394
+ var validationOption = options[validation];
395
+ var validationFunction = VALIDATIONS[validation]; // Must check for null because this could be 0
396
+
397
+ if (validationOption == null) {
398
+ continue;
399
+ }
400
+
401
+ if (!isValid(validationFunction, validationOption, formattedValue, $form)) {
402
+ return options.messages[validation];
403
+ }
404
+ }
405
+ };
406
+
407
+ var runValidations = function runValidations(formattedValue, $form, options) {
408
+ if (options.only_integer && !ClientSideValidations.patterns.numericality.only_integer.test(formattedValue)) {
409
+ return options.messages.only_integer;
410
+ }
411
+
412
+ if (!ClientSideValidations.patterns.numericality["default"].test(formattedValue)) {
413
+ return options.messages.numericality;
414
+ }
415
+
416
+ return runFunctionValidations(formattedValue, $form, options);
417
+ };
418
+
419
+ var numericalityLocalValidator = function numericalityLocalValidator(element, options) {
420
+ var value = element.val();
421
+
422
+ if (options.allow_blank && !valueIsPresent(value)) {
423
+ return;
424
+ }
425
+
426
+ var $form = $(element[0].form);
427
+ var numberFormat = $form[0].ClientSideValidations.settings.number_format;
428
+ var formattedValue = $.trim(value).replace(new RegExp('\\' + numberFormat.separator, 'g'), '.');
429
+ return runValidations(formattedValue, $form, options);
430
+ };
431
+
432
+ var VALIDATIONS$1 = {
433
+ is: function is(a, b) {
434
+ return a === parseInt(b, 10);
435
+ },
436
+ minimum: function minimum(a, b) {
437
+ return a >= parseInt(b, 10);
438
+ },
439
+ maximum: function maximum(a, b) {
440
+ return a <= parseInt(b, 10);
441
+ }
442
+ };
443
+
444
+ var runValidations$1 = function runValidations(valueLength, options) {
445
+ for (var validation in VALIDATIONS$1) {
446
+ var validationOption = options[validation];
447
+ var validationFunction = VALIDATIONS$1[validation];
448
+
449
+ if (validationOption && !validationFunction(valueLength, validationOption)) {
450
+ return options.messages[validation];
451
+ }
452
+ }
453
+ };
454
+
455
+ var lengthLocalValidator = function lengthLocalValidator(element, options) {
456
+ var value = element.val();
457
+
458
+ if (options.allow_blank && !valueIsPresent(value)) {
459
+ return;
460
+ }
461
+
462
+ return runValidations$1(value.length, options);
463
+ };
464
+
465
+ var isInList = function isInList(value, otherValues) {
466
+ var normalizedOtherValues = [];
467
+
468
+ for (var otherValueIndex in otherValues) {
469
+ normalizedOtherValues.push(otherValues[otherValueIndex].toString());
470
+ }
471
+
472
+ return arrayHasValue(value, normalizedOtherValues);
473
+ };
474
+
475
+ var isInRange = function isInRange(value, range) {
476
+ return value >= range[0] && value <= range[1];
477
+ };
478
+
479
+ var isIncluded = function isIncluded(value, options, allowBlank) {
480
+ if ((options.allow_blank && !valueIsPresent(value)) === allowBlank) {
481
+ return true;
482
+ }
483
+
484
+ return options["in"] && isInList(value, options["in"]) || options.range && isInRange(value, options.range);
485
+ };
486
+
487
+ var exclusionLocalValidator = function exclusionLocalValidator(element, options) {
488
+ var value = element.val();
489
+
490
+ if (isIncluded(value, options, false) || !options.allow_blank && !valueIsPresent(value)) {
491
+ return options.message;
492
+ }
493
+ };
494
+ var inclusionLocalValidator = function inclusionLocalValidator(element, options) {
495
+ if (!isIncluded(element.val(), options, true)) {
496
+ return options.message;
497
+ }
498
+ };
499
+
500
+ var confirmationLocalValidator = function confirmationLocalValidator(element, options) {
501
+ var value = element.val();
502
+ var confirmationValue = $('#' + element.attr('id') + '_confirmation').val();
503
+
504
+ if (!options.case_sensitive) {
505
+ value = value.toLowerCase();
506
+ confirmationValue = confirmationValue.toLowerCase();
507
+ }
508
+
509
+ if (value !== confirmationValue) {
510
+ return options.message;
511
+ }
512
+ };
513
+
514
+ var isLocallyUnique = function isLocallyUnique(currentElement, value, otherValue, caseSensitive) {
515
+ if (!caseSensitive) {
516
+ value = value.toLowerCase();
517
+ otherValue = otherValue.toLowerCase();
518
+ }
519
+
520
+ if (otherValue === value) {
521
+ $(currentElement).data('notLocallyUnique', true);
522
+ return false;
523
+ }
524
+
525
+ if ($(currentElement).data('notLocallyUnique')) {
526
+ $(currentElement).removeData('notLocallyUnique').data('changed', true);
527
+ }
528
+
529
+ return true;
530
+ };
531
+
532
+ var uniquenessLocalValidator = function uniquenessLocalValidator(element, options) {
533
+ var elementName = element.attr('name');
534
+ var matches = elementName.match(/^(.+_attributes\])\[\d+\](.+)$/);
535
+
536
+ if (!matches) {
537
+ return;
538
+ }
539
+
540
+ var form = element.closest('form');
541
+ var value = element.val();
542
+ var valid = true;
543
+ form.find(':input[name^="' + matches[1] + '"][name$="' + matches[2] + '"]').not(element).each(function () {
544
+ var otherValue = $(this).val();
545
+
546
+ if (!isLocallyUnique(this, value, otherValue, options.case_sensitive)) {
547
+ valid = false;
548
+ }
549
+ });
550
+
551
+ if (!valid) {
552
+ return options.message;
553
+ }
554
+ };
555
+
556
+ ClientSideValidations.validators.local = {
557
+ absence: absenceLocalValidator,
558
+ presence: presenceLocalValidator,
559
+ acceptance: acceptanceLocalValidator,
560
+ format: formatLocalValidator,
561
+ numericality: numericalityLocalValidator,
562
+ length: lengthLocalValidator,
563
+ inclusion: inclusionLocalValidator,
564
+ exclusion: exclusionLocalValidator,
565
+ confirmation: confirmationLocalValidator,
566
+ uniqueness: uniquenessLocalValidator
567
+ };
568
+
569
+ $.fn.disableClientSideValidations = function () {
570
+ ClientSideValidations.disable(this);
571
+ return this;
572
+ };
573
+
574
+ $.fn.enableClientSideValidations = function () {
575
+ var _this = this;
576
+
577
+ var selectors = {
578
+ forms: 'form',
579
+ inputs: 'input'
580
+ };
581
+
582
+ var _loop = function _loop() {
583
+ var enablers = selectors[selector];
584
+
585
+ _this.filter(ClientSideValidations.selectors[selector]).each(function () {
586
+ return ClientSideValidations.enablers[enablers](this);
587
+ });
588
+ };
589
+
590
+ for (var selector in selectors) {
591
+ _loop();
586
592
  }
593
+
594
+ return this;
587
595
  };
588
596
 
589
- if ((window.Turbolinks != null) && window.Turbolinks.supported) {
590
- initializeOnEvent = window.Turbolinks.EVENTS != null ? 'page:change' : 'turbolinks:load';
591
- $(document).on(initializeOnEvent, function() {
592
- return $(ClientSideValidations.selectors.forms).validate();
597
+ $.fn.resetClientSideValidations = function () {
598
+ this.filter(ClientSideValidations.selectors.forms).each(function () {
599
+ return ClientSideValidations.reset(this);
593
600
  });
594
- } else {
595
- $(function() {
596
- return $(ClientSideValidations.selectors.forms).validate();
601
+ return this;
602
+ };
603
+
604
+ $.fn.validate = function () {
605
+ this.filter(ClientSideValidations.selectors.forms).each(function () {
606
+ return $(this).enableClientSideValidations();
607
+ });
608
+ return this;
609
+ };
610
+
611
+ $.fn.isValid = function (validators) {
612
+ var obj = $(this[0]);
613
+
614
+ if (obj.is('form')) {
615
+ return validateForm(obj, validators);
616
+ } else {
617
+ return validateElement(obj, validatorsFor(this[0].name, validators));
618
+ }
619
+ };
620
+
621
+ var cleanNestedElementName = function cleanNestedElementName(elementName, nestedMatches, validators) {
622
+ for (var validatorName in validators) {
623
+ if (validatorName.match('\\[' + nestedMatches[1] + '\\].*\\[\\]\\[' + nestedMatches[2] + '\\]$')) {
624
+ elementName = elementName.replace(/\[[\da-z_]+\]\[(\w+)\]$/g, '[][$1]');
625
+ }
626
+ }
627
+
628
+ return elementName;
629
+ };
630
+
631
+ var cleanElementName = function cleanElementName(elementName, validators) {
632
+ elementName = elementName.replace(/\[(\w+_attributes)\]\[[\da-z_]+\](?=\[(?:\w+_attributes)\])/g, '[$1][]');
633
+ var nestedMatches = elementName.match(/\[(\w+_attributes)\].*\[(\w+)\]$/);
634
+
635
+ if (nestedMatches) {
636
+ elementName = cleanNestedElementName(elementName, nestedMatches, validators);
637
+ }
638
+
639
+ return elementName;
640
+ };
641
+
642
+ var validatorsFor = function validatorsFor(elementName, validators) {
643
+ if (Object.prototype.isPrototypeOf.call(validators, elementName)) {
644
+ return validators[elementName];
645
+ }
646
+
647
+ return validators[cleanElementName(elementName, validators)] || {};
648
+ };
649
+
650
+ var validateForm = function validateForm(form, validators) {
651
+ var valid = true;
652
+ form.trigger('form:validate:before.ClientSideValidations');
653
+ form.find(ClientSideValidations.selectors.validate_inputs).each(function () {
654
+ if (!$(this).isValid(validators)) {
655
+ valid = false;
656
+ }
657
+
658
+ return true;
597
659
  });
660
+
661
+ if (valid) {
662
+ form.trigger('form:validate:pass.ClientSideValidations');
663
+ } else {
664
+ form.trigger('form:validate:fail.ClientSideValidations');
665
+ }
666
+
667
+ form.trigger('form:validate:after.ClientSideValidations');
668
+ return valid;
669
+ };
670
+
671
+ var passElement = function passElement(element) {
672
+ element.trigger('element:validate:pass.ClientSideValidations').data('valid', null);
673
+ };
674
+
675
+ var failElement = function failElement(element, message) {
676
+ element.trigger('element:validate:fail.ClientSideValidations', message).data('valid', false);
677
+ };
678
+
679
+ var afterValidate = function afterValidate(element) {
680
+ return element.trigger('element:validate:after.ClientSideValidations').data('valid') !== false;
681
+ };
682
+
683
+ var executeValidator = function executeValidator(validatorFunctions, validatorFunction, validatorOptions, element) {
684
+ for (var validatorOption in validatorOptions) {
685
+ var message = validatorFunction.call(validatorFunctions, element, validatorOptions[validatorOption]);
686
+
687
+ if (message) {
688
+ failElement(element, message);
689
+ return false;
690
+ }
691
+ }
692
+
693
+ return true;
694
+ };
695
+
696
+ var executeValidators = function executeValidators(validatorFunctions, element, validators) {
697
+ for (var validator in validators) {
698
+ var validatorFunction = validatorFunctions[validator];
699
+
700
+ if (!validatorFunction) {
701
+ continue;
702
+ }
703
+
704
+ if (!executeValidator(validatorFunctions, validatorFunction, validators[validator], element)) {
705
+ return false;
706
+ }
707
+ }
708
+
709
+ return true;
710
+ };
711
+
712
+ var isMarkedForDestroy = function isMarkedForDestroy(element) {
713
+ if (element.attr('name').search(/\[([^\]]*?)\]$/) >= 0) {
714
+ var destroyInputName = element.attr('name').replace(/\[([^\]]*?)\]$/, '[_destroy]');
715
+
716
+ if ($("input[name='" + destroyInputName + "']").val() === '1') {
717
+ return true;
718
+ }
719
+ }
720
+
721
+ return false;
722
+ };
723
+
724
+ var executeAllValidators = function executeAllValidators(element, validators) {
725
+ if (element.data('changed') !== false) {
726
+ element.data('changed', false);
727
+
728
+ if (executeValidators(ClientSideValidations.validators.local, element, validators) && executeValidators(ClientSideValidations.validators.remote, element, validators)) {
729
+ passElement(element);
730
+ }
731
+ }
732
+ };
733
+
734
+ var validateElement = function validateElement(element, validators) {
735
+ element.trigger('element:validate:before.ClientSideValidations');
736
+
737
+ if (isMarkedForDestroy(element)) {
738
+ passElement(element);
739
+ } else {
740
+ executeAllValidators(element, validators);
741
+ }
742
+
743
+ return afterValidate(element);
744
+ };
745
+
746
+ if (!window.ClientSideValidations) {
747
+ window.ClientSideValidations = ClientSideValidations;
748
+
749
+ if (!isAMD() && !isCommonJS()) {
750
+ ClientSideValidations.start();
751
+ }
598
752
  }
599
753
 
600
- window.ClientSideValidations = ClientSideValidations;
754
+ function isAMD() {
755
+ return typeof define === 'function' && define.amd; // eslint-disable-line no-undef
756
+ }
757
+
758
+ function isCommonJS() {
759
+ return (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined'; // eslint-disable-line no-undef
760
+ }
761
+
762
+ var main = {
763
+ ClientSideValidations: ClientSideValidations
764
+ };
765
+
766
+ return main;
601
767
 
602
- }).call(this);
768
+ }));