client_side_validations 15.0.0 → 16.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }));