@jdlien/validator 1.5.0 → 2.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.
- package/LICENSE +7 -0
- package/README.md +352 -59
- package/dist/Validator.d.ts +72 -43
- package/dist/validator.cjs +1 -0
- package/dist/validator.js +1 -1
- package/dist/validator.mjs +893 -0
- package/package.json +39 -22
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JD Lien
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# Validator -
|
|
1
|
+
# Validator - Easy, Powerful Form Validation
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
Validator is a utility class that adds automatic validation to your HTML forms that works much like
|
|
5
|
+
Validator is a lightweight utility class that adds automatic validation to your HTML forms that works much like
|
|
6
6
|
the HTML5 form validation provided by browsers, but it is much more powerful, flexible, and
|
|
7
7
|
customizable.
|
|
8
8
|
|
|
9
|
-
It can
|
|
9
|
+
It can normalize and check user input in forms, resulting in clean, consistent submissions that
|
|
10
10
|
are very user-friendly without unnecessarily constraining the user from entering data in ways that
|
|
11
11
|
are convenient for them.
|
|
12
12
|
|
|
@@ -23,8 +23,10 @@ Validator includes the following built-in validation types:
|
|
|
23
23
|
- Canadian Postal Codes
|
|
24
24
|
- Colors (CSS colors, with color picker support)
|
|
25
25
|
- Dates (optionally constrained to past or future dates)
|
|
26
|
+
- Date and time
|
|
26
27
|
- Time of day
|
|
27
28
|
- URLs
|
|
29
|
+
- Files (type, size, count)
|
|
28
30
|
|
|
29
31
|
You can also add custom validation and customize error messages per field or for the whole form.
|
|
30
32
|
|
|
@@ -37,7 +39,7 @@ npm install @jdlien/validator
|
|
|
37
39
|
|
|
38
40
|
# or
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
pnpm add @jdlien/validator
|
|
41
43
|
```
|
|
42
44
|
|
|
43
45
|
## Basic Usage
|
|
@@ -49,6 +51,18 @@ can use a `data-` variant of these attributes to avoid the browser's built-in va
|
|
|
49
51
|
|
|
50
52
|
Any input that you want to validate should have a unique name attribute. If you want to display error messages for the input, you must also have a div with an id that is the name of the input + `-error`.
|
|
51
53
|
|
|
54
|
+
If you're using a bundler:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import Validator from '@jdlien/validator'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If you're using CommonJS:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const Validator = require('@jdlien/validator')
|
|
64
|
+
```
|
|
65
|
+
|
|
52
66
|
Then, create a new Validator instance and pass it the form element as the first argument. An optional second argument allows you to pass in options. Here is a simplified example:
|
|
53
67
|
|
|
54
68
|
```html
|
|
@@ -76,8 +90,16 @@ Then, create a new Validator instance and pass it the form element as the first
|
|
|
76
90
|
<input type="submit" value="Submit" />
|
|
77
91
|
</form>
|
|
78
92
|
|
|
79
|
-
<!--
|
|
80
|
-
|
|
93
|
+
<!-- Choose one of the following script tags if you are not using a bundler -->
|
|
94
|
+
<!-- ESM - recommended for modern browsers -->
|
|
95
|
+
<script type="module">
|
|
96
|
+
import Validator from 'https://unpkg.com/@jdlien/validator/dist/validator.mjs'
|
|
97
|
+
const form = document.getElementById('myForm')
|
|
98
|
+
const validator = new Validator(form)
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<!-- UMD - for legacy browser support (exposes global Validator) -->
|
|
102
|
+
<script src="https://unpkg.com/@jdlien/validator/dist/validator.js"></script>
|
|
81
103
|
<script>
|
|
82
104
|
const form = document.getElementById('myForm')
|
|
83
105
|
const validator = new Validator(form)
|
|
@@ -107,7 +129,7 @@ There are a few attributes that Validator looks for on the form element:
|
|
|
107
129
|
|
|
108
130
|
- `data-prevent-submit` - If this attribute is present, the form will never be submitted, even if it is valid. This is useful if you want to handle the submission yourself. (By default, the form will be submitted if it is valid and not if it is invalid.)
|
|
109
131
|
|
|
110
|
-
- `novalidate` - This is a native HTML5 attribute that
|
|
132
|
+
- `novalidate` - This is a native HTML5 attribute that disables browser validation on the form. Validator adds this by default and removes it if `destroy()` is called. If you add it yourself, it will not be added back by Validator.
|
|
111
133
|
|
|
112
134
|
On input (and sometimes select and textarea) elements, the following attributes are supported:
|
|
113
135
|
|
|
@@ -117,54 +139,134 @@ On input (and sometimes select and textarea) elements, the following attributes
|
|
|
117
139
|
- `pattern`/`data-pattern` - The input must match the specified regular expression.
|
|
118
140
|
- `type`/`data-type` - The input must match the specified type. The following types are supported:
|
|
119
141
|
|
|
120
|
-
- `number` - The input must be a number (use `data-type` to avoid quirky browser behavior)
|
|
142
|
+
- `number` (also `float`/`decimal`) - The input must be a number (use `data-type` to avoid quirky browser behavior)
|
|
121
143
|
- `integer` - The input must be a positive whole number.
|
|
122
144
|
- `tel` - The input must be a valid North American phone number.
|
|
123
145
|
- `email` - The input must be a valid email address.
|
|
124
146
|
- `zip` - The input must be a valid US zip code.
|
|
125
147
|
- `postal` - The input must be a valid Canadian postal code.
|
|
126
|
-
- `color` - The input must be a valid CSS color.
|
|
127
148
|
- `date` - The input must be a valid date.
|
|
149
|
+
- `datetime` - The input must be a valid date and time.
|
|
128
150
|
- `time` - The input must be a valid time.
|
|
129
151
|
- `url` - The input must be a valid URL.
|
|
130
152
|
- `color` - The input must be a valid CSS color. (This can be used in conjunction with a native color input - see Color Picker Support for details.)
|
|
131
153
|
|
|
132
|
-
- `data-date-format`/`data-time-format` - Applies formatting to time
|
|
133
|
-
- `data-date-range` - Applies to date input types. Supported values are `past` and `
|
|
154
|
+
- `data-date-format`/`data-time-format` - Applies formatting to date, time, or datetime inputs (these are interchangeable). The format must be a valid moment.js format string. See [moment.js docs](https://momentjs.com/docs/#/displaying/format/) for more information.
|
|
155
|
+
- `data-date-range` - Applies to date input types. Supported values are `past`, `future`, and `today`.
|
|
156
|
+
- `data-min`/`data-max` - Applies to numeric input types (`number`, `integer`, `float`, `decimal`). Validates that the numeric value is within the specified range. Also respects the native `min`/`max` attributes, but `data-` attributes take precedence.
|
|
157
|
+
- `data-arrow-step` - Applies to numeric input types (`number`, `integer`, `float`, `decimal`). Sets the arrow key step size (defaults to `1`). Set `data-arrow-step=""` to disable arrow key handling for the field.
|
|
134
158
|
- `data-error-default` - A custom error message to display if the input is invalid. This will be used for required, pattern, and date-range validation failures.
|
|
135
159
|
- `data-validation` - The name of a custom validation function.
|
|
136
160
|
- `data-novalidate` - If this attribute is present, the input will not be validated when `input` or `change` events are triggered on it.
|
|
161
|
+
- `data-max-files` - Applies to file inputs. Limits the number of files a user can upload.
|
|
162
|
+
- `data-min-file-size`/`data-max-file-size` - Applies to file inputs. Enforces min/max size per file. Accepts human-readable sizes like `200kb` (base 10), `2mib` (base 2), `1.5g`.
|
|
163
|
+
- `accept`/`data-accept` - Applies to file inputs. Restricts allowed file types using MIME types and/or extensions. `data-accept` takes precedence over `accept`.
|
|
137
164
|
|
|
138
165
|
A validation function will be called with the input value as the argument. The function may either return a boolean (true/false) or an object with a `valid` property that is a boolean. If the function returns a string or an object with a `message` property, that will be used as the error message for the input. A `messages` array may also be specified which will be used to display multiple error messages for the input.
|
|
139
166
|
|
|
140
167
|
You may also use a promise that resolves to such an object for asynchronous validation.
|
|
141
168
|
|
|
142
|
-
|
|
169
|
+
### Registering Custom Validators
|
|
170
|
+
|
|
171
|
+
There are three ways to register custom validators, listed in order of lookup priority:
|
|
172
|
+
|
|
173
|
+
#### 1. Instance Registry (Recommended)
|
|
174
|
+
|
|
175
|
+
Pass validators directly to the Validator constructor. This is the recommended approach as it provides the best type safety and keeps validators scoped to specific forms.
|
|
143
176
|
|
|
144
177
|
```javascript
|
|
145
|
-
|
|
146
|
-
|
|
178
|
+
const validator = new Validator(form, {
|
|
179
|
+
validators: {
|
|
180
|
+
validateUsername: (value) => {
|
|
181
|
+
if (value.length < 3) return 'Username must be at least 3 characters'
|
|
182
|
+
return true
|
|
183
|
+
},
|
|
184
|
+
validateEmail: async (value) => {
|
|
185
|
+
const res = await fetch(`/api/check-email?email=${encodeURIComponent(value)}`)
|
|
186
|
+
return res.ok ? true : 'Email already taken'
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
})
|
|
190
|
+
```
|
|
147
191
|
|
|
148
|
-
|
|
192
|
+
#### 2. Static Registry (For Shared Validators)
|
|
193
|
+
|
|
194
|
+
Use `Validator.registerValidator()` to make validators available to all Validator instances. Useful for reusable validators across your application.
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
// Register globally (available to all forms)
|
|
198
|
+
Validator.registerValidator('validatePhone', (value) => {
|
|
199
|
+
return /^\d{10}$/.test(value) ? true : 'Enter a 10-digit phone number'
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
// Later, in any form...
|
|
203
|
+
const validator = new Validator(form)
|
|
204
|
+
// Input with data-validation="validatePhone" will use the registered validator
|
|
205
|
+
|
|
206
|
+
// Other static methods:
|
|
207
|
+
Validator.unregisterValidator('validatePhone') // Remove a validator
|
|
208
|
+
Validator.getValidators() // Get all registered validators (returns a copy)
|
|
209
|
+
Validator.clearValidators() // Remove all registered validators
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### 3. Window Object (Legacy)
|
|
213
|
+
|
|
214
|
+
For backward compatibility, validators can be defined on the window object. This is not recommended for new code.
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
window.validateCustom = (value) => {
|
|
218
|
+
return value === 'valid' ? true : 'Invalid value'
|
|
149
219
|
}
|
|
150
220
|
```
|
|
151
221
|
|
|
152
|
-
|
|
222
|
+
### Lookup Priority
|
|
223
|
+
|
|
224
|
+
When resolving a validator by name, Validator checks in this order:
|
|
225
|
+
|
|
226
|
+
1. **Instance registry** (validators passed to constructor)
|
|
227
|
+
2. **Static registry** (Validator.registerValidator)
|
|
228
|
+
3. **Window object** (legacy fallback)
|
|
229
|
+
|
|
230
|
+
This allows you to override global validators for specific forms when needed.
|
|
231
|
+
|
|
232
|
+
### Validator Function Examples
|
|
233
|
+
|
|
234
|
+
Custom validators are functions you can write that receive the input value and can return:
|
|
235
|
+
|
|
236
|
+
- `true` — valid
|
|
237
|
+
- `false` — invalid (uses default error message)
|
|
238
|
+
- `string` — invalid with custom error message
|
|
239
|
+
- `{ valid: boolean, message?: string, messages?: string[] }` — structured result
|
|
240
|
+
|
|
241
|
+
All return types can be wrapped in a `Promise` for async validation.
|
|
153
242
|
|
|
154
243
|
```javascript
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
244
|
+
// Simple synchronous validator:
|
|
245
|
+
function customValidation(value) {
|
|
246
|
+
if (value === 'foo') return 'The value cannot be foo.'
|
|
247
|
+
return true
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Async validator using fetch:
|
|
251
|
+
async function customValidationPromise(value) {
|
|
252
|
+
const response = await fetch(`/api/validate-username?username=${value}`)
|
|
253
|
+
const { valid, error } = await response.json()
|
|
254
|
+
return valid ? true : error
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Structured result with multiple errors:
|
|
258
|
+
function validatePassword(value) {
|
|
259
|
+
const errors = []
|
|
260
|
+
if (value.length < 8) errors.push('Must be at least 8 characters')
|
|
261
|
+
if (!/[A-Z]/.test(value)) errors.push('Must contain an uppercase letter')
|
|
262
|
+
if (!/[0-9]/.test(value)) errors.push('Must contain a number')
|
|
263
|
+
return errors.length ? { valid: false, messages: errors } : true
|
|
162
264
|
}
|
|
163
265
|
```
|
|
164
266
|
|
|
165
267
|
## Displaying Error Messages
|
|
166
268
|
|
|
167
|
-
If any form validation fails on submission, Validator displays a main error message
|
|
269
|
+
If any form validation fails on submission, Validator displays a main error message directly beneath the form. By default, it looks for an element with the ID `form-error-main`. However, if the form itself has an `id` attribute (e.g., `<form id="contact-form">`), Validator will first look for a main error element with the ID `{form.id}-error-main` (e.g., `contact-form-error-main`). If that form-specific element is not found, it falls back to looking for `form-error-main`.
|
|
168
270
|
|
|
169
271
|
This allows for more targeted styling and placement of the main error message per form. You can disable the display of this main error message entirely by setting the `showMainError` option to `false`.
|
|
170
272
|
|
|
@@ -174,11 +276,11 @@ If you do not use `aria-describedby`, Validator will fall back to displaying err
|
|
|
174
276
|
|
|
175
277
|
It is recommended to initially hide error elements with a class that sets properties such as `display: none;`, `visibility: hidden;`, or `opacity: 0;`.
|
|
176
278
|
|
|
177
|
-
You can customize the class(es) that Validator uses to hide the error messages by passing in a `
|
|
279
|
+
You can customize the class(es) that Validator uses to hide the error messages by passing in a `hiddenClasses` option to the Validator constructor. The default is `hidden opacity-0`.
|
|
178
280
|
|
|
179
281
|
## Color Picker Support
|
|
180
282
|
|
|
181
|
-
|
|
283
|
+
Use data-type="color" and the input must contain any valid CSS color supported by the browser. To use this with a native color input, add an input with `type="color"` and the ID of the data-color input + `-color`. This should be inside a linked label, which will become the color preview swatch. Such a label should have an ID of the color input's name + `-color-label` so that Validator can change the background to the specified color.
|
|
182
284
|
|
|
183
285
|
A basic example that would work:
|
|
184
286
|
|
|
@@ -198,7 +300,7 @@ A basic example that would work:
|
|
|
198
300
|
|
|
199
301
|
The second parameter to the Validator constructor is an options object. The following options are available:
|
|
200
302
|
|
|
201
|
-
- `messages - An object containing custom error messages. The default messages can be overridden by
|
|
303
|
+
- `messages` - An object containing custom error messages. The default messages can be overridden by passing in a custom message object. These are all the default messages:
|
|
202
304
|
|
|
203
305
|
```javascript
|
|
204
306
|
messages = {
|
|
@@ -209,6 +311,8 @@ messages = {
|
|
|
209
311
|
CHECKED_REQUIRED: 'This must be checked.',
|
|
210
312
|
ERROR_MAXLENGTH: 'This must be ${val} characters or fewer.',
|
|
211
313
|
ERROR_MINLENGTH: 'This must be at least ${val} characters.',
|
|
314
|
+
ERROR_MIN_VALUE: 'The value must be at least ${val}.',
|
|
315
|
+
ERROR_MAX_VALUE: 'The value must be at most ${val}.',
|
|
212
316
|
ERROR_NUMBER: 'This must be a number.',
|
|
213
317
|
ERROR_INTEGER: 'This must be a whole number.',
|
|
214
318
|
ERROR_TEL: 'This is not a valid telephone number.',
|
|
@@ -219,10 +323,14 @@ messages = {
|
|
|
219
323
|
ERROR_DATE_PAST: 'The date must be in the past.',
|
|
220
324
|
ERROR_DATE_FUTURE: 'The date must be in the future.',
|
|
221
325
|
ERROR_DATE_RANGE: 'The date is outside the allowed range.',
|
|
326
|
+
ERROR_DATETIME: 'This is not a valid date and time.',
|
|
222
327
|
ERROR_TIME: 'This is not a valid time.',
|
|
223
|
-
ERROR_TIME_RANGE: 'The time is outside the allowed range.',
|
|
224
328
|
ERROR_URL: 'This is not a valid URL.',
|
|
225
329
|
ERROR_COLOR: 'This is not a valid CSS colour.',
|
|
330
|
+
ERROR_FILE_TYPE: 'This file type is not allowed.',
|
|
331
|
+
ERROR_FILE_MAX_FILES: 'You can upload up to ${val} file(s).',
|
|
332
|
+
ERROR_FILE_MAX_SIZE: 'Each file must be ${val} or smaller.',
|
|
333
|
+
ERROR_FILE_MIN_SIZE: 'Each file must be at least ${val}.',
|
|
226
334
|
ERROR_CUSTOM_VALIDATION: 'There was a problem validating this field.',
|
|
227
335
|
}
|
|
228
336
|
```
|
|
@@ -232,15 +340,19 @@ messages = {
|
|
|
232
340
|
- `preventSubmit` - A boolean indicating whether or not to prevent form submission if validation is successful. Defaults to false.
|
|
233
341
|
- `hiddenClasses` - A string containing one or more space-separated classes to toggle the hidden mode (e.g., `display: none` CSS property) on hidden elements. Defaults to `hidden opacity-0`.
|
|
234
342
|
- `errorMainClasses` - A string containing one or more space-separated classes to apply to the main error message.
|
|
235
|
-
- `errorInputClasses` - A string containing one or more space-separated classes to apply to invalid
|
|
343
|
+
- `errorInputClasses` - A string containing one or more space-separated classes to apply to invalid inputs.
|
|
236
344
|
- `showMainError` - A boolean indicating whether or not to show the main error message. Defaults to `true`.
|
|
345
|
+
- `scrollToError` - A boolean indicating whether to scroll to and focus the first invalid input when validation fails. Defaults to `false`.
|
|
346
|
+
- `scrollToErrorDelay` - A number (ms) to delay scroll-to-error behavior. Defaults to `0`.
|
|
347
|
+
- `validateOnBlur` - A boolean indicating whether to validate fields when they lose focus, even if the value hasn't changed. Useful for showing errors on touched-but-empty required fields. Defaults to `false`.
|
|
237
348
|
- `validationSuccessCallback` - A function to be called when validation is successful.
|
|
238
349
|
- `validationErrorCallback` - A function to be called when validation fails.
|
|
350
|
+
- `validators` - An object mapping validator names to functions. These validators have the highest lookup priority (see Registering Custom Validators).
|
|
239
351
|
|
|
240
352
|
### Example:
|
|
241
353
|
|
|
242
354
|
```javascript
|
|
243
|
-
import Validator from 'validator'
|
|
355
|
+
import Validator from '@jdlien/validator'
|
|
244
356
|
|
|
245
357
|
const myForm = document.querySelector('form')
|
|
246
358
|
const myValidator = new Validator(myForm, {
|
|
@@ -258,6 +370,125 @@ const myValidator = new Validator(myForm, {
|
|
|
258
370
|
})
|
|
259
371
|
```
|
|
260
372
|
|
|
373
|
+
## Methods
|
|
374
|
+
|
|
375
|
+
### Instance Methods
|
|
376
|
+
|
|
377
|
+
#### `validateSingle(input): Promise<boolean>`
|
|
378
|
+
|
|
379
|
+
Validates a single input that belongs to the form and displays any error messages. Returns `true` if the input is valid, `false` otherwise.
|
|
380
|
+
|
|
381
|
+
This is useful for:
|
|
382
|
+
|
|
383
|
+
- **Multi-step forms/wizards** - Validate each step before allowing progression
|
|
384
|
+
- **Dependent field validation** - Validate field A when field B changes
|
|
385
|
+
- **Custom validation triggers** - Validate on demand rather than relying on events
|
|
386
|
+
- **Dynamic form updates** - Validate after programmatically updating a field's value
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
const validator = new Validator(form)
|
|
390
|
+
const emailInput = document.getElementById('email')
|
|
391
|
+
|
|
392
|
+
// Validate a single input on demand
|
|
393
|
+
const isValid = await validator.validateSingle(emailInput)
|
|
394
|
+
|
|
395
|
+
if (isValid) {
|
|
396
|
+
// Proceed to next step
|
|
397
|
+
} else {
|
|
398
|
+
// Error messages are automatically displayed
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Notes:
|
|
403
|
+
|
|
404
|
+
- Only validates inputs that belong to the validator's form
|
|
405
|
+
- Returns `true` for inputs not in the form (with console warning) or disabled inputs (use `Validator.validateSingle()` for standalone inputs)
|
|
406
|
+
- Clears previous errors before validating
|
|
407
|
+
- Displays error messages in the associated error element
|
|
408
|
+
- Works with all form control types (input, select, textarea) except radio/checkbox groups
|
|
409
|
+
|
|
410
|
+
#### `clearInputErrors(input): void`
|
|
411
|
+
|
|
412
|
+
Clears validation errors from a specific input element.
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
validator.clearInputErrors(emailInput)
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
#### `clearAllErrors(): void`
|
|
419
|
+
|
|
420
|
+
Clears all validation errors from the form, including the main error message and all input errors.
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
validator.clearAllErrors()
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
#### `init(): void`
|
|
427
|
+
|
|
428
|
+
Re-initializes the validator, refreshing the list of form inputs. Call this after dynamically adding or removing inputs.
|
|
429
|
+
|
|
430
|
+
#### `destroy(): void`
|
|
431
|
+
|
|
432
|
+
Removes all event listeners and restores the form's original `novalidate` state. Call this before removing the form from the DOM.
|
|
433
|
+
|
|
434
|
+
### Static Methods
|
|
435
|
+
|
|
436
|
+
These methods allow validation without creating a Validator instance, useful for standalone inputs outside of forms.
|
|
437
|
+
|
|
438
|
+
#### `Validator.validateSingle(input, options?): Promise<boolean>`
|
|
439
|
+
|
|
440
|
+
Validates any input element without needing a Validator instance. Useful for standalone fields outside of forms.
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
// Validate a standalone input (not in a form)
|
|
444
|
+
const standaloneInput = document.getElementById('standalone-email')
|
|
445
|
+
const isValid = await Validator.validateSingle(standaloneInput)
|
|
446
|
+
|
|
447
|
+
// With custom options
|
|
448
|
+
const isValid = await Validator.validateSingle(standaloneInput, {
|
|
449
|
+
validators: {
|
|
450
|
+
customCheck: (value) => value.length > 5 || 'Too short',
|
|
451
|
+
},
|
|
452
|
+
})
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
#### `Validator.clearInputErrors(input, options?): void`
|
|
456
|
+
|
|
457
|
+
Clears validation errors from any input element without needing a Validator instance.
|
|
458
|
+
|
|
459
|
+
```javascript
|
|
460
|
+
Validator.clearInputErrors(standaloneInput)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## Events
|
|
464
|
+
|
|
465
|
+
Validator dispatches two custom events on the form during submission validation:
|
|
466
|
+
|
|
467
|
+
- `validationSuccess` - Fired when the form is valid.
|
|
468
|
+
- `validationError` - Fired when the form is invalid.
|
|
469
|
+
|
|
470
|
+
Both events are instances of `ValidationEvent` and include the original submit event as `submitEvent`.
|
|
471
|
+
|
|
472
|
+
## Dynamic Forms and Cleanup
|
|
473
|
+
|
|
474
|
+
Validator does not watch the DOM for changes. If you add or remove inputs after initialization
|
|
475
|
+
(for example, injecting fields with JavaScript or swapping Blade partials), call `init()` again
|
|
476
|
+
to refresh the list of inputs and their error state.
|
|
477
|
+
|
|
478
|
+
If you remove the form from the page (such as when closing a modal or navigating in an SPA),
|
|
479
|
+
call `destroy()` first to remove event listeners and restore the form's original `novalidate` state.
|
|
480
|
+
|
|
481
|
+
```javascript
|
|
482
|
+
const validator = new Validator(form)
|
|
483
|
+
|
|
484
|
+
// After dynamically adding/removing inputs:
|
|
485
|
+
validator.init()
|
|
486
|
+
|
|
487
|
+
// Before removing the form from the DOM:
|
|
488
|
+
validator.destroy()
|
|
489
|
+
form.remove()
|
|
490
|
+
```
|
|
491
|
+
|
|
261
492
|
## Utility Functions
|
|
262
493
|
|
|
263
494
|
Validator uses its own `@jdlien/validator-utils` for several utility functions that may be useful in your own code. You may use this package directly if you need any of these functions without using the Validator class.
|
|
@@ -268,54 +499,116 @@ If you wish to use these, you may import the functions directly from the module
|
|
|
268
499
|
// Import all the functions into a validatorUtils object
|
|
269
500
|
import * as validatorUtils from '@jdlien/validator-utils'
|
|
270
501
|
// Or just import the functions you need
|
|
271
|
-
import {
|
|
502
|
+
import { parseDate, formatDateTime } from '@jdlien/validator-utils'
|
|
272
503
|
```
|
|
273
504
|
|
|
274
505
|
Here is a list of the utility functions:
|
|
275
506
|
|
|
276
|
-
|
|
277
|
-
- **isType**: Checks if an element has a type or data-type attribute matching one of the passed values.
|
|
278
|
-
- **momentToFPFormat**: Converts a moment.js-style format string to the flatpickr format.
|
|
279
|
-
- **monthToNumber**: Converts month string or number to a zero-based month number (January == 0).
|
|
280
|
-
- **yearToFull**: Converts a year string or number to a 4-digit year.
|
|
507
|
+
**Date & Time:**
|
|
281
508
|
- **parseDate**: Parses a date string or Date object into a Date object.
|
|
509
|
+
- **parseDateTime**: Parses a datetime string (e.g., "tomorrow 3pm") into a Date object.
|
|
282
510
|
- **parseTime**: Parses a time string into an object with hour, minute, and second properties.
|
|
283
|
-
- **
|
|
284
|
-
- **
|
|
285
|
-
- **
|
|
511
|
+
- **parseRelativeDate**: Parses relative date strings like "+3d", "-1w", "+2m" into a Date object.
|
|
512
|
+
- **parseDateToString**: Formats a date into a string with the specified moment.js-style format.
|
|
513
|
+
- **parseDateTimeToString**: Formats a datetime into a string with the specified format.
|
|
514
|
+
- **parseTimeToString**: Formats a time string into a formatted string.
|
|
515
|
+
- **formatDateTime**: Formats a Date object into a string with a specified format.
|
|
516
|
+
- **momentToFPFormat**: Converts a moment.js-style format string to flatpickr format.
|
|
517
|
+
- **monthToNumber**: Converts month string or number to zero-based month number (January = 0).
|
|
518
|
+
- **yearToFull**: Converts a 2-digit year to a 4-digit year.
|
|
286
519
|
- **isDate**: Determines if a value is a valid date.
|
|
287
|
-
- **
|
|
520
|
+
- **isDateTime**: Determines if a value is a valid datetime.
|
|
288
521
|
- **isTime**: Determines if a value is a valid time.
|
|
289
|
-
- **
|
|
290
|
-
- **
|
|
291
|
-
|
|
292
|
-
|
|
522
|
+
- **isMeridiem**: Determines if a value is "am" or "pm".
|
|
523
|
+
- **isDateInRange**: Determines if a date falls within a specified range (past, future, or custom).
|
|
524
|
+
|
|
525
|
+
**Numbers & Bytes:**
|
|
526
|
+
- **parseNumber**: Parses a number string, stripping non-numeric characters.
|
|
527
|
+
- **parseInteger**: Parses an integer string, stripping non-digit characters.
|
|
528
|
+
- **parseBytes**: Parses human-readable byte sizes ("1.5MB", "2GiB") into bytes.
|
|
529
|
+
- **formatBytes**: Formats bytes into human-readable string (e.g., "1.5 MB").
|
|
293
530
|
- **isNumber**: Determines if a value is a valid number.
|
|
294
|
-
- **parseNumber**: Parses a number string into a standardized format.
|
|
295
531
|
- **isInteger**: Determines if a value is a valid integer.
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
- **
|
|
299
|
-
- **
|
|
300
|
-
- **
|
|
532
|
+
|
|
533
|
+
**Contact & Location:**
|
|
534
|
+
- **parseNANPTel**: Parses a North American phone number into standardized format.
|
|
535
|
+
- **isNANPTel**: Determines if a value is a valid North American phone number.
|
|
536
|
+
- **isEmail**: Determines if a value is a valid email address.
|
|
537
|
+
- **parseZip**: Parses a US zip code into standardized format.
|
|
538
|
+
- **isZip**: Determines if a value is a valid US zip code.
|
|
539
|
+
- **parsePostalCA**: Parses a Canadian postal code into standardized format.
|
|
301
540
|
- **isPostalCA**: Determines if a value is a valid Canadian postal code.
|
|
302
|
-
- **
|
|
303
|
-
- **
|
|
304
|
-
|
|
541
|
+
- **parseUrl**: Parses a URL, adding https:// if missing.
|
|
542
|
+
- **isUrl**: Determines if a value is a valid URL.
|
|
543
|
+
|
|
544
|
+
**Color:**
|
|
545
|
+
- **parseColor**: Parses any CSS color into a normalized format.
|
|
546
|
+
- **isColor**: Determines if a value is a valid CSS color.
|
|
547
|
+
|
|
548
|
+
**Utilities:**
|
|
549
|
+
- **isFormControl**: Determines if an element is an input, select, or textarea.
|
|
550
|
+
- **isType**: Checks if an element's type or data-type matches specified values.
|
|
551
|
+
- **normalizeValidationResult**: Normalizes validation results (boolean/string/object) into a standard format.
|
|
552
|
+
|
|
553
|
+
## Breaking Changes in v2.0.0
|
|
554
|
+
|
|
555
|
+
### Manual Lifecycle Management Required
|
|
556
|
+
|
|
557
|
+
Previously, Validator used MutationObservers to automatically reinitialize when inputs changed and clean up
|
|
558
|
+
when forms were removed. This was inefficient and unreliable, so it has been removed.
|
|
559
|
+
|
|
560
|
+
Now, if you're dynamically changing forms/form elements in a webpage, you must run the following:
|
|
561
|
+
```javascript
|
|
562
|
+
// After dynamically adding/removing inputs:
|
|
563
|
+
validator.init()
|
|
564
|
+
|
|
565
|
+
// Before removing a form from the DOM:
|
|
566
|
+
validator.destroy()
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Event Classes Consolidated
|
|
570
|
+
|
|
571
|
+
The separate `ValidationSuccessEvent` and `ValidationErrorEvent` classes have been replaced with a unified `ValidationEvent` class:
|
|
572
|
+
|
|
573
|
+
```javascript
|
|
574
|
+
// Before (v1.x)
|
|
575
|
+
form.addEventListener('validationSuccess', (e: ValidationSuccessEvent) => { ... })
|
|
576
|
+
|
|
577
|
+
// After (v2.0)
|
|
578
|
+
form.addEventListener('validationSuccess', (e: ValidationEvent) => { ... })
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
The `ValidationEvent` class has a `type` property that is either `'validationSuccess'` or `'validationError'`, and a `submitEvent` property containing the original form submission event.
|
|
582
|
+
|
|
583
|
+
### TypeScript Changes
|
|
584
|
+
|
|
585
|
+
- **`messages` option typing:** Now `Record<string, string>` instead of `object`
|
|
586
|
+
- **`types.d.ts` removed:** Import types directly from the package instead:
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
// Before
|
|
590
|
+
import type { ValidatorOptions } from '@jdlien/validator/types'
|
|
591
|
+
|
|
592
|
+
// After
|
|
593
|
+
import type { ValidatorOptions } from '@jdlien/validator'
|
|
594
|
+
```
|
|
305
595
|
|
|
306
596
|
## Contributing
|
|
307
597
|
|
|
308
598
|
Install dev dependencies:
|
|
309
599
|
|
|
310
600
|
```bash
|
|
311
|
-
|
|
601
|
+
pnpm install
|
|
312
602
|
```
|
|
313
603
|
|
|
314
|
-
|
|
604
|
+
Run tests with coverage (100% required for release):
|
|
315
605
|
|
|
606
|
+
```bash
|
|
607
|
+
pnpm coverage
|
|
316
608
|
```
|
|
317
|
-
Module did not self-register: '...\node_modules\canvas\build\Release\canvas.node'
|
|
318
|
-
```
|
|
319
609
|
|
|
320
|
-
|
|
321
|
-
|
|
610
|
+
Build the project and demo page for testing/release:
|
|
611
|
+
|
|
612
|
+
```bash
|
|
613
|
+
pnpm build
|
|
614
|
+
```
|