vgapp 1.2.4 → 1.2.6
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/CHANGELOG.md +66 -7
- package/README.md +2 -1
- package/agents.md +2 -2
- package/app/modules/base-module.js +87 -10
- package/app/modules/vgalert/js/vgalert.js +133 -202
- package/app/modules/vgalert/readme.md +105 -46
- package/app/modules/vgalert/scss/vgalert.scss +18 -0
- package/app/modules/vgdynamictable/index.js +5 -0
- package/app/modules/vgdynamictable/js/editable.js +438 -0
- package/app/modules/vgdynamictable/js/expandable.js +248 -0
- package/app/modules/vgdynamictable/js/filters.js +450 -0
- package/app/modules/vgdynamictable/js/fixed.js +566 -0
- package/app/modules/vgdynamictable/js/options.js +646 -0
- package/app/modules/vgdynamictable/js/pagination.js +623 -0
- package/app/modules/vgdynamictable/js/search.js +82 -0
- package/app/modules/vgdynamictable/js/skeleton.js +136 -0
- package/app/modules/vgdynamictable/js/sortable.js +442 -0
- package/app/modules/vgdynamictable/js/summary-footer.js +284 -0
- package/app/modules/vgdynamictable/js/table-remote.js +821 -0
- package/app/modules/vgdynamictable/js/table-state.js +243 -0
- package/app/modules/vgdynamictable/js/table-url-state.js +444 -0
- package/app/modules/vgdynamictable/js/utils/common.js +48 -0
- package/app/modules/vgdynamictable/js/vgdynamictable.js +3829 -0
- package/app/modules/vgdynamictable/js/viewport.js +322 -0
- package/app/modules/vgdynamictable/readme.md +251 -0
- package/app/modules/vgdynamictable/scss/_actions.scss +193 -0
- package/app/modules/vgdynamictable/scss/_pagination.scss +183 -0
- package/app/modules/vgdynamictable/scss/_skeleton.scss +60 -0
- package/app/modules/vgdynamictable/scss/_sortable.scss +63 -0
- package/app/modules/vgdynamictable/scss/_table.scss +157 -0
- package/app/modules/vgdynamictable/scss/_variables.scss +130 -0
- package/app/modules/vgdynamictable/scss/vgdynamictable.scss +267 -0
- package/app/modules/vgrangeslider/index.js +3 -0
- package/app/modules/vgrangeslider/js/skins.js +222 -0
- package/app/modules/vgrangeslider/js/vgrangeslider.js +704 -0
- package/app/modules/vgrangeslider/readme.md +523 -0
- package/app/modules/vgrangeslider/scss/_variables.scss +53 -0
- package/app/modules/vgrangeslider/scss/vgrangeslider.scss +240 -0
- package/app/modules/vgtoast/js/vgtoast.js +111 -111
- package/app/modules/vgtooltip/index.js +3 -0
- package/app/modules/vgtooltip/js/vgtooltip.js +493 -0
- package/app/modules/vgtooltip/readme.md +181 -0
- package/app/modules/vgtooltip/scss/_variables.scss +15 -0
- package/app/modules/vgtooltip/scss/vgtooltip.scss +64 -0
- package/app/utils/js/components/ajax.js +116 -7
- package/app/utils/js/components/placement.js +112 -41
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/index.js +20 -17
- package/index.scss +9 -0
- package/package.json +1 -1
|
@@ -3,64 +3,12 @@ import VGModal from "../../vgmodal";
|
|
|
3
3
|
|
|
4
4
|
import { isElement, isVisible, makeRandomString, mergeDeepObject } from "../../../utils/js/functions";
|
|
5
5
|
import { getSVG } from "../../module-fn";
|
|
6
|
-
import {
|
|
6
|
+
import {Classes, Manipulator} from "../../../utils/js/dom/manipulator";
|
|
7
7
|
import Selectors from "../../../utils/js/dom/selectors";
|
|
8
8
|
import EventHandler from "../../../utils/js/dom/event";
|
|
9
9
|
import {lang_buttons, lang_messages} from "../../../utils/js/components/lang";
|
|
10
10
|
import Html from "../../../utils/js/components/templater";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @typedef {Object} AjaxParams
|
|
14
|
-
* @property {string} route - URL-адрес для AJAX-запроса.
|
|
15
|
-
* @property {string} target - Селектор элемента, куда будет вставлен ответ.
|
|
16
|
-
* @property {string} method - HTTP-метод ('get', 'post' и т.д.).
|
|
17
|
-
* @property {boolean} loader - Показывать ли индикатор загрузки.
|
|
18
|
-
* @property {boolean} once - Выполнить запрос только один раз.
|
|
19
|
-
* @property {boolean} output - Выводить ли результат в целевой элемент.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @typedef {Object} ModalParams
|
|
24
|
-
* @property {boolean} centered - Центрировать ли модальное окно по вертикали.
|
|
25
|
-
* @property {boolean|string} backdrop - Фоновая подложка ('static', true, false).
|
|
26
|
-
* @property {boolean} overflow - Разрешить прокрутку фона при открытом окне.
|
|
27
|
-
* @property {boolean} keyboard - Закрывать по нажатию Escape.
|
|
28
|
-
* @property {boolean} dismiss - Закрывать при клике по подложке.
|
|
29
|
-
* @property {Object} animation - Параметры анимации.
|
|
30
|
-
* @property {boolean} animation.enable - Включить анимацию.
|
|
31
|
-
* @property {string} animation.in - Класс анимации входа.
|
|
32
|
-
* @property {string} animation.out - Класс анимации выхода.
|
|
33
|
-
* @property {number} animation.delay - Задержка перед показом (мс).
|
|
34
|
-
* @property {number} animation.duration - Длительность анимации (мс).
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @typedef {Object} ButtonConfig
|
|
39
|
-
* @property {string} [element] - Готовый HTML-элемент кнопки.
|
|
40
|
-
* @property {'button'|'a'} [tag='button'] - Тип элемента.
|
|
41
|
-
* @property {string} [type='button'] - Атрибут type (для <button>).
|
|
42
|
-
* @property {Object.<string, string>} [attr] - Дополнительные атрибуты.
|
|
43
|
-
* @property {string} toggle - Атрибут данных для управления.
|
|
44
|
-
* @property {string[]} class - CSS-классы кнопки.
|
|
45
|
-
* @property {string} text - Текст кнопки.
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @typedef {Object} MessageConfig
|
|
50
|
-
* @property {string} title - Заголовок сообщения.
|
|
51
|
-
* @property {string} description - Описание/текст сообщения.
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @typedef {Object} AlertParams
|
|
56
|
-
* @property {AjaxParams} ajax - Параметры AJAX-запроса.
|
|
57
|
-
* @property {ModalParams} modal - Параметры модального окна.
|
|
58
|
-
* @property {'confirm'|'info'} mode - Режим алерта: подтверждение или информационное.
|
|
59
|
-
* @property {'danger'|'warning'|'success'|'info'} theme - Тема оформления.
|
|
60
|
-
* @property {{agree: ButtonConfig, cancel: ButtonConfig}} buttons - Конфигурация кнопок.
|
|
61
|
-
* @property {MessageConfig} message - Сообщение и заголовок.
|
|
62
|
-
* @property {string} [icon] - SVG-иконка, соответствующая теме.
|
|
63
|
-
*/
|
|
11
|
+
import Params from "../../../utils/js/components/params";
|
|
64
12
|
|
|
65
13
|
/**
|
|
66
14
|
* Константы
|
|
@@ -75,38 +23,14 @@ const NAME_KEY = "vg.alert";
|
|
|
75
23
|
// Глобальная блокировка: предотвращаем открытие нескольких алертов
|
|
76
24
|
let isAlertOpen = false;
|
|
77
25
|
|
|
78
|
-
/**
|
|
79
|
-
* Класс VGAlert — модальное окно подтверждения или информационное уведомление.
|
|
80
|
-
*
|
|
81
|
-
* @class
|
|
82
|
-
* @example
|
|
83
|
-
* VGAlert.call({
|
|
84
|
-
* mode: 'confirm',
|
|
85
|
-
* theme: 'danger',
|
|
86
|
-
* message: {
|
|
87
|
-
* title: 'Вы уверены?',
|
|
88
|
-
* description: 'Это действие нельзя отменить.'
|
|
89
|
-
* },
|
|
90
|
-
* buttons: {
|
|
91
|
-
* agree: { text: 'Удалить', class: ['btn-danger'] },
|
|
92
|
-
* cancel: { text: 'Отмена' }
|
|
93
|
-
* }
|
|
94
|
-
* }).then(() => {
|
|
95
|
-
* console.log('Подтверждено');
|
|
96
|
-
* }).catch(() => {
|
|
97
|
-
* console.log('Отменено');
|
|
98
|
-
* });
|
|
99
|
-
*/
|
|
100
26
|
class VGAlert {
|
|
101
|
-
/**
|
|
102
|
-
* Создаёт экземпляр VGAlert.
|
|
103
|
-
*
|
|
104
|
-
* @param {AlertParams} params - Пользовательские параметры.
|
|
105
|
-
* @param {'ru'|'en'} [lang='ru'] - Язык интерфейса.
|
|
106
|
-
*/
|
|
107
27
|
constructor(params = {}, lang = 'ru') {
|
|
108
28
|
this.lang = lang;
|
|
109
29
|
this._defaultParams = {
|
|
30
|
+
render: {
|
|
31
|
+
type: "modal", // modal or overlay,
|
|
32
|
+
dismiss: false,
|
|
33
|
+
},
|
|
110
34
|
ajax: {
|
|
111
35
|
route: "",
|
|
112
36
|
target: "",
|
|
@@ -169,29 +93,55 @@ class VGAlert {
|
|
|
169
93
|
this._params = this._setParams(params);
|
|
170
94
|
}
|
|
171
95
|
|
|
172
|
-
/**
|
|
173
|
-
* Открывает алерт и возвращает Promise.
|
|
174
|
-
*
|
|
175
|
-
* @static
|
|
176
|
-
* @param {AlertParams} options - Параметры алерта.
|
|
177
|
-
* @param {'ru'|'en'} [lang='ru'] - Язык.
|
|
178
|
-
* @returns {Promise<{accepted: boolean, timestamp: Date}>} Результат взаимодействия.
|
|
179
|
-
* @throws {Error} Если алерт уже открыт.
|
|
180
|
-
*/
|
|
181
96
|
static call(options = {}, lang = 'ru') {
|
|
182
97
|
const context = new VGAlert(options, lang);
|
|
183
98
|
|
|
184
99
|
if (isAlertOpen) return Promise.reject({ accepted: false, reason: lang_messages(context.lang, NAME_KEY).reason });
|
|
185
100
|
isAlertOpen = true;
|
|
186
101
|
|
|
187
|
-
|
|
188
|
-
|
|
102
|
+
const getContainer = () => {
|
|
103
|
+
if (context._params.render.type === "overlay") {
|
|
104
|
+
const overlay = context._buildOverlay();
|
|
105
|
+
return {
|
|
106
|
+
element: overlay.element,
|
|
107
|
+
render: overlay.render,
|
|
108
|
+
type: 'overlay'
|
|
109
|
+
}
|
|
110
|
+
} else if (context._params.render.type === "modal") {
|
|
111
|
+
const modal = context._buildModal();
|
|
112
|
+
return {
|
|
113
|
+
element: modal._element,
|
|
114
|
+
render: modal,
|
|
115
|
+
type: 'modal'
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const {element: container, render, type} = getContainer();
|
|
121
|
+
|
|
122
|
+
if (type === 'modal') {
|
|
123
|
+
render.show();
|
|
124
|
+
}
|
|
189
125
|
|
|
190
|
-
const container = modal._element;
|
|
191
126
|
const agreeBtn = Selectors.find(`[${DATA_AGREE}]`, container);
|
|
192
127
|
const cancelBtn = Selectors.find(`[${DATA_CANCEL}]`, container);
|
|
193
128
|
|
|
194
129
|
return new Promise((resolve, reject) => {
|
|
130
|
+
const closeAlert = (isHide = true) => {
|
|
131
|
+
if (type === 'modal') {
|
|
132
|
+
render.hide();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (type === 'overlay') {
|
|
137
|
+
container.remove();
|
|
138
|
+
|
|
139
|
+
if (context._params.render.dismiss && isHide) {
|
|
140
|
+
render.hide();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
195
145
|
const handleAgree = (e) => {
|
|
196
146
|
e.preventDefault();
|
|
197
147
|
cleanup();
|
|
@@ -199,12 +149,17 @@ class VGAlert {
|
|
|
199
149
|
accepted: true,
|
|
200
150
|
timestamp: new Date(),
|
|
201
151
|
});
|
|
202
|
-
|
|
152
|
+
closeAlert();
|
|
203
153
|
};
|
|
204
154
|
|
|
205
155
|
const handleCancel = (e) => {
|
|
206
156
|
e.preventDefault();
|
|
207
|
-
|
|
157
|
+
cleanup();
|
|
158
|
+
reject({
|
|
159
|
+
accepted: false,
|
|
160
|
+
timestamp: new Date(),
|
|
161
|
+
});
|
|
162
|
+
closeAlert(false);
|
|
208
163
|
};
|
|
209
164
|
|
|
210
165
|
const handleKeydown = (e) => {
|
|
@@ -235,26 +190,21 @@ class VGAlert {
|
|
|
235
190
|
}
|
|
236
191
|
|
|
237
192
|
document.addEventListener("keydown", handleKeydown);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
193
|
+
|
|
194
|
+
if (type === 'modal') {
|
|
195
|
+
container.addEventListener("vg.modal.hide", () => {
|
|
196
|
+
cleanup();
|
|
197
|
+
reject({
|
|
198
|
+
accepted: false,
|
|
199
|
+
timestamp: new Date(),
|
|
200
|
+
});
|
|
201
|
+
}, {once: true});
|
|
202
|
+
}
|
|
245
203
|
|
|
246
204
|
container.focus();
|
|
247
205
|
});
|
|
248
206
|
}
|
|
249
207
|
|
|
250
|
-
/**
|
|
251
|
-
* Инициирует алерт подтверждения на основе DOM-элемента.
|
|
252
|
-
*
|
|
253
|
-
* @static
|
|
254
|
-
* @param {HTMLElement} elem - Элемент, вызвавший алерт.
|
|
255
|
-
* @param {AlertParams} options - Параметры алерта.
|
|
256
|
-
* @returns {void}
|
|
257
|
-
*/
|
|
258
208
|
static confirm(elem, options = {}) {
|
|
259
209
|
let lang = 'ru';
|
|
260
210
|
|
|
@@ -269,13 +219,6 @@ class VGAlert {
|
|
|
269
219
|
instance.run(VGAlert);
|
|
270
220
|
}
|
|
271
221
|
|
|
272
|
-
/**
|
|
273
|
-
* Слияние пользовательских параметров с дефолтными.
|
|
274
|
-
*
|
|
275
|
-
* @private
|
|
276
|
-
* @param {AlertParams} params - Пользовательские параметры.
|
|
277
|
-
* @returns {AlertParams} Полный объект параметров.
|
|
278
|
-
*/
|
|
279
222
|
_setParams(params) {
|
|
280
223
|
const merged = mergeDeepObject(this._defaultParams, params);
|
|
281
224
|
merged.buttons = mergeDeepObject(this._elementsDefault.buttons, merged.buttons);
|
|
@@ -285,68 +228,88 @@ class VGAlert {
|
|
|
285
228
|
return merged;
|
|
286
229
|
}
|
|
287
230
|
|
|
288
|
-
/**
|
|
289
|
-
* Создаёт и возвращает экземпляр модального окна с контентом алерта.
|
|
290
|
-
*
|
|
291
|
-
* @private
|
|
292
|
-
* @returns {VGModal} Экземпляр модального окна.
|
|
293
|
-
*/
|
|
294
231
|
_buildModal() {
|
|
295
|
-
const id = `${CLASS_NAME_ALERT}-${
|
|
296
|
-
const $modal = Selectors.find(`.${CLASS_NAME_ALERT}-modal`);
|
|
297
|
-
if ($modal) $modal.remove();
|
|
232
|
+
const id = `${CLASS_NAME_ALERT}-${makeRandomString()}`;
|
|
298
233
|
|
|
299
|
-
|
|
234
|
+
return VGModal.build(id, this._params.modal, (modal) => {
|
|
235
|
+
modal._element.classList.add(`${CLASS_NAME_ALERT}-modal`);
|
|
236
|
+
const body = Selectors.find(".vg-modal-body", modal._element);
|
|
237
|
+
body.append(this._buildContent());
|
|
238
|
+
});
|
|
239
|
+
}
|
|
300
240
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
element.classList.add(`${CLASS_NAME_ALERT}-modal`);
|
|
304
|
-
element.setAttribute("role", "alertdialog");
|
|
305
|
-
element.setAttribute("aria-modal", "true");
|
|
241
|
+
_buildContent() {
|
|
242
|
+
const html = Html('dom');
|
|
306
243
|
|
|
307
|
-
|
|
308
|
-
if (!$body) return;
|
|
244
|
+
let icon = null;
|
|
309
245
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
246
|
+
if (this._params.icon) {
|
|
247
|
+
icon = html.div(
|
|
248
|
+
{class: `${CLASS_NAME_ALERT}-content--icon`},
|
|
249
|
+
this._params.icon,
|
|
250
|
+
{isHTML: true}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
314
253
|
|
|
315
|
-
|
|
316
|
-
|
|
254
|
+
const buttons = document.createElement("div");
|
|
255
|
+
Classes.add(buttons, "vg-alert-buttons");
|
|
317
256
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
257
|
+
if (this._params.mode === "confirm") {
|
|
258
|
+
this._createButton(buttons, "cancel");
|
|
259
|
+
this._createButton(buttons, "agree");
|
|
260
|
+
}
|
|
322
261
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
262
|
+
if (this._params.mode === "info") {
|
|
263
|
+
this._createButton(buttons, "cancel");
|
|
264
|
+
}
|
|
326
265
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
266
|
+
return html.div(
|
|
267
|
+
{class: `${CLASS_NAME_ALERT}-wrapper ${CLASS_NAME_ALERT}-${this._params.theme}`},
|
|
268
|
+
[
|
|
269
|
+
html.div(
|
|
270
|
+
{class: `${CLASS_NAME_ALERT}-content`},
|
|
271
|
+
[
|
|
272
|
+
icon,
|
|
273
|
+
html.div(
|
|
274
|
+
{class: `${CLASS_NAME_ALERT}-content--message`},
|
|
275
|
+
[
|
|
276
|
+
html.div(
|
|
277
|
+
{class: `${CLASS_NAME_ALERT}-content--title`},
|
|
278
|
+
this._params.message.title
|
|
279
|
+
),
|
|
280
|
+
html.div(
|
|
281
|
+
{class: `${CLASS_NAME_ALERT}-content--description`},
|
|
282
|
+
this._params.message.description
|
|
283
|
+
)
|
|
284
|
+
]
|
|
285
|
+
)
|
|
286
|
+
]
|
|
287
|
+
),
|
|
335
288
|
buttons
|
|
336
|
-
]
|
|
289
|
+
]
|
|
290
|
+
);
|
|
291
|
+
}
|
|
337
292
|
|
|
338
|
-
|
|
339
|
-
|
|
293
|
+
_buildOverlay() {
|
|
294
|
+
let targetContainers = ['.vg-modal', '.vg-sidebar'];
|
|
295
|
+
const containerWrap = this._params.relatedTarget.closest(targetContainers.join(', '));
|
|
296
|
+
|
|
297
|
+
const modal = VGModal.getOrCreateInstance(containerWrap);
|
|
298
|
+
const container = Selectors.find('.vg-modal-content', modal._element) || containerWrap;
|
|
299
|
+
|
|
300
|
+
const overlay = document.createElement('div');
|
|
301
|
+
|
|
302
|
+
overlay.className = `${CLASS_NAME_ALERT}-overlay`;
|
|
303
|
+
overlay.append(this._buildContent());
|
|
304
|
+
|
|
305
|
+
container.append(overlay);
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
element: overlay,
|
|
309
|
+
render: modal,
|
|
310
|
+
};
|
|
340
311
|
}
|
|
341
312
|
|
|
342
|
-
/**
|
|
343
|
-
* Создаёт кнопку и добавляет её в контейнер.
|
|
344
|
-
*
|
|
345
|
-
* @private
|
|
346
|
-
* @param {HTMLElement} container - Родительский элемент.
|
|
347
|
-
* @param {'agree'|'cancel'} key - Ключ кнопки.
|
|
348
|
-
* @returns {void}
|
|
349
|
-
*/
|
|
350
313
|
_createButton(container, key) {
|
|
351
314
|
const button = this._params.buttons[key];
|
|
352
315
|
if (!button || button.element) {
|
|
@@ -385,51 +348,25 @@ const EVENT_KEY_ACCEPT = `${NAME_KEY}.accept`;
|
|
|
385
348
|
const EVENT_KEY_REJECT = `${NAME_KEY}.reject`;
|
|
386
349
|
const EVENT_KEY_FINALLY = `${NAME_KEY}.finally`;
|
|
387
350
|
|
|
388
|
-
/**
|
|
389
|
-
* Класс для работы с алертами по data-атрибутам.
|
|
390
|
-
*
|
|
391
|
-
* @class
|
|
392
|
-
* @extends BaseModule
|
|
393
|
-
* @example
|
|
394
|
-
* <button data-vg-toggle="alert" data-ajax-route="/delete/1">Удалить</button>
|
|
395
|
-
*/
|
|
396
351
|
class VGAlertConfirm extends BaseModule {
|
|
397
|
-
/**
|
|
398
|
-
* Создаёт экземпляр VGAlertConfirm.
|
|
399
|
-
*
|
|
400
|
-
* @param {HTMLElement} element - DOM-элемент.
|
|
401
|
-
* @param {AlertParams} options - Параметры.
|
|
402
|
-
*/
|
|
403
352
|
constructor(element, options = {}) {
|
|
404
353
|
super(element);
|
|
405
354
|
this._params = this._getParams(element, mergeDeepObject({}, options));
|
|
406
355
|
}
|
|
407
356
|
|
|
408
|
-
/**
|
|
409
|
-
* Возвращает имя модуля.
|
|
410
|
-
* @returns {string}
|
|
411
|
-
*/
|
|
412
357
|
static get NAME() {
|
|
413
358
|
return NAME;
|
|
414
359
|
}
|
|
415
360
|
|
|
416
|
-
/**
|
|
417
|
-
* Возвращает ключевое имя с префиксом.
|
|
418
|
-
* @returns {string}
|
|
419
|
-
*/
|
|
420
361
|
static get NAME_KEY() {
|
|
421
362
|
return NAME_KEY;
|
|
422
363
|
}
|
|
423
364
|
|
|
424
|
-
/**
|
|
425
|
-
* Запускает логику алерта: вызывает модальное окно и обрабатывает результат.
|
|
426
|
-
*
|
|
427
|
-
* @param {typeof VGAlert} AlertClass - Класс алерта.
|
|
428
|
-
* @returns {void}
|
|
429
|
-
*/
|
|
430
365
|
run(AlertClass) {
|
|
431
366
|
if (this._params.mode !== "confirm") return;
|
|
432
367
|
|
|
368
|
+
this._params.relatedTarget = this._element;
|
|
369
|
+
|
|
433
370
|
AlertClass.call(this._params)
|
|
434
371
|
.then((resolve) => {
|
|
435
372
|
if (!resolve.accepted) return Promise.reject(resolve);
|
|
@@ -447,12 +384,6 @@ class VGAlertConfirm extends BaseModule {
|
|
|
447
384
|
});
|
|
448
385
|
}
|
|
449
386
|
|
|
450
|
-
/**
|
|
451
|
-
* Выполняет AJAX-запрос после подтверждения.
|
|
452
|
-
*
|
|
453
|
-
* @private
|
|
454
|
-
* @returns {Promise<Object>} Ответ от сервера.
|
|
455
|
-
*/
|
|
456
387
|
_ajax() {
|
|
457
388
|
return new Promise((resolve) => {
|
|
458
389
|
this._route((status, data) => {
|
|
@@ -482,4 +413,4 @@ EventHandler.on(document, EVENT_KEY_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, functi
|
|
|
482
413
|
});
|
|
483
414
|
});
|
|
484
415
|
|
|
485
|
-
export default VGAlert;
|
|
416
|
+
export default VGAlert;
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
- Полная **локализация** (настройка языка)
|
|
12
12
|
- Гибкая **настройка кнопок** и сообщений
|
|
13
13
|
- Поддержка **SVG-иконок** и тем стилей (`danger`, `warning`, `success`, `info`)
|
|
14
|
-
- Работа как через **API**, так и через **`data`-атрибуты**
|
|
15
|
-
- Интеграция с промисами (`Promise`)
|
|
16
|
-
- Защита от **множественных одновременных вызовов**
|
|
17
|
-
- Поддержка **клавиатурных сокращений** (Enter, Escape)
|
|
14
|
+
- Работа как через **API**, так и через **`data`-атрибуты**
|
|
15
|
+
- Интеграция с промисами (`Promise`)
|
|
16
|
+
- Защита от **множественных одновременных вызовов**
|
|
17
|
+
- Поддержка **клавиатурных сокращений** (Enter, Escape)
|
|
18
|
+
- Два режима рендера: обычный **`modal`** и вложенный **`overlay`**
|
|
19
|
+
- Возможность закрывать родительскую модалку/сайдбар через `render.dismiss`
|
|
18
20
|
|
|
19
21
|
---
|
|
20
22
|
|
|
@@ -27,15 +29,45 @@ import VGAlert from "./app/modules/vgalert/js/vgalert.js";
|
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
30
|
-
## 🧩 Режимы работы
|
|
32
|
+
## 🧩 Режимы работы
|
|
31
33
|
|
|
32
34
|
### 1. `confirm` — Подтверждение действия
|
|
33
35
|
Показывает два действия: **Подтвердить** и **Отмена**.
|
|
34
36
|
|
|
35
|
-
### 2. `info` — Информационное сообщение
|
|
36
|
-
Показывает только кнопку **ОК** (или "Продолжить").
|
|
37
|
-
|
|
38
|
-
---
|
|
37
|
+
### 2. `info` — Информационное сообщение
|
|
38
|
+
Показывает только кнопку **ОК** (или "Продолжить").
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🖼 Рендер (`render`)
|
|
43
|
+
|
|
44
|
+
`VGAlert` поддерживает два варианта отображения:
|
|
45
|
+
|
|
46
|
+
| Параметр | Значение | Описание |
|
|
47
|
+
|--------|--------|----------|
|
|
48
|
+
| `render.type` | `modal` | Обычный alert в отдельной модалке |
|
|
49
|
+
| `render.type` | `overlay` | Alert-оверлей внутри текущей `.vg-modal` или `.vg-sidebar` |
|
|
50
|
+
| `render.dismiss` | `true` / `false` | Для `overlay`: после закрытия alert дополнительно закрывает родительский контейнер |
|
|
51
|
+
|
|
52
|
+
### Пример: alert поверх открытой модалки
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
VGAlert.call({
|
|
56
|
+
render: {
|
|
57
|
+
type: "overlay",
|
|
58
|
+
dismiss: true
|
|
59
|
+
},
|
|
60
|
+
relatedTarget: button,
|
|
61
|
+
message: {
|
|
62
|
+
title: "Удалить запись",
|
|
63
|
+
description: "Действие будет выполнено в текущем окне."
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`relatedTarget` нужен для `overlay`, чтобы модуль нашёл ближайшую `.vg-modal` или `.vg-sidebar`, куда надо встроить alert.
|
|
69
|
+
|
|
70
|
+
---
|
|
39
71
|
|
|
40
72
|
## 🎨 Темы (`theme`)
|
|
41
73
|
| Значение | Иконка | Назначение |
|
|
@@ -76,9 +108,9 @@ VGAlert.call({
|
|
|
76
108
|
});
|
|
77
109
|
```
|
|
78
110
|
|
|
79
|
-
### Пример 2: Информационное сообщение
|
|
80
|
-
```js
|
|
81
|
-
VGAlert.call({
|
|
111
|
+
### Пример 2: Информационное сообщение
|
|
112
|
+
```js
|
|
113
|
+
VGAlert.call({
|
|
82
114
|
mode: "info",
|
|
83
115
|
theme: "success",
|
|
84
116
|
message: {
|
|
@@ -91,10 +123,26 @@ VGAlert.call({
|
|
|
91
123
|
class: ["btn-success"]
|
|
92
124
|
}
|
|
93
125
|
}
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Пример 3: Обработка результата через `Promise`
|
|
130
|
+
```js
|
|
131
|
+
VGAlert.call({
|
|
132
|
+
message: {
|
|
133
|
+
title: "Подтвердите действие",
|
|
134
|
+
description: "Продолжить?"
|
|
135
|
+
}
|
|
136
|
+
}).then((result) => {
|
|
137
|
+
console.log(result.accepted); // true
|
|
138
|
+
console.log(result.timestamp);
|
|
139
|
+
}).catch((error) => {
|
|
140
|
+
console.log(error.accepted); // false
|
|
141
|
+
console.log(error.timestamp);
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
98
146
|
|
|
99
147
|
## 🔌 Работа с AJAX
|
|
100
148
|
|
|
@@ -121,24 +169,30 @@ VGAlert.confirm(element, {
|
|
|
121
169
|
|
|
122
170
|
---
|
|
123
171
|
|
|
124
|
-
## 🔔 События
|
|
125
|
-
|
|
126
|
-
Модуль генерирует
|
|
127
|
-
|
|
128
|
-
| Событие | Описание |
|
|
129
|
-
|--------|--------|
|
|
130
|
-
| `vg.alert.accept` | Пользователь подтвердил действие |
|
|
172
|
+
## 🔔 События
|
|
173
|
+
|
|
174
|
+
Модуль генерирует события на элементе-триггере, у которого есть `[data-vg-toggle="alert"]`:
|
|
175
|
+
|
|
176
|
+
| Событие | Описание |
|
|
177
|
+
|--------|--------|
|
|
178
|
+
| `vg.alert.accept` | Пользователь подтвердил действие |
|
|
131
179
|
| `vg.alert.reject` | Пользователь отменил действие |
|
|
132
|
-
| `vg.alert.finally` | Действие завершено (в любом случае) |
|
|
133
|
-
| `vg.alert.loaded` | Получен ответ от сервера (если был AJAX) |
|
|
134
|
-
|
|
135
|
-
```js
|
|
136
|
-
document.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
180
|
+
| `vg.alert.finally` | Действие завершено (в любом случае) |
|
|
181
|
+
| `vg.alert.loaded` | Получен ответ от сервера (если был AJAX) |
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
const buttons = document.querySelectorAll('[data-vg-toggle="alert"]');
|
|
185
|
+
|
|
186
|
+
buttons.forEach((button) => {
|
|
187
|
+
button.addEventListener('vg.alert.accept', function (e) {
|
|
188
|
+
console.log('Подтверждено:', e.vgalert);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Если нужен общий глобальный обработчик, событие можно слушать и на `document`, так как оно всплывает.
|
|
194
|
+
|
|
195
|
+
---
|
|
142
196
|
|
|
143
197
|
## ⌨️ Клавиатурные комбинации
|
|
144
198
|
|
|
@@ -149,12 +203,16 @@ document.addEventListener('vg.alert.accept', function(e) {
|
|
|
149
203
|
|
|
150
204
|
## 🛠️ Конфигурация по умолчанию
|
|
151
205
|
```js
|
|
152
|
-
{
|
|
153
|
-
mode: "confirm",
|
|
154
|
-
theme: "danger",
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
206
|
+
{
|
|
207
|
+
mode: "confirm",
|
|
208
|
+
theme: "danger",
|
|
209
|
+
render: {
|
|
210
|
+
type: "modal",
|
|
211
|
+
dismiss: false
|
|
212
|
+
},
|
|
213
|
+
modal: {
|
|
214
|
+
centered: false,
|
|
215
|
+
backdrop: true,
|
|
158
216
|
keyboard: true,
|
|
159
217
|
dismiss: true
|
|
160
218
|
},
|
|
@@ -191,12 +249,13 @@ VGAlert.call(params, 'en');
|
|
|
191
249
|
|
|
192
250
|
## 🧩 Кастомизация кнопок
|
|
193
251
|
|
|
194
|
-
Поддерживает:
|
|
195
|
-
- `tag: 'button' | 'a'`
|
|
196
|
-
- `type` (для `<button>`)
|
|
197
|
-
- `class` — массив CSS-классов
|
|
198
|
-
- `attr` — любые дополнительные атрибуты
|
|
199
|
-
- `element` — готовый HTML-код кнопки
|
|
252
|
+
Поддерживает:
|
|
253
|
+
- `tag: 'button' | 'a'`
|
|
254
|
+
- `type` (для `<button>`)
|
|
255
|
+
- `class` — массив CSS-классов
|
|
256
|
+
- `attr` — любые дополнительные атрибуты
|
|
257
|
+
- `element` — готовый HTML-код кнопки
|
|
258
|
+
- `toggle` — служебный атрибут кнопки (`data-vg-alert-agree` / `data-vg-alert-cancel`), обычно задаётся модулем автоматически
|
|
200
259
|
|
|
201
260
|
### Пример: кнопка-ссылка
|
|
202
261
|
```js
|
|
@@ -239,4 +298,4 @@ MIT — свободно используйте и модифицируйте.
|
|
|
239
298
|
---
|
|
240
299
|
|
|
241
300
|
> 🚀 Автор: VEGAS STUDIO (vegas-dev.com)
|
|
242
|
-
> 📍 Поддерживается в проектах VEGAS
|
|
301
|
+
> 📍 Поддерживается в проектах VEGAS
|
|
@@ -18,6 +18,24 @@
|
|
|
18
18
|
--vg-modal-margin: 65px !important;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
&-overlay {
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: 100%;
|
|
24
|
+
position: absolute;
|
|
25
|
+
top: 0;
|
|
26
|
+
left: 0;
|
|
27
|
+
background: rgba(0, 0, 0, 0.75);
|
|
28
|
+
|
|
29
|
+
.vg-alert-wrapper {
|
|
30
|
+
background-color: white;
|
|
31
|
+
width: 90%;
|
|
32
|
+
position: absolute;
|
|
33
|
+
left: 50%;
|
|
34
|
+
transform: translateX(-50%);
|
|
35
|
+
top: 1rem;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
21
39
|
&-wrapper {
|
|
22
40
|
@include mix-vars('alert', $alert-map);
|
|
23
41
|
@include mix-alert-color-mode($class: vg-alert);
|