client_side_validations 23.0.0 → 24.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: ef6d8525210c9b0acce60e07133b9c2e4aabcf82b9744d3ad1cf3879547a626b
4
- data.tar.gz: dd0459e369159db8872bcb69b3a9f7b563a76215bba30a13d7ea48e7e0e6c955
3
+ metadata.gz: 2d881931955d33c3687fb6b38218fe696d081d40c6d41f788d3201bc82a5b2da
4
+ data.tar.gz: b2ca222a27708e478bd129d30eb694d6ee9cdaf8ae6547f32dad4b0ab280d199
5
5
  SHA512:
6
- metadata.gz: 356194e33e944ede175469a5ec74e29d4f71abb4c81906357e4fce7a0021bbb647c4c4559925511bb1dfab99dabe8fd06a4d5f2c8dbd7b29a98f15d8c21eef7d
7
- data.tar.gz: f839f63357b08914e87463aae5c6318b7eaab93362a5a6e0c8420e5b7824db619dbf8a78f9d4c89ae23987517f6c5cc6e20bedeffa67b77a6bee46cb6be5ea52
6
+ metadata.gz: 18e724e1e357c233d91bc16106ef5b7326f8c0b54a04a986cf488c31e1ba72cd357fce89bb3a59178e237143e05c87255a7adc6dd33e02ae9e9b7aa44ddc76e0
7
+ data.tar.gz: 0b14c029231eff6401e95f37db1cb5fb0434379fb675121e704ddbb268bba77e237315d05e30e31858ea10ae7ddd6432145f96e4d09a8c43da1abaa5e145cd6d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 24.0.0 / 2026-04-19
4
+ * [FEATURE] Breaking change: Remove the jQuery runtime dependency and the old jQuery plugin aliases from the published JavaScript assets
5
+ * [FEATURE] Breaking change: Public JavaScript APIs now work with native DOM elements and DOM collections instead of jQuery-wrapped objects
6
+ * [ENHANCEMENT] Use native browser events and event listeners throughout the runtime and test harness
7
+
8
+ ## 23.1.0 / 2026-01-27
9
+
10
+ * [FEATURE] Add jQuery 4.0.0 compatibility
11
+
3
12
  ## 23.0.0 / 2026-01-07
4
13
 
5
14
  * [FEATURE] Breaking change: Add `csv` prefix to CSV related data attributes:
data/README.md CHANGED
@@ -56,12 +56,11 @@ config/initializers/client_side_validations.rb
56
56
 
57
57
  Instructions depend on your technology stack.
58
58
 
59
- Please note that CSV depends on jQuery >= 3.7.1 (jQuery slim is fine).
59
+ ClientSideValidations no longer depends on jQuery.
60
+ If you previously installed `jquery-rails`, `jquery_ujs`, or custom jQuery startup code only for ClientSideValidations, you can remove that integration when upgrading to 24.x.
60
61
 
61
62
  #### When using Webpacker ####
62
63
 
63
- Make sure that you are requiring jQuery.
64
-
65
64
  Add the following package:
66
65
 
67
66
  ```sh
@@ -92,42 +91,77 @@ detect `window.Turbolinks` and attach its event handlers.
92
91
 
93
92
  #### When using Sprockets ####
94
93
 
95
- Since ClientSideValidations can also be used via webpacker, it does not require
96
- by default `jquery-rails` gem.
94
+ Add the following to your `app/assets/javascripts/application.js` file:
97
95
 
98
- Make sure that `jquery-rails` is part of your bundled gems and `application.js`,
99
- otherwise add:
96
+ ```js
97
+ //= require rails.validations
98
+ ```
100
99
 
101
- ```ruby
102
- gem 'jquery-rails'
100
+ If you are using [Turbolinks](https://github.com/turbolinks/turbolinks),
101
+ make sure that `rails.validations` is required **after** `turbolinks`, so
102
+ ClientSideValidations can properly attach its event handlers.
103
+
104
+ If you need to copy the asset files from the gem into your project, run:
105
+
106
+ ```
107
+ rails g client_side_validations:copy_assets
103
108
  ```
104
109
 
105
- to your `Gemfile`, run `bundle`, and add
110
+ Note: If you run `copy_assets`, you will need to run it again each time you update this project.
111
+
112
+ ## Migration Guide ##
113
+
114
+ ### 24.x Breaking Changes ###
115
+
116
+ If you are upgrading to 24.x, update your integration code to use the `ClientSideValidations` object directly.
117
+
118
+ The old jQuery plugin methods are removed. Use the DOM-first public API instead:
106
119
 
107
120
  ```js
108
- //= require jquery
121
+ ClientSideValidations.enable(form)
122
+ ClientSideValidations.validate(form)
123
+ ClientSideValidations.isValid(form, validators)
124
+ ClientSideValidations.disable(form)
125
+ ClientSideValidations.reset(form)
109
126
  ```
110
127
 
111
- to your `app/assets/javascripts/application.js` file.
128
+ These methods accept native DOM elements and DOM collections. They do not accept jQuery objects or CSS selector strings.
112
129
 
113
- Then, add the following to your `app/assets/javascripts/application.js` file
114
- after `//= require jquery`.
130
+ Custom validators, form builders, and callbacks now receive native DOM nodes instead of jQuery wrappers. Update any custom code to use DOM APIs such as `.value`, `.form`, `.closest()`, and `querySelector()`.
131
+ Local validators are called as `(element, options)`. Form callbacks receive `(form, eventData)`, and element callbacks receive either `(element, message, callback)` or `(element, callback)` depending on the event.
115
132
 
116
- ```js
117
- //= require rails.validations
133
+ All runtime-owned validation state attributes are now namespaced under `csv`. If you read or write these attributes in custom selectors, callbacks, or validators, update them to the scoped names:
134
+
135
+ ```text
136
+ data-changed => data-csv-changed
137
+ data-valid => data-csv-valid
138
+ data-validate => data-csv-validate
139
+ data-not-locally-unique => data-csv-not-locally-unique
118
140
  ```
119
141
 
120
- If you are using [Turbolinks](https://github.com/turbolinks/turbolinks),
121
- make sure that `rails.validations` is required **after** `turbolinks`, so
122
- ClientSideValidations can properly attach its event handlers.
142
+ The matching dataset properties are `element.dataset.csvChanged`, `element.dataset.csvValid`, `element.dataset.csvValidate`, and `element.dataset.csvNotLocallyUnique`. `csvChanged` is stored as the string values `'true'` and `'false'`.
123
143
 
124
- If you need to copy the asset files from the gem into your project, run:
144
+ **jQuery namespaced events are removed.** Events are now plain native DOM custom events. If your application listens to or unbinds events using jQuery-style namespacing, you must update those calls.
145
+
146
+ Before:
125
147
 
148
+ ```js
149
+ $(form).on('form:validate:before.ClientSideValidations', handler)
150
+ $(input).off('.ClientSideValidations')
126
151
  ```
127
- rails g client_side_validations:copy_assets
152
+
153
+ After:
154
+
155
+ ```js
156
+ form.addEventListener('form:validate:before', handler)
157
+ // store and pass the handler reference to removeEventListener when unbinding
128
158
  ```
129
159
 
130
- Note: If you run `copy_assets`, you will need to run it again each time you update this project.
160
+ The full list of native events dispatched by ClientSideValidations: `form:validate:before`, `form:validate:after`, `form:validate:pass`, `form:validate:fail`, `element:validate:before`, `element:validate:after`, `element:validate:pass`, `element:validate:fail`.
161
+
162
+ If you are upgrading from a version older than 23.0.0, the `data-csv-*` renaming above is required for any custom code that still reads or writes the old attribute names. If you are already on 23.x, the new 24.x upgrade step is to update any local uniqueness integrations that still reference `data-not-locally-unique` or `element.dataset.notLocallyUnique`.
163
+
164
+ If your application vendors the compiled asset with `rails g client_side_validations:copy_assets`, run that generator again after upgrading so your copied asset matches the current jQuery-free bundle.
131
165
 
132
166
  ## Initializer ##
133
167
 
@@ -324,11 +358,11 @@ If you need to change the markup of how the errors are rendered you can modify t
324
358
 
325
359
  ```js
326
360
  window.ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'] = {
327
- add: function($element, settings, message) {
361
+ add: function(element, settings, message) {
328
362
  // custom add code here
329
363
  },
330
364
 
331
- remove: function($element, settings) {
365
+ remove: function(element, settings) {
332
366
  // custom remove code here
333
367
  }
334
368
  }
@@ -376,14 +410,14 @@ en:
376
410
  Finally we need to add a client side validator. This can be done by hooking into the `ClientSideValidations.validator` object. Create a new file `app/assets/javascripts/rails.validations.customValidators.js`
377
411
 
378
412
  ```js
379
- // The validator variable is a JSON Object
380
- // The selector variable is a jQuery Object
381
- window.ClientSideValidations.validators.local['email'] = function($element, options) {
413
+ // The options variable is a JSON Object
414
+ // The element variable is a DOM element
415
+ window.ClientSideValidations.validators.local.email = function (element, options) {
382
416
  // Your validator code goes in here
383
- if (!/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i.test($element.val())) {
417
+ if (!/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i.test(element.value)) {
384
418
  // When the value fails to pass validation you need to return the error message.
385
419
  // It can be derived from validator.message
386
- return options.message;
420
+ return options.message
387
421
  }
388
422
  }
389
423
  ```
@@ -408,7 +442,7 @@ There are many reasons why you might want to enable, disable, or even completely
408
442
  If you have rendered a new form via AJAX into your page you will need to enable that form for validation:
409
443
 
410
444
  ```js
411
- $(new_form).enableClientSideValidations();
445
+ ClientSideValidations.enable(newForm)
412
446
  ```
413
447
 
414
448
  You should attach this to an event that is fired when the new HTML renders.
@@ -416,7 +450,7 @@ You should attach this to an event that is fired when the new HTML renders.
416
450
  You can use the same function if you introduce new inputs to an existing form:
417
451
 
418
452
  ```js
419
- $(new_input).enableClientSideValidations();
453
+ ClientSideValidations.enable(newInput)
420
454
  ```
421
455
 
422
456
  ### Disabling ###
@@ -424,7 +458,7 @@ $(new_input).enableClientSideValidations();
424
458
  If you wish to turn off validations entirely on a form:
425
459
 
426
460
  ```js
427
- $(form).disableClientSideValidations();
461
+ ClientSideValidations.disable(form)
428
462
  ```
429
463
 
430
464
  ### Resetting ###
@@ -432,44 +466,54 @@ $(form).disableClientSideValidations();
432
466
  You can reset the current state of the validations, clear all error messages, and reattach clean event handlers:
433
467
 
434
468
  ```js
435
- $(form).resetClientSideValidations();
469
+ ClientSideValidations.reset(form)
436
470
  ```
437
471
 
438
472
  ## Callbacks ##
439
473
 
440
474
  `ClientSideValidations` will run callbacks based upon the state of the element or form. The following callbacks are supported:
441
475
 
442
- * `ClientSideValidations.callbacks.element.after($element, eventData)`
443
- * `ClientSideValidations.callbacks.element.before($element, eventData)`
444
- * `ClientSideValidations.callbacks.element.fail($element, message, callback, eventData)`
445
- * `ClientSideValidations.callbacks.element.pass($element, callback, eventData)`
446
- * `ClientSideValidations.callbacks.form.after($form, eventData)`
447
- * `ClientSideValidations.callbacks.form.before($form, eventData)`
448
- * `ClientSideValidations.callbacks.form.fail($form, eventData)`
449
- * `ClientSideValidations.callbacks.form.pass($form, eventData)`
476
+ * `ClientSideValidations.callbacks.element.after(element, eventData)`
477
+ * `ClientSideValidations.callbacks.element.before(element, eventData)`
478
+ * `ClientSideValidations.callbacks.element.fail(element, message, callback, eventData)`
479
+ * `ClientSideValidations.callbacks.element.pass(element, callback, eventData)`
480
+ * `ClientSideValidations.callbacks.form.after(form, eventData)`
481
+ * `ClientSideValidations.callbacks.form.before(form, eventData)`
482
+ * `ClientSideValidations.callbacks.form.fail(form, eventData)`
483
+ * `ClientSideValidations.callbacks.form.pass(form, eventData)`
450
484
 
451
485
  The names of the callbacks should be pretty straight forward. For example, `ClientSideValidations.callbacks.form.fail` will be called if a form failed to validate. And `ClientSideValidations.callbacks.element.before` will be called before that particular element's validations are run.
452
486
 
453
- All element callbacks will receive the element in a jQuery object as the first parameter and the eventData object as the second parameter. `ClientSideValidations.callbacks.element.fail()` will receive the message of the failed validation as the second parameter, the callback for adding the error fields as the third and the eventData object as the third. `ClientSideValidations.elementValidatePass()` will receive the callback for removing the error fields. The error field callbacks must be run in your custom callback in some fashion. (either after a blocking event or as a callback for another event, such as an animation)
487
+ All element callbacks receive the DOM element as the first parameter and the native event object as the second parameter. `ClientSideValidations.callbacks.element.fail()` receives the failed message as the second parameter, the callback for adding error fields as the third parameter, and the eventData object as the fourth parameter. `ClientSideValidations.callbacks.element.pass()` receives the callback for removing the error fields as the second parameter. The error field callbacks must still be invoked by your custom callback.
454
488
 
455
- All form callbacks will receive the form in a jQuery object as the first parameter and the eventData object as the second parameter.
489
+ All form callbacks receive the DOM form element as the first parameter and the native event object as the second parameter.
456
490
 
457
- Here is an example callback for sliding out the error message when the validation fails then sliding it back in when the validation passes:
491
+ Here is an example callback that animates the error message when validation fails:
458
492
 
459
493
  ``` javascript
460
- // You will need to require 'jquery-ui' for this to work
461
- window.ClientSideValidations.callbacks.element.fail = function($element, message, callback) {
494
+ window.ClientSideValidations.callbacks.element.fail = function (element, message, callback) {
462
495
  callback()
463
496
 
464
- if ($element.data('csvValid') !== false) {
465
- $element.parent().find('.message').hide().show('slide', { direction: 'left', easing: 'easeOutBounce' }, 500)
497
+ var messageElement = element.parentElement.querySelector('.message')
498
+
499
+ if (messageElement) {
500
+ if (typeof messageElement.animate === 'function') {
501
+ messageElement.animate(
502
+ [
503
+ { opacity: 0, transform: 'translateX(-8px)' },
504
+ { opacity: 1, transform: 'translateX(0)' }
505
+ ],
506
+ { duration: 250, easing: 'ease-out', fill: 'both' }
507
+ )
508
+ } else {
509
+ messageElement.style.opacity = '1'
510
+ messageElement.style.transform = 'translateX(0)'
511
+ }
466
512
  }
467
513
  }
468
514
 
469
- window.ClientSideValidations.callbacks.element.pass = function($element, callback) {
470
- // Take note how we're passing the callback to the hide()
471
- // method so it is run after the animation is complete.
472
- $element.parent().find('.message').hide('slide', { direction: 'left' }, 500, callback)
515
+ window.ClientSideValidations.callbacks.element.pass = function (element, callback) {
516
+ callback()
473
517
  }
474
518
  ```
475
519
 
@@ -478,12 +522,9 @@ window.ClientSideValidations.callbacks.element.pass = function($element, callbac
478
522
  background-color: red;
479
523
  border-bottom-right-radius: 5px 5px;
480
524
  border-top-right-radius: 5px 5px;
525
+ display: inline-block;
481
526
  padding: 2px 5px;
482
527
  }
483
-
484
- div.field_with_errors div.ui-effects-wrapper {
485
- display: inline-block !important;
486
- }
487
528
  ```
488
529
 
489
530
  Finally uncomment the `ActionView::Base.field_error_proc` override in `config/initializers/client_side_validations.rb`
@@ -506,22 +547,21 @@ By default, ClientSideValidations will automatically validate the form.
506
547
  If for some reason you would like to manually validate the form (for example you're working with a multi-step form), you can use the following approach:
507
548
 
508
549
  ```js
509
- $input = $('#myInputField');
510
- $form = $($input[0].form);
511
- validators = $form[0].ClientSideValidations.settings.validators;
550
+ const input = document.getElementById('myInputField')
551
+ const form = input.form
552
+ const validators = form.ClientSideValidations.settings.validators
512
553
 
513
554
  // Validate a single field
514
- // It might not work for multiple inputs selected at once by `$input`
515
- $input.isValid(validators);
555
+ ClientSideValidations.isValid(input, validators)
516
556
 
517
557
  // Validate the whole form
518
- $form.isValid(validators);
558
+ ClientSideValidations.isValid(form, validators)
519
559
  ```
520
560
 
521
561
  To manually validate a single field, you may also trigger a focusout event:
522
562
 
523
563
  ```js
524
- $('#myInputField').trigger('focusout');
564
+ input.dispatchEvent(new Event('focusout', { bubbles: true }))
525
565
  ```
526
566
 
527
567
  ## Authors ##
@@ -63,7 +63,7 @@ module ClientSideValidations
63
63
  end
64
64
  end
65
65
 
66
- if ::ActionView::Helpers::FormBuilder.public_instance_methods.include?(:collection_checkboxes)
66
+ if ::ActionView::Helpers::FormBuilder.public_method_defined?(:collection_checkboxes)
67
67
  alias collection_checkboxes collection_check_boxes
68
68
  end
69
69
 
@@ -86,7 +86,7 @@ module ClientSideValidations
86
86
  @validators.each_with_object({}) do |object_opts, validator_hash|
87
87
  next unless object_opts[0].respond_to?(:client_side_validation_hash)
88
88
 
89
- option_hash = object_opts[1].each_with_object({}) do |attr, result|
89
+ option_hash = object_opts[1].each_with_object({}) do |attr, result| # rubocop:disable Style/ReduceToHash -- False positive
90
90
  result[attr[0]] = attr[1][:options]
91
91
  end
92
92
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClientSideValidations
4
- VERSION = '23.0.0'
4
+ VERSION = '24.0.0'
5
5
  end
@@ -1,14 +1,50 @@
1
1
  /*!
2
- * Client Side Validations JS - v23.0.0 (https://github.com/DavyJonesLocker/client_side_validations)
2
+ * Client Side Validations JS - v24.0.0 (https://github.com/DavyJonesLocker/client_side_validations)
3
3
  * Copyright (c) 2026 Geremia Taglialatela, Brian Cardarella
4
4
  * Licensed under MIT (https://opensource.org/licenses/mit-license.php)
5
5
  */
6
6
 
7
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 = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ClientSideValidations = factory(global.jQuery));
11
- })(this, (function (jQuery) { 'use strict';
8
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9
+ typeof define === 'function' && define.amd ? define(factory) :
10
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ClientSideValidations = factory());
11
+ })(this, (function () { 'use strict';
12
+
13
+ const boundEventListeners = new WeakMap();
14
+ const addBoundEventListener = (element, eventName, listener) => {
15
+ element.addEventListener(eventName, listener);
16
+ const listeners = boundEventListeners.get(element) || [];
17
+ listeners.push({
18
+ eventName,
19
+ listener
20
+ });
21
+ boundEventListeners.set(element, listeners);
22
+ };
23
+ const bindElementEvents = (element, eventsToBind) => {
24
+ for (const eventName in eventsToBind) {
25
+ addBoundEventListener(element, eventName, eventsToBind[eventName]);
26
+ }
27
+ };
28
+ const clearBoundEventListeners = element => {
29
+ const listeners = boundEventListeners.get(element);
30
+ if (!listeners) {
31
+ return;
32
+ }
33
+ listeners.forEach(_ref => {
34
+ let {
35
+ eventName,
36
+ listener
37
+ } = _ref;
38
+ element.removeEventListener(eventName, listener);
39
+ });
40
+ boundEventListeners.delete(element);
41
+ };
42
+ const dispatchCustomEvent = (element, eventName, detail) => {
43
+ element.dispatchEvent(new CustomEvent(eventName, {
44
+ bubbles: true,
45
+ detail
46
+ }));
47
+ };
12
48
 
13
49
  const arrayHasValue = (value, otherValues) => {
14
50
  for (let i = 0, l = otherValues.length; i < l; i++) {
@@ -23,136 +59,190 @@
23
59
  element.innerHTML = html;
24
60
  return element.firstChild;
25
61
  };
62
+ const isDOMCollection = target => {
63
+ return Array.isArray(target) || typeof NodeList !== 'undefined' && target instanceof NodeList || typeof HTMLCollection !== 'undefined' && target instanceof HTMLCollection || typeof RadioNodeList !== 'undefined' && target instanceof RadioNodeList;
64
+ };
65
+ const isDOMElement = target => {
66
+ return target != null && target.nodeType === 1;
67
+ };
68
+ const getDOMElements = target => {
69
+ if (target == null) {
70
+ return [];
71
+ }
72
+ if (isDOMElement(target)) {
73
+ return [target];
74
+ }
75
+ if (isDOMCollection(target)) {
76
+ return Array.from(target).filter(isDOMElement);
77
+ }
78
+ return [];
79
+ };
80
+ const isFormElement = element => {
81
+ return element.tagName === 'FORM';
82
+ };
83
+ const isInputElement = element => {
84
+ switch (element.tagName) {
85
+ case 'INPUT':
86
+ return element.type !== 'submit' && element.type !== 'button';
87
+ case 'SELECT':
88
+ case 'TEXTAREA':
89
+ return true;
90
+ default:
91
+ return false;
92
+ }
93
+ };
94
+ const isVisible = element => {
95
+ return Boolean(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
96
+ };
26
97
  const isValuePresent = value => {
27
98
  return !/^\s*$/.test(value || '');
28
99
  };
29
100
 
101
+ const isNamedInputElement = element => {
102
+ return isInputElement(element) && element.name != null && element.name !== '';
103
+ };
104
+ const getFormControls = form => {
105
+ return Array.from(form.elements).filter(isInputElement);
106
+ };
107
+ const getFormInputs = form => {
108
+ return getFormControls(form).filter(element => {
109
+ return isNamedInputElement(element) && !element.disabled && isVisible(element);
110
+ });
111
+ };
112
+ const findFormElementByName = (form, name) => {
113
+ return getFormControls(form).find(element => element.name === name);
114
+ };
115
+ const enableForm = form => {
116
+ ClientSideValidations.enablers.form(form);
117
+ };
118
+ const enableForms = () => {
119
+ document.querySelectorAll(ClientSideValidations.selectors.forms).forEach(enableForm);
120
+ };
30
121
  const ClientSideValidations = {
31
122
  callbacks: {
32
123
  element: {
33
- after: ($element, eventData) => {},
34
- before: ($element, eventData) => {},
35
- fail: ($element, message, addError, eventData) => addError(),
36
- pass: ($element, removeError, eventData) => removeError()
124
+ after: (element, eventData) => {},
125
+ before: (element, eventData) => {},
126
+ fail: (element, message, addError, eventData) => addError(),
127
+ pass: (element, removeError, eventData) => removeError()
37
128
  },
38
129
  form: {
39
- after: ($form, eventData) => {},
40
- before: ($form, eventData) => {},
41
- fail: ($form, eventData) => {},
42
- pass: ($form, eventData) => {}
130
+ after: (form, eventData) => {},
131
+ before: (form, eventData) => {},
132
+ fail: (form, eventData) => {},
133
+ pass: (form, eventData) => {}
43
134
  }
44
135
  },
45
136
  eventsToBind: {
46
- form: (form, $form) => ({
47
- 'submit.ClientSideValidations': eventData => {
48
- if (!$form.isValid(form.ClientSideValidations.settings.validators)) {
137
+ form: form => ({
138
+ submit: eventData => {
139
+ if (!ClientSideValidations.isValid(form, form.ClientSideValidations.settings.validators)) {
49
140
  eventData.preventDefault();
50
141
  eventData.stopImmediatePropagation();
51
142
  }
52
143
  },
53
- 'ajax:beforeSend.ClientSideValidations': function (eventData) {
144
+ 'ajax:beforeSend': function (eventData) {
54
145
  if (eventData.target === this) {
55
- $form.isValid(form.ClientSideValidations.settings.validators);
146
+ ClientSideValidations.isValid(form, form.ClientSideValidations.settings.validators);
56
147
  }
57
148
  },
58
- 'form:validate:after.ClientSideValidations': eventData => {
59
- ClientSideValidations.callbacks.form.after($form, eventData);
149
+ 'form:validate:after': eventData => {
150
+ ClientSideValidations.callbacks.form.after(form, eventData);
60
151
  },
61
- 'form:validate:before.ClientSideValidations': eventData => {
62
- ClientSideValidations.callbacks.form.before($form, eventData);
152
+ 'form:validate:before': eventData => {
153
+ ClientSideValidations.callbacks.form.before(form, eventData);
63
154
  },
64
- 'form:validate:fail.ClientSideValidations': eventData => {
65
- ClientSideValidations.callbacks.form.fail($form, eventData);
155
+ 'form:validate:fail': eventData => {
156
+ ClientSideValidations.callbacks.form.fail(form, eventData);
66
157
  },
67
- 'form:validate:pass.ClientSideValidations': eventData => {
68
- ClientSideValidations.callbacks.form.pass($form, eventData);
158
+ 'form:validate:pass': eventData => {
159
+ ClientSideValidations.callbacks.form.pass(form, eventData);
69
160
  }
70
161
  }),
71
162
  input: form => ({
72
- 'focusout.ClientSideValidations': function () {
73
- jQuery(this).isValid(form.ClientSideValidations.settings.validators);
163
+ focusout: function () {
164
+ ClientSideValidations.isValid(this, form.ClientSideValidations.settings.validators);
74
165
  },
75
- 'change.ClientSideValidations': function () {
166
+ change: function () {
76
167
  this.dataset.csvChanged = 'true';
77
168
  },
78
- 'element:validate:after.ClientSideValidations': function (eventData) {
79
- ClientSideValidations.callbacks.element.after(jQuery(this), eventData);
169
+ 'element:validate:after': function (eventData) {
170
+ ClientSideValidations.callbacks.element.after(this, eventData);
80
171
  },
81
- 'element:validate:before.ClientSideValidations': function (eventData) {
82
- ClientSideValidations.callbacks.element.before(jQuery(this), eventData);
172
+ 'element:validate:before': function (eventData) {
173
+ ClientSideValidations.callbacks.element.before(this, eventData);
83
174
  },
84
- 'element:validate:fail.ClientSideValidations': function (eventData, message) {
85
- const $element = jQuery(this);
86
- ClientSideValidations.callbacks.element.fail($element, message, function () {
87
- form.ClientSideValidations.addError($element, message);
175
+ 'element:validate:fail': function (eventData) {
176
+ const element = this;
177
+ const message = eventData.detail;
178
+ ClientSideValidations.callbacks.element.fail(element, message, function () {
179
+ form.ClientSideValidations.addError(element, message);
88
180
  }, eventData);
89
181
  },
90
- 'element:validate:pass.ClientSideValidations': function (eventData) {
91
- const $element = jQuery(this);
92
- ClientSideValidations.callbacks.element.pass($element, function () {
93
- form.ClientSideValidations.removeError($element);
182
+ 'element:validate:pass': function (eventData) {
183
+ const element = this;
184
+ ClientSideValidations.callbacks.element.pass(element, function () {
185
+ form.ClientSideValidations.removeError(element);
94
186
  }, eventData);
95
187
  }
96
188
  }),
97
- inputConfirmation: ($element, form) => ({
98
- 'focusout.ClientSideValidations': () => {
99
- $element[0].dataset.csvChanged = 'true';
100
- $element.isValid(form.ClientSideValidations.settings.validators);
189
+ inputConfirmation: (elementToConfirm, form) => ({
190
+ focusout: () => {
191
+ elementToConfirm.dataset.csvChanged = 'true';
192
+ ClientSideValidations.isValid(elementToConfirm, form.ClientSideValidations.settings.validators);
101
193
  },
102
- 'keyup.ClientSideValidations': () => {
103
- $element[0].dataset.csvChanged = 'true';
104
- $element.isValid(form.ClientSideValidations.settings.validators);
194
+ keyup: () => {
195
+ elementToConfirm.dataset.csvChanged = 'true';
196
+ ClientSideValidations.isValid(elementToConfirm, form.ClientSideValidations.settings.validators);
105
197
  }
106
198
  })
107
199
  },
108
200
  enablers: {
109
201
  form: form => {
110
- const $form = jQuery(form);
202
+ clearBoundEventListeners(form);
203
+ getFormControls(form).forEach(clearBoundEventListeners);
111
204
  form.ClientSideValidations = {
112
205
  settings: JSON.parse(form.dataset.clientSideValidations),
113
- addError: ($element, message) => ClientSideValidations.formBuilders[form.ClientSideValidations.settings.html_settings.type].add($element, form.ClientSideValidations.settings.html_settings, message),
114
- removeError: $element => ClientSideValidations.formBuilders[form.ClientSideValidations.settings.html_settings.type].remove($element, form.ClientSideValidations.settings.html_settings)
206
+ addError: (element, message) => ClientSideValidations.formBuilders[form.ClientSideValidations.settings.html_settings.type].add(element, form.ClientSideValidations.settings.html_settings, message),
207
+ removeError: element => ClientSideValidations.formBuilders[form.ClientSideValidations.settings.html_settings.type].remove(element, form.ClientSideValidations.settings.html_settings)
115
208
  };
116
- const eventsToBind = ClientSideValidations.eventsToBind.form(form, $form);
117
- for (const eventName in eventsToBind) {
118
- const eventFunction = eventsToBind[eventName];
119
- $form.on(eventName, eventFunction);
120
- }
121
- $form.find(ClientSideValidations.selectors.inputs).each(function () {
122
- ClientSideValidations.enablers.input(this);
209
+ bindElementEvents(form, ClientSideValidations.eventsToBind.form(form));
210
+ getFormInputs(form).forEach(element => {
211
+ ClientSideValidations.enablers.input(element);
123
212
  });
124
213
  },
125
214
  input: function (input) {
126
- const $input = jQuery(input);
127
215
  const form = input.form;
128
- const $form = jQuery(form);
216
+ if (!form) {
217
+ return;
218
+ }
219
+ clearBoundEventListeners(input);
129
220
  const eventsToBind = ClientSideValidations.eventsToBind.input(form);
130
- for (const eventName in eventsToBind) {
131
- const eventFunction = eventsToBind[eventName];
132
- $input.filter(':not(:radio):not([id$=_confirmation])').each(function () {
133
- this.dataset.csvValidate = 'true';
134
- }).on(eventName, eventFunction);
221
+ if (input.type !== 'radio' && !(input.id && input.id.endsWith('_confirmation'))) {
222
+ input.dataset.csvValidate = 'true';
223
+ bindElementEvents(input, eventsToBind);
135
224
  }
136
- $input.filter(':checkbox').on('change.ClientSideValidations', function () {
137
- jQuery(this).isValid(form.ClientSideValidations.settings.validators);
138
- });
139
- $input.filter('[id$=_confirmation]').each(function () {
140
- const $element = jQuery(this);
141
- const $elementToConfirm = $form.find("#".concat(this.id.match(/(.+)_confirmation/)[1], ":input"));
142
- if ($elementToConfirm.length) {
143
- const eventsToBind = ClientSideValidations.eventsToBind.inputConfirmation($elementToConfirm, form);
144
- for (const eventName in eventsToBind) {
145
- const eventFunction = eventsToBind[eventName];
146
- jQuery("#".concat($element.attr('id'))).on(eventName, eventFunction);
225
+ if (input.type === 'checkbox') {
226
+ bindElementEvents(input, {
227
+ change: function () {
228
+ ClientSideValidations.isValid(this, form.ClientSideValidations.settings.validators);
147
229
  }
230
+ });
231
+ }
232
+ if (input.id && input.id.endsWith('_confirmation')) {
233
+ const elementToConfirm = document.getElementById(input.id.match(/(.+)_confirmation/)[1]);
234
+ if (elementToConfirm && elementToConfirm.form === form) {
235
+ bindElementEvents(input, ClientSideValidations.eventsToBind.inputConfirmation(elementToConfirm, form));
148
236
  }
149
- });
237
+ }
150
238
  }
151
239
  },
152
240
  formBuilders: {
153
241
  'ActionView::Helpers::FormBuilder': {
154
- add: ($element, settings, message) => {
155
- const element = $element[0];
242
+ add: (element, settings, message) => {
243
+ if (!element) {
244
+ return;
245
+ }
156
246
  const form = element.form;
157
247
  const inputErrorTemplate = createElementFromHTML(settings.input_tag);
158
248
  let inputErrorElement = element.closest(".".concat(inputErrorTemplate.getAttribute('class').replace(/ /g, '.')));
@@ -182,8 +272,10 @@
182
272
  labelMessageElement.textContent = message;
183
273
  }
184
274
  },
185
- remove: ($element, settings) => {
186
- const element = $element[0];
275
+ remove: (element, settings) => {
276
+ if (!element) {
277
+ return;
278
+ }
187
279
  const form = element.form;
188
280
  const inputErrorClass = createElementFromHTML(settings.input_tag).getAttribute('class');
189
281
  const inputErrorElement = element.closest(".".concat(inputErrorClass.replace(/ /g, '.')));
@@ -213,8 +305,8 @@
213
305
  }
214
306
  },
215
307
  selectors: {
216
- inputs: ':input:not(button):not([type="submit"])[name]:visible:enabled',
217
- validate_inputs: ':input:enabled:visible[data-csv-validate]',
308
+ inputs: 'input:not([type="submit"]):not([type="button"])[name], select[name], textarea[name]',
309
+ validate_inputs: 'input[data-csv-validate]:not([type="submit"]):not([type="button"]), select[data-csv-validate], textarea[data-csv-validate]',
218
310
  forms: 'form[data-client-side-validations]'
219
311
  },
220
312
  validators: {
@@ -228,23 +320,31 @@
228
320
  remote: {}
229
321
  },
230
322
  disable: target => {
231
- const $target = jQuery(target);
232
- $target.off('.ClientSideValidations');
233
- if ($target.is('form')) {
234
- ClientSideValidations.disable($target.find(':input'));
235
- } else {
236
- delete $target[0].dataset.csvValid;
237
- delete $target[0].dataset.csvChanged;
238
- $target.filter(':input').each(function () {
239
- delete this.dataset.csvValidate;
240
- });
241
- }
323
+ getDOMElements(target).forEach(element => {
324
+ clearBoundEventListeners(element);
325
+ if (isFormElement(element)) {
326
+ getFormControls(element).forEach(input => {
327
+ clearBoundEventListeners(input);
328
+ delete input.dataset.csvValid;
329
+ delete input.dataset.csvChanged;
330
+ delete input.dataset.csvValidate;
331
+ });
332
+ return;
333
+ }
334
+ delete element.dataset.csvValid;
335
+ delete element.dataset.csvChanged;
336
+ if (isInputElement(element)) {
337
+ delete element.dataset.csvValidate;
338
+ }
339
+ });
242
340
  },
243
341
  reset: form => {
244
- const $form = jQuery(form);
245
342
  ClientSideValidations.disable(form);
246
343
  for (const key in form.ClientSideValidations.settings.validators) {
247
- form.ClientSideValidations.removeError($form.find("[name=\"".concat(key, "\"]")));
344
+ const element = findFormElementByName(form, key);
345
+ if (element) {
346
+ form.ClientSideValidations.removeError(element);
347
+ }
248
348
  }
249
349
  ClientSideValidations.enablers.form(form);
250
350
  },
@@ -258,21 +358,23 @@
258
358
  start: () => {
259
359
  const initializeOnEvent = ClientSideValidations.initializeOnEvent();
260
360
  if (initializeOnEvent != null) {
261
- jQuery(document).on(initializeOnEvent, () => jQuery(ClientSideValidations.selectors.forms).validate());
361
+ document.addEventListener(initializeOnEvent, enableForms);
362
+ } else if (document.readyState === 'loading') {
363
+ document.addEventListener('DOMContentLoaded', enableForms, {
364
+ once: true
365
+ });
262
366
  } else {
263
- jQuery(() => jQuery(ClientSideValidations.selectors.forms).validate());
367
+ enableForms();
264
368
  }
265
369
  }
266
370
  };
267
371
 
268
- const absenceLocalValidator = ($element, options) => {
269
- const element = $element[0];
372
+ const absenceLocalValidator = (element, options) => {
270
373
  if (isValuePresent(element.value)) {
271
374
  return options.message;
272
375
  }
273
376
  };
274
- const presenceLocalValidator = ($element, options) => {
275
- const element = $element[0];
377
+ const presenceLocalValidator = (element, options) => {
276
378
  if (!isValuePresent(element.value)) {
277
379
  return options.message;
278
380
  }
@@ -288,8 +390,7 @@
288
390
  }
289
391
  return value === acceptOption;
290
392
  };
291
- const acceptanceLocalValidator = ($element, options) => {
292
- const element = $element[0];
393
+ const acceptanceLocalValidator = (element, options) => {
293
394
  let valid = true;
294
395
  if (element.type === 'checkbox') {
295
396
  valid = element.checked;
@@ -308,8 +409,7 @@
308
409
  const hasValidFormat = (value, withOptions, withoutOptions) => {
309
410
  return withOptions && isMatching(value, withOptions) || withoutOptions && !isMatching(value, withoutOptions);
310
411
  };
311
- const formatLocalValidator = ($element, options) => {
312
- const element = $element[0];
412
+ const formatLocalValidator = (element, options) => {
313
413
  const value = element.value;
314
414
  if (options.allow_blank && !isValuePresent(value)) {
315
415
  return;
@@ -394,8 +494,7 @@
394
494
  }
395
495
  return runFunctionValidations(formattedValue, form, options);
396
496
  };
397
- const numericalityLocalValidator = ($element, options) => {
398
- const element = $element[0];
497
+ const numericalityLocalValidator = (element, options) => {
399
498
  const value = element.value;
400
499
  if (options.allow_blank && !isValuePresent(value)) {
401
500
  return;
@@ -425,8 +524,7 @@
425
524
  }
426
525
  }
427
526
  };
428
- const lengthLocalValidator = ($element, options) => {
429
- const element = $element[0];
527
+ const lengthLocalValidator = (element, options) => {
430
528
  const value = element.value;
431
529
  if (options.allow_blank && !isValuePresent(value)) {
432
530
  return;
@@ -450,23 +548,20 @@
450
548
  }
451
549
  return options.in && isInList(value, options.in) || options.range && isInRange(value, options.range);
452
550
  };
453
- const exclusionLocalValidator = ($element, options) => {
454
- const element = $element[0];
551
+ const exclusionLocalValidator = (element, options) => {
455
552
  const value = element.value;
456
553
  if (isIncluded(value, options, false) || !options.allow_blank && !isValuePresent(value)) {
457
554
  return options.message;
458
555
  }
459
556
  };
460
- const inclusionLocalValidator = ($element, options) => {
461
- const element = $element[0];
557
+ const inclusionLocalValidator = (element, options) => {
462
558
  const value = element.value;
463
559
  if (!isIncluded(value, options, true)) {
464
560
  return options.message;
465
561
  }
466
562
  };
467
563
 
468
- const confirmationLocalValidator = ($element, options) => {
469
- const element = $element[0];
564
+ const confirmationLocalValidator = (element, options) => {
470
565
  let value = element.value;
471
566
  let confirmationValue = document.getElementById("".concat(element.id, "_confirmation")).value;
472
567
  if (!options.case_sensitive) {
@@ -484,17 +579,16 @@
484
579
  otherValue = otherValue.toLowerCase();
485
580
  }
486
581
  if (otherValue === value) {
487
- element.dataset.notLocallyUnique = true;
582
+ element.dataset.csvNotLocallyUnique = 'true';
488
583
  return false;
489
584
  }
490
- if (element.dataset.notLocallyUnique) {
491
- delete element.dataset.notLocallyUnique;
492
- element.dataset.changed = true;
585
+ if (element.dataset.csvNotLocallyUnique) {
586
+ delete element.dataset.csvNotLocallyUnique;
587
+ element.dataset.csvChanged = 'true';
493
588
  }
494
589
  return true;
495
590
  };
496
- const uniquenessLocalValidator = ($element, options) => {
497
- const element = $element[0];
591
+ const uniquenessLocalValidator = (element, options) => {
498
592
  const elementName = element.name;
499
593
  const matches = elementName.match(/^(.+_attributes\])\[\d+\](.+)$/);
500
594
  if (!matches) {
@@ -529,42 +623,38 @@
529
623
  confirmation: confirmationLocalValidator,
530
624
  uniqueness: uniquenessLocalValidator
531
625
  };
532
- jQuery.fn.disableClientSideValidations = function () {
533
- ClientSideValidations.disable(this);
534
- return this;
535
- };
536
- jQuery.fn.enableClientSideValidations = function () {
537
- const selectors = {
538
- forms: 'form',
539
- inputs: 'input'
540
- };
541
- for (const selector in selectors) {
542
- const enablers = selectors[selector];
543
- this.filter(ClientSideValidations.selectors[selector]).each(function () {
544
- ClientSideValidations.enablers[enablers](this);
545
- });
546
- }
547
- return this;
548
- };
549
- jQuery.fn.resetClientSideValidations = function () {
550
- this.filter(ClientSideValidations.selectors.forms).each(function () {
551
- ClientSideValidations.reset(this);
626
+ ClientSideValidations.enable = target => {
627
+ getDOMElements(target).forEach(element => {
628
+ if (isFormElement(element)) {
629
+ ClientSideValidations.enablers.form(element);
630
+ } else if (isInputElement(element)) {
631
+ ClientSideValidations.enablers.input(element);
632
+ }
552
633
  });
553
- return this;
634
+ return target;
554
635
  };
555
- jQuery.fn.validate = function () {
556
- this.filter(ClientSideValidations.selectors.forms).each(function () {
557
- jQuery(this).enableClientSideValidations();
636
+ ClientSideValidations.validate = target => {
637
+ getDOMElements(target).forEach(element => {
638
+ if (isFormElement(element)) {
639
+ ClientSideValidations.enable(element);
640
+ }
558
641
  });
559
- return this;
642
+ return target;
560
643
  };
561
- jQuery.fn.isValid = function (validators) {
562
- const obj = jQuery(this[0]);
563
- if (obj.is('form')) {
564
- return validateForm(obj, validators);
565
- } else {
566
- return validateElement(obj, validatorsFor(this[0].name, validators));
644
+ ClientSideValidations.isValid = (target, validators) => {
645
+ const element = getDOMElements(target)[0];
646
+ if (!element) {
647
+ return true;
648
+ }
649
+ if (!validators) {
650
+ var _form$ClientSideValid;
651
+ const form = isFormElement(element) ? element : element.form;
652
+ validators = form === null || form === void 0 || (_form$ClientSideValid = form.ClientSideValidations) === null || _form$ClientSideValid === void 0 || (_form$ClientSideValid = _form$ClientSideValid.settings) === null || _form$ClientSideValid === void 0 ? void 0 : _form$ClientSideValid.validators;
653
+ }
654
+ if (isFormElement(element)) {
655
+ return validateForm(element, validators || {});
567
656
  }
657
+ return validateElement(element, validatorsFor(element.name, validators || {}));
568
658
  };
569
659
  const cleanNestedElementName = (elementName, nestedMatches, validators) => {
570
660
  for (const validatorName in validators) {
@@ -583,97 +673,103 @@
583
673
  return elementName;
584
674
  };
585
675
  const validatorsFor = (elementName, validators) => {
676
+ if (!elementName || !validators) {
677
+ return {};
678
+ }
586
679
  if (Object.prototype.hasOwnProperty.call(validators, elementName)) {
587
680
  return validators[elementName];
588
681
  }
589
682
  return validators[cleanElementName(elementName, validators)] || {};
590
683
  };
591
- const validateForm = ($form, validators) => {
684
+ const getValidationInputs = form => {
685
+ return Array.from(form.elements).filter(element => {
686
+ if (element.dataset.csvValidate == null || element.disabled) {
687
+ return false;
688
+ }
689
+ return isVisible(element);
690
+ });
691
+ };
692
+ const validateForm = (form, validators) => {
592
693
  let valid = true;
593
- $form.trigger('form:validate:before.ClientSideValidations');
594
- $form.find(ClientSideValidations.selectors.validate_inputs).each(function () {
595
- if (!jQuery(this).isValid(validators)) {
694
+ dispatchCustomEvent(form, 'form:validate:before');
695
+ getValidationInputs(form).forEach(element => {
696
+ if (!validateElement(element, validatorsFor(element.name, validators))) {
596
697
  valid = false;
597
698
  }
598
- return true;
599
699
  });
600
700
  if (valid) {
601
- $form.trigger('form:validate:pass.ClientSideValidations');
701
+ dispatchCustomEvent(form, 'form:validate:pass');
602
702
  } else {
603
- $form.trigger('form:validate:fail.ClientSideValidations');
703
+ dispatchCustomEvent(form, 'form:validate:fail');
604
704
  }
605
- $form.trigger('form:validate:after.ClientSideValidations');
705
+ dispatchCustomEvent(form, 'form:validate:after');
606
706
  return valid;
607
707
  };
608
- const passElement = $element => {
609
- const element = $element[0];
610
- $element.trigger('element:validate:pass.ClientSideValidations');
708
+ const passElement = element => {
709
+ dispatchCustomEvent(element, 'element:validate:pass');
611
710
  delete element.dataset.csvValid;
612
711
  };
613
- const failElement = ($element, message) => {
614
- const element = $element[0];
615
- $element.trigger('element:validate:fail.ClientSideValidations', message);
712
+ const failElement = (element, message) => {
713
+ dispatchCustomEvent(element, 'element:validate:fail', message);
616
714
  element.dataset.csvValid = 'false';
617
715
  };
618
- const afterValidate = $element => {
619
- const element = $element[0];
620
- $element.trigger('element:validate:after.ClientSideValidations');
716
+ const afterValidate = element => {
717
+ dispatchCustomEvent(element, 'element:validate:after');
621
718
  return element.dataset.csvValid !== 'false';
622
719
  };
623
- const executeValidator = (validatorFunctions, validatorFunction, validatorOptions, $element) => {
720
+ const executeValidator = (validatorFunctions, validatorFunction, validatorOptions, element) => {
624
721
  for (const validatorOption in validatorOptions) {
625
722
  if (!validatorOptions[validatorOption]) {
626
723
  continue;
627
724
  }
628
- const message = validatorFunction.call(validatorFunctions, $element, validatorOptions[validatorOption]);
725
+ const message = validatorFunction.call(validatorFunctions, element, validatorOptions[validatorOption]);
629
726
  if (message) {
630
- failElement($element, message);
727
+ failElement(element, message);
631
728
  return false;
632
729
  }
633
730
  }
634
731
  return true;
635
732
  };
636
- const executeValidators = (validatorFunctions, $element, validators) => {
733
+ const executeValidators = (validatorFunctions, element, validators) => {
637
734
  for (const validator in validators) {
638
735
  if (!validatorFunctions[validator]) {
639
736
  continue;
640
737
  }
641
- if (!executeValidator(validatorFunctions, validatorFunctions[validator], validators[validator], $element)) {
738
+ if (!executeValidator(validatorFunctions, validatorFunctions[validator], validators[validator], element)) {
642
739
  return false;
643
740
  }
644
741
  }
645
742
  return true;
646
743
  };
647
- const isMarkedForDestroy = $element => {
648
- const element = $element[0];
744
+ const isMarkedForDestroy = element => {
649
745
  const elementName = element.name;
650
- if (/\[([^\]]*?)\]$/.test(elementName)) {
746
+ const form = element.form;
747
+ if (form && /\[([^\]]*?)\]$/.test(elementName)) {
651
748
  const destroyInputName = elementName.replace(/\[([^\]]*?)\]$/, '[_destroy]');
652
- const destroyInputElement = document.querySelector("input[name=\"".concat(destroyInputName, "\"]"));
749
+ const destroyInputElement = form.querySelector("input[name=\"".concat(destroyInputName, "\"]"));
653
750
  if (destroyInputElement && destroyInputElement.value === '1') {
654
751
  return true;
655
752
  }
656
753
  }
657
754
  return false;
658
755
  };
659
- const executeAllValidators = ($element, validators) => {
660
- const element = $element[0];
756
+ const executeAllValidators = (element, validators) => {
661
757
  if (element.dataset.csvChanged === 'false' || element.disabled) {
662
758
  return;
663
759
  }
664
760
  element.dataset.csvChanged = 'false';
665
- if (executeValidators(ClientSideValidations.validators.all(), $element, validators)) {
666
- passElement($element);
761
+ if (executeValidators(ClientSideValidations.validators.all(), element, validators)) {
762
+ passElement(element);
667
763
  }
668
764
  };
669
- const validateElement = ($element, validators) => {
670
- $element.trigger('element:validate:before.ClientSideValidations');
671
- if (isMarkedForDestroy($element)) {
672
- passElement($element);
765
+ const validateElement = (element, validators) => {
766
+ dispatchCustomEvent(element, 'element:validate:before');
767
+ if (isMarkedForDestroy(element)) {
768
+ passElement(element);
673
769
  } else {
674
- executeAllValidators($element, validators);
770
+ executeAllValidators(element, validators);
675
771
  }
676
- return afterValidate($element);
772
+ return afterValidate(element);
677
773
  };
678
774
  if (!window.ClientSideValidations) {
679
775
  window.ClientSideValidations = ClientSideValidations;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: client_side_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 23.0.0
4
+ version: 24.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geremia Taglialatela
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  requirements: []
105
- rubygems_version: 4.0.3
105
+ rubygems_version: 4.0.9
106
106
  specification_version: 4
107
107
  summary: Client Side Validations
108
108
  test_files: []