vgapp 1.3.5 → 1.3.7
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
|
|
|
@@ -21,13 +21,16 @@
|
|
|
21
21
|
* type: 'modal',
|
|
22
22
|
* enabled: true
|
|
23
23
|
* },
|
|
24
|
-
* callback: {
|
|
25
|
-
* afterSuccess: (form, instance, event, data) => {
|
|
26
|
-
* console.log('Форма успешно отправлена');
|
|
27
|
-
* }
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
24
|
+
* callback: {
|
|
25
|
+
* afterSuccess: (form, instance, event, data) => {
|
|
26
|
+
* console.log('Форма успешно отправлена');
|
|
27
|
+
* },
|
|
28
|
+
* afterValidateError: (form, instance, event, errors) => {
|
|
29
|
+
* console.log(errors);
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
31
34
|
|
|
32
35
|
import BaseModule from "../../base-module";
|
|
33
36
|
import VGModal from "../../vgmodal/js/vgmodal";
|
|
@@ -160,12 +163,13 @@ class VGFormSender extends BaseModule {
|
|
|
160
163
|
wasValidate: 'was-validated',
|
|
161
164
|
content: 'vg-form-sender--content'
|
|
162
165
|
},
|
|
163
|
-
callback: {
|
|
164
|
-
afterInit: noop,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
callback: {
|
|
167
|
+
afterInit: noop,
|
|
168
|
+
afterValidateError: noop,
|
|
169
|
+
afterSuccess: noop,
|
|
170
|
+
afterError: noop,
|
|
171
|
+
afterSend: noop,
|
|
172
|
+
},
|
|
169
173
|
interceptors: {
|
|
170
174
|
beforeSend: () => new Promise((resolve, reject) => resolve()),
|
|
171
175
|
success: false,
|
|
@@ -469,18 +473,59 @@ class VGFormSender extends BaseModule {
|
|
|
469
473
|
* @param {'success'|'error'} status - Статус ответа
|
|
470
474
|
* @private
|
|
471
475
|
*/
|
|
472
|
-
_jsonParse(data, status) {
|
|
473
|
-
const _this = this;
|
|
476
|
+
_jsonParse(data, status) {
|
|
477
|
+
const _this = this;
|
|
474
478
|
|
|
475
479
|
if (_this._params.isJsonParse) {
|
|
476
480
|
_this.alert(normalizeData(data), status);
|
|
477
481
|
} else {
|
|
478
482
|
_this.alert(data, status);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
*
|
|
483
|
+
}
|
|
484
|
+
}
|
|
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
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Отображение алерта в зависимости от типа (modal/collapse)
|
|
484
529
|
* @param {Object|string} data - Данные для отображения
|
|
485
530
|
* @param {string} status - Статус: success, error, danger и т.д.
|
|
486
531
|
*/
|
|
@@ -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,21 @@ 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
|
+
const mOX = okaux.Modal.getOrCreateInstance(element);
|
|
686
|
+
mOX.hide();
|
|
687
|
+
}
|
|
688
|
+
});
|
|
634
689
|
}
|
|
635
690
|
|
|
636
691
|
/**
|
|
@@ -889,16 +944,11 @@ EventHandler.on(document, EVENT_SUBMIT_DATA_API, function (event) {
|
|
|
889
944
|
return;
|
|
890
945
|
}
|
|
891
946
|
|
|
892
|
-
if (instance._params.validate) {
|
|
893
|
-
if (!instance._element.checkValidity()) {
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
instance._element.classList.add(instance._params.classes.wasValidate);
|
|
898
|
-
|
|
899
|
-
return false;
|
|
900
|
-
}
|
|
901
|
-
}
|
|
947
|
+
if (instance._params.validate) {
|
|
948
|
+
if (!instance._element.checkValidity()) {
|
|
949
|
+
return instance._handleValidateError(event);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
902
952
|
|
|
903
953
|
if (!instance._params.submit) {
|
|
904
954
|
event.preventDefault();
|
|
@@ -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
|
|