vgapp 1.3.6 → 1.3.8
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.
|
@@ -112,12 +112,22 @@ class VGAlert {
|
|
|
112
112
|
if (isAlertOpen) return Promise.reject({ accepted: false, reason: lang_messages(context.lang, NAME_KEY).reason });
|
|
113
113
|
isAlertOpen = true;
|
|
114
114
|
|
|
115
|
-
const getContainer = () => {
|
|
116
|
-
if (context._params.render.type === "overlay") {
|
|
117
|
-
const overlay = context._buildOverlay();
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
const getContainer = () => {
|
|
116
|
+
if (context._params.render.type === "overlay") {
|
|
117
|
+
const overlay = context._buildOverlay();
|
|
118
|
+
|
|
119
|
+
if (!overlay.element || !overlay.render) {
|
|
120
|
+
const modal = context._buildModal();
|
|
121
|
+
return {
|
|
122
|
+
element: modal._element,
|
|
123
|
+
render: modal,
|
|
124
|
+
type: 'modal'
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
element: overlay.element,
|
|
130
|
+
render: overlay.render,
|
|
121
131
|
type: 'overlay'
|
|
122
132
|
}
|
|
123
133
|
} else if (context._params.render.type === "modal") {
|
|
@@ -239,11 +249,11 @@ class VGAlert {
|
|
|
239
249
|
|
|
240
250
|
this._isDataApiBound = true;
|
|
241
251
|
|
|
242
|
-
EventHandler.on(document, EVENT_KEY_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
|
243
|
-
event.preventDefault();
|
|
244
|
-
const target = event.target;
|
|
245
|
-
|
|
246
|
-
if (!isVisible(target) || !isElement(target)) return;
|
|
252
|
+
EventHandler.on(document, EVENT_KEY_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
const target = event.delegateTarget || this || event.target?.closest(SELECTOR_DATA_TOGGLE) || event.target;
|
|
255
|
+
|
|
256
|
+
if (!isVisible(target) || !isElement(target)) return;
|
|
247
257
|
|
|
248
258
|
VGAlert.confirm(target, {
|
|
249
259
|
buttons: {
|
|
@@ -329,12 +339,22 @@ class VGAlert {
|
|
|
329
339
|
);
|
|
330
340
|
}
|
|
331
341
|
|
|
332
|
-
_buildOverlay() {
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
342
|
+
_buildOverlay() {
|
|
343
|
+
const targetContainers = ['.vg-modal', '.vg-sidebar'];
|
|
344
|
+
const relatedTarget = this._params.relatedTarget;
|
|
345
|
+
const containerWrap = isElement(relatedTarget)
|
|
346
|
+
? relatedTarget.closest(targetContainers.join(', '))
|
|
347
|
+
: null;
|
|
348
|
+
|
|
349
|
+
if (!containerWrap) {
|
|
350
|
+
return {
|
|
351
|
+
element: null,
|
|
352
|
+
render: null,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const modal = VGModal.getOrCreateInstance(containerWrap);
|
|
357
|
+
const container = Selectors.find('.vg-modal-content', modal._element) || containerWrap;
|
|
338
358
|
|
|
339
359
|
const overlay = document.createElement('div');
|
|
340
360
|
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
* callback: {
|
|
25
25
|
* afterSuccess: (form, instance, event, data) => {
|
|
26
26
|
* console.log('Форма успешно отправлена');
|
|
27
|
+
* },
|
|
28
|
+
* afterValidateError: (form, instance, event, errors) => {
|
|
29
|
+
* console.log(errors);
|
|
27
30
|
* }
|
|
28
31
|
* }
|
|
29
32
|
* });
|
|
@@ -162,6 +165,7 @@ class VGFormSender extends BaseModule {
|
|
|
162
165
|
},
|
|
163
166
|
callback: {
|
|
164
167
|
afterInit: noop,
|
|
168
|
+
afterValidateError: noop,
|
|
165
169
|
afterSuccess: noop,
|
|
166
170
|
afterError: noop,
|
|
167
171
|
afterSend: noop,
|
|
@@ -479,6 +483,47 @@ class VGFormSender extends BaseModule {
|
|
|
479
483
|
}
|
|
480
484
|
}
|
|
481
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Возвращает список ошибок нативной валидации формы
|
|
488
|
+
* @returns {Array<Object>}
|
|
489
|
+
* @private
|
|
490
|
+
*/
|
|
491
|
+
_getValidationErrors() {
|
|
492
|
+
return [...this._element.elements]
|
|
493
|
+
.filter((field) => typeof field?.checkValidity === 'function' && !field.checkValidity())
|
|
494
|
+
.map((field) => ({
|
|
495
|
+
element: field,
|
|
496
|
+
name: field.name || '',
|
|
497
|
+
id: field.id || '',
|
|
498
|
+
type: field.type || '',
|
|
499
|
+
value: field.value,
|
|
500
|
+
message: field.validationMessage || '',
|
|
501
|
+
validity: {...field.validity}
|
|
502
|
+
}));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Обрабатывает неуспешную нативную валидацию перед отправкой
|
|
507
|
+
* @param {Event} event
|
|
508
|
+
* @returns {boolean}
|
|
509
|
+
* @private
|
|
510
|
+
*/
|
|
511
|
+
_handleValidateError(event) {
|
|
512
|
+
event.preventDefault();
|
|
513
|
+
event.stopPropagation();
|
|
514
|
+
|
|
515
|
+
this._element.classList.add(this._params.classes.wasValidate);
|
|
516
|
+
|
|
517
|
+
execute(this._params.callback.afterValidateError, [
|
|
518
|
+
this._element,
|
|
519
|
+
this,
|
|
520
|
+
event,
|
|
521
|
+
this._getValidationErrors()
|
|
522
|
+
]);
|
|
523
|
+
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
|
|
482
527
|
/**
|
|
483
528
|
* Отображение алерта в зависимости от типа (modal/collapse)
|
|
484
529
|
* @param {Object|string} data - Данные для отображения
|
|
@@ -602,7 +647,7 @@ class VGFormSender extends BaseModule {
|
|
|
602
647
|
* @private
|
|
603
648
|
*/
|
|
604
649
|
_getNextModalZIndex() {
|
|
605
|
-
const indexes = Selectors.findAll('.modal.show, .vg-modal.show')
|
|
650
|
+
const indexes = Selectors.findAll('.modal.show, .vg-modal.show, .ox-modal.is-open')
|
|
606
651
|
.map((element) => Number.parseInt(window.getComputedStyle(element).zIndex, 10))
|
|
607
652
|
.filter((index) => Number.isFinite(index));
|
|
608
653
|
|
|
@@ -614,6 +659,7 @@ class VGFormSender extends BaseModule {
|
|
|
614
659
|
* @private
|
|
615
660
|
*/
|
|
616
661
|
_closeOpenedModals() {
|
|
662
|
+
// Модалка Bootstrap
|
|
617
663
|
[...document.getElementsByClassName('modal')].forEach((element) => {
|
|
618
664
|
if (element && element.classList.contains('show')) {
|
|
619
665
|
if (typeof bootstrap !== 'undefined' && bootstrap.Modal?.getOrCreateInstance) {
|
|
@@ -625,12 +671,22 @@ class VGFormSender extends BaseModule {
|
|
|
625
671
|
}
|
|
626
672
|
});
|
|
627
673
|
|
|
674
|
+
// Модалка VGApp
|
|
628
675
|
[...document.getElementsByClassName('vg-modal')].forEach((element) => {
|
|
629
676
|
if (element && element.classList.contains('show')) {
|
|
630
677
|
const mVG = VGModal.getOrCreateInstance(element);
|
|
631
678
|
mVG.hide([mVG]);
|
|
632
679
|
}
|
|
633
680
|
});
|
|
681
|
+
|
|
682
|
+
// Модалка OKAUX
|
|
683
|
+
[...document.getElementsByClassName('ox-modal')].forEach((element) => {
|
|
684
|
+
if (element && element.classList.contains('is-open')) {
|
|
685
|
+
okaux.Modal.getOpenInstances().forEach((instance) => {
|
|
686
|
+
instance.hide();
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
});
|
|
634
690
|
}
|
|
635
691
|
|
|
636
692
|
/**
|
|
@@ -891,12 +947,7 @@ EventHandler.on(document, EVENT_SUBMIT_DATA_API, function (event) {
|
|
|
891
947
|
|
|
892
948
|
if (instance._params.validate) {
|
|
893
949
|
if (!instance._element.checkValidity()) {
|
|
894
|
-
|
|
895
|
-
event.stopPropagation();
|
|
896
|
-
|
|
897
|
-
instance._element.classList.add(instance._params.classes.wasValidate);
|
|
898
|
-
|
|
899
|
-
return false;
|
|
950
|
+
return instance._handleValidateError(event);
|
|
900
951
|
}
|
|
901
952
|
}
|
|
902
953
|
|
|
@@ -43,10 +43,13 @@ VGFormSender.init(document.getElementById('contactForm'), {
|
|
|
43
43
|
enabled: true,
|
|
44
44
|
delay: 5000 // ожидание открытия, через 5 секунд
|
|
45
45
|
},
|
|
46
|
-
callback: {
|
|
47
|
-
|
|
48
|
-
console.log('
|
|
49
|
-
},
|
|
46
|
+
callback: {
|
|
47
|
+
afterValidateError: (form, instance, event, errors) => {
|
|
48
|
+
console.log('Ошибки валидации:', errors);
|
|
49
|
+
},
|
|
50
|
+
afterSuccess: (form, instance, event, data) => {
|
|
51
|
+
console.log('Форма отправлена!', data);
|
|
52
|
+
},
|
|
50
53
|
afterError: (form, instance, event, data) => {
|
|
51
54
|
console.error('Ошибка:', data);
|
|
52
55
|
}
|
|
@@ -94,12 +97,40 @@ VGFormSender.init(document.getElementById('contactForm'), {
|
|
|
94
97
|
| `interceptors.beforeSend` | `Function` | `Promise.resolve()` | Выполняется перед отправкой |
|
|
95
98
|
| `interceptors.success` | `Function\|false` | `false` | Кастомная обработка успеха |
|
|
96
99
|
| `interceptors.error` | `Function\|false` | `false` | Кастомная обработка ошибки |
|
|
97
|
-
| `callback.afterInit` | `Function` | `noop` | После инициализации |
|
|
98
|
-
| `callback.
|
|
99
|
-
| `callback.
|
|
100
|
-
| `callback.
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
| `callback.afterInit` | `Function` | `noop` | После инициализации |
|
|
101
|
+
| `callback.afterValidateError` | `Function` | `noop` | После провала нативной HTML5-валидации, до отправки формы |
|
|
102
|
+
| `callback.afterSuccess` | `Function` | `noop` | После успеха |
|
|
103
|
+
| `callback.afterError` | `Function` | `noop` | После ошибки |
|
|
104
|
+
| `callback.afterSend` | `Function` | `noop` | После любого ответа |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Проверка валидации до отправки
|
|
109
|
+
|
|
110
|
+
Если включён `validate: true`, модуль сначала вызывает нативный `checkValidity()` у формы. Если форма невалидна, отправка отменяется, форме добавляется класс `was-validated`, а затем вызывается `callback.afterValidateError`.
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
VGFormSender.init(document.getElementById('contactForm'), {
|
|
114
|
+
validate: true,
|
|
115
|
+
callback: {
|
|
116
|
+
afterValidateError: (form, instance, event, errors) => {
|
|
117
|
+
errors.forEach((error) => {
|
|
118
|
+
console.log(error.name, error.message);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Каждый элемент массива `errors` содержит:
|
|
126
|
+
|
|
127
|
+
- `element` — ссылку на невалидное поле
|
|
128
|
+
- `name` / `id` / `type`
|
|
129
|
+
- `value` — текущее значение поля
|
|
130
|
+
- `message` — текст из `validationMessage`
|
|
131
|
+
- `validity` — слепок объекта `ValidityState`
|
|
132
|
+
|
|
133
|
+
---
|
|
103
134
|
|
|
104
135
|
## 🔔 События
|
|
105
136
|
|