@kupola/kupola 1.2.0 → 1.4.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 +21 -0
- package/README.md +330 -286
- package/adapters/axios.d.ts +34 -0
- package/adapters/axios.js +122 -0
- package/adapters/navios-http.d.ts +110 -0
- package/adapters/navios-http.js +151 -0
- package/css/components-ext.css +157 -0
- package/css/components.css +69 -0
- package/css/theme-dark.css +5 -5
- package/css/utilities.css +119 -1
- package/dist/css/accessibility.css +119 -0
- package/dist/css/animations.css +224 -0
- package/dist/css/brand-themes.css +300 -0
- package/dist/css/colors_and_type.css +441 -0
- package/dist/css/components-ext.css +4165 -0
- package/dist/css/components.css +1483 -0
- package/dist/css/kupola.css +1 -12
- package/dist/css/kupola.min.css +1 -0
- package/dist/css/responsive.css +697 -0
- package/dist/css/scaffold.css +145 -0
- package/dist/css/states.css +316 -0
- package/dist/css/theme-dark.css +296 -0
- package/dist/css/theme-light.css +296 -0
- package/dist/css/utilities.css +171 -0
- package/dist/icons.svg +284 -0
- package/dist/kupola.cjs.js +17409 -257
- package/dist/kupola.cjs.js.map +1 -1
- package/dist/kupola.css +9000 -0
- package/dist/kupola.esm.js +17183 -7597
- package/dist/kupola.esm.js.map +1 -1
- package/dist/kupola.min.css +1 -0
- package/dist/kupola.min.js +2 -0
- package/dist/kupola.min.js.map +1 -0
- package/dist/kupola.umd.js +17415 -257
- package/dist/kupola.umd.js.map +1 -1
- package/dist/plugins/vite-plugin-kupola.js +120 -0
- package/dist/types/kupola.d.ts +421 -323
- package/js/calendar.js +334 -25
- package/js/carousel.js +182 -48
- package/js/collapse.js +148 -34
- package/js/color-picker.js +416 -108
- package/js/component.js +8 -19
- package/js/countdown.js +9 -8
- package/js/data-bind.js +73 -16
- package/js/datepicker.js +488 -110
- package/js/depends.js +710 -0
- package/js/dialog.js +4 -2
- package/js/drawer.js +172 -8
- package/js/dropdown.js +272 -17
- package/js/dynamic-tags.js +156 -40
- package/js/fileupload.js +9 -8
- package/js/form.js +280 -254
- package/js/global-events.js +281 -188
- package/js/heatmap.js +10 -7
- package/js/i18n.js +18 -10
- package/js/icons.js +141 -161
- package/js/image-preview.js +146 -2
- package/js/initializer.js +151 -71
- package/js/kupola-core.js +123 -45
- package/js/kupola-lifecycle.js +13 -11
- package/js/message.js +8 -1
- package/js/modal.js +207 -59
- package/js/notification.js +8 -1
- package/js/numberinput.js +9 -8
- package/js/pagination.js +263 -0
- package/js/registry.js +29 -12
- package/js/select.js +482 -27
- package/js/slide-captcha.js +11 -2
- package/js/slider.js +442 -25
- package/js/statcard.js +9 -7
- package/js/table.js +1210 -0
- package/js/tag.js +268 -14
- package/js/theme-standalone.js +88 -0
- package/js/theme.js +14 -43
- package/js/timepicker.js +335 -66
- package/js/tooltip.js +317 -86
- package/js/utils.js +6 -2
- package/js/validation.js +6 -2
- package/js/virtual-list.js +11 -7
- package/js/web-components.js +288 -0
- package/package.json +81 -67
- package/plugins/vite-plugin-kupola.js +120 -0
- package/scripts/build-css.cjs +113 -0
- package/scripts/build-svg-sprite.cjs +107 -0
- package/types/kupola.d.ts +421 -323
- package/CHANGELOG.md +0 -130
- package/INTEGRATION.md +0 -440
- package/PROJECT_SUMMARY.md +0 -312
- package/SKILL.md +0 -572
- package/dist/utils/utils/Kupola.cs +0 -77
- package/dist/utils/utils/Kupola.java +0 -104
- package/dist/utils/utils/kupola.go +0 -120
- package/dist/utils/utils/kupola.js +0 -63
- package/dist/utils/utils/kupola.py +0 -1392
- package/dist/utils/utils/kupola.rb +0 -69
- package/js/composition-api.js +0 -458
- package/js/error-handler.js +0 -181
- package/js/http.js +0 -419
- package/js/kupola-devtools.js +0 -598
- package/js/performance.js +0 -250
- package/js/router.js +0 -396
- package/js/security.js +0 -189
- package/js/test-utils.js +0 -251
- package/templates/base.html +0 -30
- package/templates/base_dashboard.html +0 -99
- package/utils/Kupola.cs +0 -77
- package/utils/Kupola.java +0 -104
- package/utils/kupola.go +0 -120
- package/utils/kupola.js +0 -63
- package/utils/kupola.py +0 -1392
- package/utils/kupola.rb +0 -69
package/js/form.js
CHANGED
|
@@ -1,291 +1,317 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
validateOnSubmit: true,
|
|
10
|
-
validateOnChange: false,
|
|
11
|
-
validateOnBlur: false,
|
|
12
|
-
preventDefault: true,
|
|
13
|
-
...options
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
this.submitHandlers = [];
|
|
17
|
-
this.isSubmitting = false;
|
|
18
|
-
this.errors = {};
|
|
19
|
-
this.rules = {};
|
|
20
|
-
this.validator = window.kupolaValidator || new window.KupolaValidator();
|
|
21
|
-
|
|
22
|
-
if (!this.form || !(this.form instanceof HTMLFormElement)) {
|
|
23
|
-
console.warn('[KupolaForm] Invalid form element');
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
this._init();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
_init() {
|
|
31
|
-
if (this.options.validateOnChange) {
|
|
32
|
-
this.form.addEventListener('input', (e) => {
|
|
33
|
-
this._validateField(e.target);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
1
|
+
class KupolaForm {
|
|
2
|
+
constructor(formElement) {
|
|
3
|
+
this.form = formElement;
|
|
4
|
+
this.fields = [];
|
|
5
|
+
this.validators = {};
|
|
6
|
+
this.errorMessages = {};
|
|
7
|
+
this._init();
|
|
8
|
+
}
|
|
36
9
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}, true);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
10
|
+
_init() {
|
|
11
|
+
this._setupValidators();
|
|
12
|
+
this._collectFields();
|
|
13
|
+
this._bindEvents();
|
|
14
|
+
}
|
|
45
15
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
16
|
+
_setupValidators() {
|
|
17
|
+
this.validators = {
|
|
18
|
+
required: (value) => {
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
return value.trim() !== '';
|
|
50
21
|
}
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
if (this.options.validateOnSubmit) {
|
|
56
|
-
const validation = await this.validate();
|
|
57
|
-
if (!validation.valid) {
|
|
58
|
-
this._showErrors(validation.errors);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const result = handler(e);
|
|
64
|
-
if (result instanceof Promise) {
|
|
65
|
-
await result;
|
|
66
|
-
}
|
|
67
|
-
} finally {
|
|
68
|
-
this.isSubmitting = false;
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
return value.length > 0;
|
|
69
24
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
25
|
+
return value !== null && value !== undefined;
|
|
26
|
+
},
|
|
27
|
+
email: (value) => {
|
|
28
|
+
if (!value) return true;
|
|
29
|
+
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
30
|
+
return regex.test(value);
|
|
31
|
+
},
|
|
32
|
+
phone: (value) => {
|
|
33
|
+
if (!value) return true;
|
|
34
|
+
const regex = /^1[3-9]\d{9}$/;
|
|
35
|
+
return regex.test(value);
|
|
36
|
+
},
|
|
37
|
+
url: (value) => {
|
|
38
|
+
if (!value) return true;
|
|
39
|
+
try {
|
|
40
|
+
new URL(value);
|
|
41
|
+
return true;
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
80
44
|
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return
|
|
45
|
+
},
|
|
46
|
+
number: (value) => {
|
|
47
|
+
if (!value) return true;
|
|
48
|
+
return !isNaN(parseFloat(value)) && isFinite(value);
|
|
49
|
+
},
|
|
50
|
+
minlength: (value, min) => {
|
|
51
|
+
if (!value) return true;
|
|
52
|
+
return value.length >= parseInt(min);
|
|
53
|
+
},
|
|
54
|
+
maxlength: (value, max) => {
|
|
55
|
+
if (!value) return true;
|
|
56
|
+
return value.length <= parseInt(max);
|
|
57
|
+
},
|
|
58
|
+
min: (value, min) => {
|
|
59
|
+
if (!value) return true;
|
|
60
|
+
return parseFloat(value) >= parseFloat(min);
|
|
61
|
+
},
|
|
62
|
+
max: (value, max) => {
|
|
63
|
+
if (!value) return true;
|
|
64
|
+
return parseFloat(value) <= parseFloat(max);
|
|
65
|
+
},
|
|
66
|
+
pattern: (value, pattern) => {
|
|
67
|
+
if (!value) return true;
|
|
68
|
+
const regex = new RegExp(pattern);
|
|
69
|
+
return regex.test(value);
|
|
70
|
+
},
|
|
71
|
+
equalTo: (value, targetId) => {
|
|
72
|
+
const target = document.getElementById(targetId);
|
|
73
|
+
if (!target) return true;
|
|
74
|
+
return value === target.value;
|
|
104
75
|
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
this.errorMessages = {
|
|
79
|
+
required: '该字段为必填项',
|
|
80
|
+
email: '请输入有效的邮箱地址',
|
|
81
|
+
phone: '请输入有效的手机号码',
|
|
82
|
+
url: '请输入有效的URL地址',
|
|
83
|
+
number: '请输入有效的数字',
|
|
84
|
+
minlength: (param) => `至少需要${param}个字符`,
|
|
85
|
+
maxlength: (param) => `最多允许${param}个字符`,
|
|
86
|
+
min: (param) => `最小值为${param}`,
|
|
87
|
+
max: (param) => `最大值为${param}`,
|
|
88
|
+
pattern: '格式不正确',
|
|
89
|
+
equalTo: '两次输入不一致'
|
|
90
|
+
};
|
|
91
|
+
}
|
|
105
92
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} else {
|
|
115
|
-
parts.push(rule);
|
|
116
|
-
}
|
|
117
|
-
} else if (typeof config === 'number' || typeof config === 'string') {
|
|
118
|
-
parts.push(`${rule}:${config}`);
|
|
119
|
-
} else if (config === true) {
|
|
120
|
-
parts.push(rule);
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
return parts.join('|');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async validate(fields = null) {
|
|
127
|
-
this.errors = {};
|
|
128
|
-
const allErrors = [];
|
|
93
|
+
_collectFields() {
|
|
94
|
+
const inputs = this.form.querySelectorAll('input, select, textarea');
|
|
95
|
+
inputs.forEach(input => {
|
|
96
|
+
if (!input.hasAttribute('data-kupola-ignore')) {
|
|
97
|
+
this.fields.push(input);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
129
101
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
102
|
+
_bindEvents() {
|
|
103
|
+
this.form.addEventListener('submit', (e) => {
|
|
104
|
+
if (!this.validate()) {
|
|
105
|
+
e.preventDefault();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
133
108
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
109
|
+
this.fields.forEach(field => {
|
|
110
|
+
field.addEventListener('blur', () => this.validateField(field));
|
|
111
|
+
field.addEventListener('input', () => this.clearError(field));
|
|
112
|
+
});
|
|
113
|
+
}
|
|
137
114
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
115
|
+
validate() {
|
|
116
|
+
let isValid = true;
|
|
117
|
+
this.fields.forEach(field => {
|
|
118
|
+
if (!this.validateField(field)) {
|
|
119
|
+
isValid = false;
|
|
143
120
|
}
|
|
121
|
+
});
|
|
122
|
+
return isValid;
|
|
123
|
+
}
|
|
144
124
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
125
|
+
validateField(field) {
|
|
126
|
+
const errors = this._getFieldErrors(field);
|
|
127
|
+
|
|
128
|
+
if (errors.length > 0) {
|
|
129
|
+
this.showError(field, errors[0]);
|
|
130
|
+
return false;
|
|
150
131
|
}
|
|
132
|
+
|
|
133
|
+
this.clearError(field);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
151
136
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return [message];
|
|
137
|
+
_getFieldErrors(field) {
|
|
138
|
+
const errors = [];
|
|
139
|
+
const value = this._getFieldValue(field);
|
|
140
|
+
|
|
141
|
+
for (const [validatorName, validator] of Object.entries(this.validators)) {
|
|
142
|
+
const attrValue = field.getAttribute(`data-${validatorName}`);
|
|
143
|
+
if (attrValue !== null) {
|
|
144
|
+
const isValid = validator(value, attrValue);
|
|
145
|
+
if (!isValid) {
|
|
146
|
+
let message = this.errorMessages[validatorName];
|
|
147
|
+
if (typeof message === 'function') {
|
|
148
|
+
message = message(attrValue);
|
|
165
149
|
}
|
|
166
|
-
|
|
167
|
-
const displayName = input.getAttribute('data-label') || input.getAttribute('placeholder') || name;
|
|
168
|
-
const message = typeof result === 'string' ? result : `${displayName} 验证失败`;
|
|
169
|
-
this.validator.showError(input, message);
|
|
170
|
-
return [message];
|
|
150
|
+
errors.push(message);
|
|
171
151
|
}
|
|
172
|
-
this.validator.clearError(input);
|
|
173
|
-
return [];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const isValid = await this.validator.validateInputAsync(input);
|
|
177
|
-
if (!isValid) {
|
|
178
|
-
const errorElement = input.parentElement?.querySelector('.ds-input__error');
|
|
179
|
-
return errorElement ? [errorElement.textContent] : ['Validation failed'];
|
|
180
152
|
}
|
|
181
|
-
return [];
|
|
182
153
|
}
|
|
154
|
+
|
|
155
|
+
return errors;
|
|
156
|
+
}
|
|
183
157
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
158
|
+
_getFieldValue(field) {
|
|
159
|
+
const type = field.type;
|
|
160
|
+
|
|
161
|
+
if (type === 'checkbox') {
|
|
162
|
+
return field.checked;
|
|
190
163
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
inputs.forEach(input => {
|
|
197
|
-
const name = input.name;
|
|
198
|
-
if (!name) return;
|
|
199
|
-
|
|
200
|
-
if (input.type === 'checkbox') {
|
|
201
|
-
if (!values[name]) {
|
|
202
|
-
values[name] = [];
|
|
203
|
-
}
|
|
204
|
-
if (input.checked) {
|
|
205
|
-
values[name].push(input.value);
|
|
206
|
-
}
|
|
207
|
-
} else if (input.type === 'radio') {
|
|
208
|
-
if (input.checked) {
|
|
209
|
-
values[name] = input.value;
|
|
210
|
-
}
|
|
211
|
-
} else if (input.type === 'file') {
|
|
212
|
-
values[name] = input.files;
|
|
213
|
-
} else {
|
|
214
|
-
values[name] = input.value;
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
return values;
|
|
164
|
+
|
|
165
|
+
if (type === 'radio') {
|
|
166
|
+
const name = field.name;
|
|
167
|
+
const checked = this.form.querySelector(`input[name="${name}"]:checked`);
|
|
168
|
+
return checked ? checked.value : null;
|
|
219
169
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const input = this.form.querySelector(`[name="${key}"]`);
|
|
224
|
-
if (!input) return;
|
|
225
|
-
|
|
226
|
-
if (input.type === 'checkbox') {
|
|
227
|
-
const valuesArray = Array.isArray(values[key]) ? values[key] : [values[key]];
|
|
228
|
-
input.checked = valuesArray.includes(input.value);
|
|
229
|
-
} else if (input.type === 'radio') {
|
|
230
|
-
const radio = this.form.querySelector(`[name="${key}"][value="${values[key]}"]`);
|
|
231
|
-
if (radio) radio.checked = true;
|
|
232
|
-
} else if (input.type === 'file') {
|
|
233
|
-
const dataTransfer = new DataTransfer();
|
|
234
|
-
if (values[key] instanceof FileList) {
|
|
235
|
-
Array.from(values[key]).forEach(file => {
|
|
236
|
-
dataTransfer.items.add(file);
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
input.files = dataTransfer.files;
|
|
240
|
-
} else {
|
|
241
|
-
input.value = values[key];
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
return this;
|
|
170
|
+
|
|
171
|
+
if (type === 'select-multiple') {
|
|
172
|
+
return Array.from(field.selectedOptions).map(option => option.value);
|
|
245
173
|
}
|
|
174
|
+
|
|
175
|
+
return field.value;
|
|
176
|
+
}
|
|
246
177
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
178
|
+
showError(field, message) {
|
|
179
|
+
this.clearError(field);
|
|
180
|
+
|
|
181
|
+
const errorElement = document.createElement('span');
|
|
182
|
+
errorElement.className = 'ds-form-error';
|
|
183
|
+
errorElement.textContent = message;
|
|
184
|
+
|
|
185
|
+
field.classList.add('ds-form-field--error');
|
|
186
|
+
|
|
187
|
+
const container = field.parentElement;
|
|
188
|
+
if (container.classList.contains('ds-form-field')) {
|
|
189
|
+
container.appendChild(errorElement);
|
|
190
|
+
} else {
|
|
191
|
+
field.parentNode.insertBefore(errorElement, field.nextSibling);
|
|
252
192
|
}
|
|
193
|
+
}
|
|
253
194
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
195
|
+
clearError(field) {
|
|
196
|
+
field.classList.remove('ds-form-field--error');
|
|
197
|
+
|
|
198
|
+
const errorElement = field.parentElement.querySelector('.ds-form-error');
|
|
199
|
+
if (errorElement) {
|
|
200
|
+
errorElement.remove();
|
|
260
201
|
}
|
|
202
|
+
}
|
|
261
203
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
204
|
+
addValidator(name, validator, message) {
|
|
205
|
+
this.validators[name] = validator;
|
|
206
|
+
this.errorMessages[name] = message;
|
|
207
|
+
}
|
|
265
208
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
209
|
+
getData() {
|
|
210
|
+
const data = {};
|
|
211
|
+
|
|
212
|
+
this.fields.forEach(field => {
|
|
213
|
+
const name = field.name;
|
|
214
|
+
if (!name) return;
|
|
215
|
+
|
|
216
|
+
const value = this._getFieldValue(field);
|
|
217
|
+
|
|
218
|
+
if (field.type === 'checkbox') {
|
|
219
|
+
if (!data[name]) {
|
|
220
|
+
data[name] = [];
|
|
221
|
+
}
|
|
222
|
+
if (field.checked) {
|
|
223
|
+
data[name].push(field.value);
|
|
224
|
+
}
|
|
225
|
+
} else if (field.type === 'radio') {
|
|
226
|
+
if (!data[name] && field.checked) {
|
|
227
|
+
data[name] = field.value;
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
data[name] = value;
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return data;
|
|
235
|
+
}
|
|
269
236
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
237
|
+
setData(data) {
|
|
238
|
+
Object.keys(data).forEach(name => {
|
|
239
|
+
const fields = this.form.querySelectorAll(`[name="${name}"]`);
|
|
240
|
+
|
|
241
|
+
fields.forEach(field => {
|
|
242
|
+
const type = field.type;
|
|
243
|
+
|
|
244
|
+
if (type === 'checkbox') {
|
|
245
|
+
const values = Array.isArray(data[name]) ? data[name] : [data[name]];
|
|
246
|
+
field.checked = values.includes(field.value);
|
|
247
|
+
} else if (type === 'radio') {
|
|
248
|
+
field.checked = field.value === data[name];
|
|
249
|
+
} else if (type === 'select-multiple') {
|
|
250
|
+
const values = Array.isArray(data[name]) ? data[name] : [data[name]];
|
|
251
|
+
Array.from(field.options).forEach(option => {
|
|
252
|
+
option.selected = values.includes(option.value);
|
|
253
|
+
});
|
|
254
|
+
} else {
|
|
255
|
+
field.value = data[name] || '';
|
|
256
|
+
}
|
|
273
257
|
});
|
|
274
|
-
|
|
275
|
-
this.errors = {};
|
|
276
|
-
this.rules = {};
|
|
277
|
-
}
|
|
258
|
+
});
|
|
278
259
|
}
|
|
279
260
|
|
|
280
|
-
|
|
281
|
-
|
|
261
|
+
reset() {
|
|
262
|
+
this.form.reset();
|
|
263
|
+
this.fields.forEach(field => this.clearError(field));
|
|
282
264
|
}
|
|
283
265
|
|
|
284
|
-
|
|
285
|
-
|
|
266
|
+
destroy() {
|
|
267
|
+
this.fields.forEach(field => {
|
|
268
|
+
field.removeEventListener('blur', () => this.validateField(field));
|
|
269
|
+
field.removeEventListener('input', () => this.clearError(field));
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
this.form.removeEventListener('submit', () => {});
|
|
273
|
+
|
|
274
|
+
this.fields = null;
|
|
275
|
+
this.validators = null;
|
|
276
|
+
this.errorMessages = null;
|
|
277
|
+
this.form = null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function initFormValidation(formSelector) {
|
|
282
|
+
const forms = document.querySelectorAll(formSelector || '.ds-form');
|
|
283
|
+
|
|
284
|
+
forms.forEach(form => {
|
|
285
|
+
if (form._kupolaForm) return;
|
|
286
|
+
|
|
287
|
+
const instance = new KupolaForm(form);
|
|
288
|
+
form._kupolaForm = instance;
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
return forms.length;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function getFormInstance(formElement) {
|
|
295
|
+
return formElement._kupolaForm;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function validateForm(formElement) {
|
|
299
|
+
const instance = formElement._kupolaForm;
|
|
300
|
+
if (instance) {
|
|
301
|
+
return instance.validate();
|
|
286
302
|
}
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
287
305
|
|
|
306
|
+
export { KupolaForm, initFormValidation, getFormInstance, validateForm };
|
|
307
|
+
|
|
308
|
+
if (typeof window !== 'undefined') {
|
|
288
309
|
window.KupolaForm = KupolaForm;
|
|
289
|
-
window.
|
|
290
|
-
window.
|
|
291
|
-
|
|
310
|
+
window.initFormValidation = initFormValidation;
|
|
311
|
+
window.getFormInstance = getFormInstance;
|
|
312
|
+
window.validateForm = validateForm;
|
|
313
|
+
|
|
314
|
+
if (window.kupolaInitializer) {
|
|
315
|
+
window.kupolaInitializer.register('form-validation', initFormValidation);
|
|
316
|
+
}
|
|
317
|
+
}
|