vgapp 0.6.8 → 0.7.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/CHANGELOG.md +13 -0
- package/app/modules/base-module.js +22 -20
- package/app/modules/vgformsender/js/vgformsender.js +53 -61
- package/app/modules/vgmodal/js/vgmodal.js +11 -16
- package/app/modules/vgsidebar/js/vgsidebar.js +10 -9
- package/app/utils/js/components/params.js +20 -14
- package/app/utils/js/functions.js +16 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
# VEGAS-APP 0.6.9 - 0.7.0 (Ноябрь, 21, 2025)
|
|
2
|
+
* Изменения коснулись модуля vgformsender в частности кнопку submit, дата атрибуты можно вешать на нее или на саму форму
|
|
3
|
+
1. Опциональное состояние кнопки(submit) data-button-enabled="false" - никаких действий с текстом кнопки не будет
|
|
4
|
+
2. data-button-disabled - по умолчанию `true`, блокирует кнопку при отправке
|
|
5
|
+
3. data-button-spinner-enabled - по умолчанию `false`, добавляет спиннер загрузки в кнопку
|
|
6
|
+
4. data-button-spinner-element - добавит код по умолчанию `<span class="spinner-border spinner-border-sm me-2"></span>`, можно придумать свой
|
|
7
|
+
5. data-button-initial - можно вписать текст, или он сам возьмет содержимое кнопки.
|
|
8
|
+
6. data-button-send - текст во время отправки, по умолчанию `Отправляем...`
|
|
9
|
+
|
|
10
|
+
* Исправлены ошибки в разных модулях
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
1
14
|
# VEGAS-APP 0.6.6 - 0.6.8 (Ноябрь, 17, 2025)
|
|
2
15
|
* isLeaveBackDrop (boolean) - для методов .hide() модулей VGModal и VGSidebar. Если программно нужно сменить модалки или сайдбары и/или одно на другое при этом не будет затронут задний фон Backdrop
|
|
3
16
|
* Исправлены ошибки в разных модулях
|
|
@@ -34,48 +34,50 @@ class BaseModule {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
_route(callback) {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
let $content = null,
|
|
38
|
+
timeout = this._params.ajax.timeout || 0;
|
|
39
39
|
|
|
40
|
-
if (
|
|
40
|
+
if (this._isLoaded) return;
|
|
41
41
|
|
|
42
42
|
const setData = (data) => {
|
|
43
43
|
if ($content) $content.innerHTML = data;
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
if (!
|
|
46
|
+
if (!this._params.hasOwnProperty('ajax')) {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
if (!
|
|
50
|
+
if (!this._params.ajax.route) {
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
if (!'method' in
|
|
55
|
-
|
|
54
|
+
if (!'method' in this._params.ajax) {
|
|
55
|
+
this._params.ajax.method = 'get';
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
if ('target' in
|
|
59
|
-
$content = Selectors.find(
|
|
58
|
+
if ('target' in this._params.ajax && this._params.ajax.target) {
|
|
59
|
+
$content = Selectors.find(this._params.ajax.target);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
if ('loader' in
|
|
63
|
-
if ('output' in
|
|
62
|
+
if ('loader' in this._params.ajax && this._params.ajax.loader) {
|
|
63
|
+
if ('output' in this._params.ajax && this._params.ajax.output) {
|
|
64
64
|
setData('<div class="vg-loader"></div>');
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
Ajax[this._params.ajax.method](this._params.ajax.route, this._params.ajax.data || {}, (status, data) => {
|
|
70
|
+
if ('once' in this._params.ajax && this._params.ajax.once) {
|
|
71
|
+
this._isLoaded = true;
|
|
72
|
+
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
if ('output' in this._params.ajax && this._params.ajax.output) {
|
|
75
|
+
setData(data.response);
|
|
76
|
+
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
execute(callback, [status, data, $content]);
|
|
79
|
+
});
|
|
80
|
+
}, timeout)
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
_dismissElement() {
|
|
@@ -3,7 +3,7 @@ import {Manipulator} from "../../../utils/js/dom/manipulator";
|
|
|
3
3
|
import EventHandler from "../../../utils/js/dom/event";
|
|
4
4
|
import VGModal from "../../vgmodal/js/vgmodal";
|
|
5
5
|
import {
|
|
6
|
-
execute,
|
|
6
|
+
execute, getDeepestLastChild,
|
|
7
7
|
isObject,
|
|
8
8
|
isVisible,
|
|
9
9
|
makeRandomString,
|
|
@@ -66,6 +66,7 @@ class VGFormSender extends BaseModule {
|
|
|
66
66
|
route: '',
|
|
67
67
|
target: '',
|
|
68
68
|
method: 'get',
|
|
69
|
+
timeout: 1000,
|
|
69
70
|
},
|
|
70
71
|
classes: {
|
|
71
72
|
general: 'vg-form-sender',
|
|
@@ -83,7 +84,17 @@ class VGFormSender extends BaseModule {
|
|
|
83
84
|
interceptors: {
|
|
84
85
|
success: false,
|
|
85
86
|
error: false
|
|
86
|
-
}
|
|
87
|
+
},
|
|
88
|
+
button: {
|
|
89
|
+
enabled: true,
|
|
90
|
+
disabled: true,
|
|
91
|
+
send: 'Отправляем...',
|
|
92
|
+
initial: 'Отправить',
|
|
93
|
+
spinner: {
|
|
94
|
+
enabled: false,
|
|
95
|
+
element: '<span class="spinner-border spinner-border-sm me-2"></span>'
|
|
96
|
+
}
|
|
97
|
+
},
|
|
87
98
|
}, params));
|
|
88
99
|
|
|
89
100
|
this._params.ajax.route = Manipulator.get(this._element, 'action').toLowerCase();
|
|
@@ -93,6 +104,9 @@ class VGFormSender extends BaseModule {
|
|
|
93
104
|
this._params.isBtnText = Manipulator.get(this._element, 'data-btn-text') !== 'false';
|
|
94
105
|
this._params.isJsonParse = Manipulator.get(this._element, 'data-json-parse') !== 'false';
|
|
95
106
|
this._params.isShowPass = Manipulator.get(this._element, 'data-show-pass') === 'true';
|
|
107
|
+
|
|
108
|
+
this._params = this._getParams(this._button, this._params);
|
|
109
|
+
this._params.button.initial = this._button.innerHTML || this._params.button.initial;
|
|
96
110
|
}
|
|
97
111
|
|
|
98
112
|
static get NAME() {
|
|
@@ -129,40 +143,38 @@ class VGFormSender extends BaseModule {
|
|
|
129
143
|
}
|
|
130
144
|
|
|
131
145
|
request(data, event) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
_this._alertBefore();
|
|
146
|
+
this._alertBefore();
|
|
135
147
|
|
|
136
|
-
|
|
148
|
+
this._params.ajax.data = data;
|
|
137
149
|
|
|
138
|
-
|
|
139
|
-
|
|
150
|
+
this._route((status, data) => {
|
|
151
|
+
this._element.classList.remove('was-validated');
|
|
140
152
|
|
|
141
|
-
if (
|
|
142
|
-
data.response =
|
|
153
|
+
if (this._params.response.enabled) {
|
|
154
|
+
data.response = this._params.response;
|
|
143
155
|
}
|
|
144
156
|
|
|
145
|
-
if (
|
|
157
|
+
if (this._params.alert.enabled) {
|
|
146
158
|
if (typeof status === 'string' && status === 'error') {
|
|
147
|
-
if (
|
|
148
|
-
window.location.href =
|
|
159
|
+
if (this._params.redirect.error) {
|
|
160
|
+
window.location.href = this._params.redirect.error;
|
|
149
161
|
} else {
|
|
150
|
-
if (!
|
|
151
|
-
|
|
152
|
-
execute(
|
|
162
|
+
if (!this._params.interceptors.error) {
|
|
163
|
+
this._alertError(event, data);
|
|
164
|
+
execute(this._params.callback.afterError, [this._element, this, event, data]);
|
|
153
165
|
} else {
|
|
154
|
-
execute(
|
|
166
|
+
execute(this._params.callback.afterError, [this._element, this, event, data]);
|
|
155
167
|
}
|
|
156
168
|
}
|
|
157
169
|
} else if (typeof status === 'string' && status === 'success') {
|
|
158
|
-
if (
|
|
159
|
-
window.location.href =
|
|
170
|
+
if (this._params.redirect.success) {
|
|
171
|
+
window.location.href = this._params.redirect.success;
|
|
160
172
|
} else {
|
|
161
|
-
if (!
|
|
162
|
-
|
|
163
|
-
execute(
|
|
173
|
+
if (!this._params.interceptors.success) {
|
|
174
|
+
this._alertSuccess(event, data);
|
|
175
|
+
execute(this._params.callback.afterSuccess, [this._element, this, event, data]);
|
|
164
176
|
} else {
|
|
165
|
-
execute(
|
|
177
|
+
execute(this._params.callback.afterSuccess, [this._element, this, event, data]);
|
|
166
178
|
}
|
|
167
179
|
}
|
|
168
180
|
}
|
|
@@ -202,55 +214,35 @@ class VGFormSender extends BaseModule {
|
|
|
202
214
|
}
|
|
203
215
|
|
|
204
216
|
_statusButton(status) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (!_this._button) return;
|
|
208
|
-
|
|
209
|
-
let btnSubmitText = _this._button,
|
|
210
|
-
btnText = {
|
|
211
|
-
send: 'Отправляем...',
|
|
212
|
-
text: 'Отправить'
|
|
213
|
-
};
|
|
217
|
+
if (!this._button) return;
|
|
214
218
|
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
}
|
|
219
|
+
if (status === 'before') {
|
|
220
|
+
const button = getDeepestLastChild(this._button) || this._button;
|
|
218
221
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
} else {
|
|
222
|
-
let $btnText = _this._button.querySelector('[data-text]');
|
|
223
|
-
if ($btnText) {
|
|
224
|
-
btnText.text = Manipulator.get($btnText, 'data-text');
|
|
225
|
-
btnSubmitText = $btnText;
|
|
222
|
+
if (this._params.button.spinner.enabled) {
|
|
223
|
+
this._button.insertAdjacentHTML('afterbegin', this._params.button.spinner.element);
|
|
226
224
|
}
|
|
227
|
-
}
|
|
228
225
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
} else {
|
|
232
|
-
let $btnTextSend = _this._button.querySelector('[data-text-send]');
|
|
233
|
-
if ($btnTextSend) {
|
|
234
|
-
btnText.send = Manipulator.get($btnTextSend, 'data-text-send');
|
|
235
|
-
btnSubmitText = $btnTextSend;
|
|
226
|
+
if (this._params.button.enabled) {
|
|
227
|
+
button.innerHTML = this._params.button.send
|
|
236
228
|
}
|
|
237
|
-
}
|
|
238
229
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
btnSubmitText.innerHTML = btnText.send;
|
|
230
|
+
if (this._params.button.disabled) {
|
|
231
|
+
Manipulator.set(this._button,'disabled', 'disabled');
|
|
242
232
|
}
|
|
243
|
-
Manipulator.set(_this._button,'disabled', 'disabled');
|
|
244
233
|
}
|
|
245
234
|
|
|
246
235
|
if (status === 'after') {
|
|
247
|
-
if (
|
|
248
|
-
|
|
236
|
+
if (this._params.button.enabled) {
|
|
237
|
+
this._button.innerHTML = this._params.button.initial;
|
|
238
|
+
}
|
|
239
|
+
if (this._params.button.disabled) {
|
|
240
|
+
Manipulator.remove(this._button,'disabled');
|
|
241
|
+
}
|
|
242
|
+
if (this._params.button.spinner.enabled) {
|
|
243
|
+
let spinner = this._button.querySelector('.spinner-border');
|
|
244
|
+
if (spinner) spinner.remove();
|
|
249
245
|
}
|
|
250
|
-
Manipulator.remove(_this._button,'disabled');
|
|
251
|
-
|
|
252
|
-
let spinner = _this._button.querySelector('.spinner-border');
|
|
253
|
-
if (spinner) spinner.remove();
|
|
254
246
|
}
|
|
255
247
|
}
|
|
256
248
|
|
|
@@ -187,6 +187,8 @@ class VGModal extends BaseModule {
|
|
|
187
187
|
this._isShown = false;
|
|
188
188
|
this._isTransitioning = true;
|
|
189
189
|
|
|
190
|
+
document.body.classList.remove(CLASS_NAME_OPEN);
|
|
191
|
+
|
|
190
192
|
setTimeout(() => {
|
|
191
193
|
this._element.classList.remove(CLASS_NAME_SHOW);
|
|
192
194
|
this._queueCallback(() => this._hideModal(openedModals, isLeaveBackDrop), this._element, this._isAnimatedFade());
|
|
@@ -194,31 +196,24 @@ class VGModal extends BaseModule {
|
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
_hideModal(openedModals, isLeaveBackDrop) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
if (!isLeaveBackDrop) {
|
|
200
|
+
this._element.style.display = 'none';
|
|
201
|
+
this._element.removeAttribute('aria-modal');
|
|
202
|
+
this._element.removeAttribute('role');
|
|
203
|
+
this._isTransitioning = false;
|
|
201
204
|
|
|
202
|
-
|
|
205
|
+
if (openedModals.length) return;
|
|
203
206
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
+
if (this._params.hash) {
|
|
208
|
+
history.pushState("", document.title, window.location.pathname + window.location.search);
|
|
209
|
+
}
|
|
207
210
|
|
|
208
|
-
if (!isLeaveBackDrop) {
|
|
209
211
|
Backdrop.hide(() => {
|
|
210
|
-
document.body.classList.remove(CLASS_NAME_OPEN);
|
|
211
212
|
this._resetAdjustments();
|
|
212
213
|
this._scrollBar.reset();
|
|
213
214
|
|
|
214
215
|
EventHandler.trigger(this._element, EVENT_KEY_HIDDEN);
|
|
215
216
|
})
|
|
216
|
-
} else {
|
|
217
|
-
document.body.classList.remove(CLASS_NAME_OPEN);
|
|
218
|
-
this._resetAdjustments();
|
|
219
|
-
this._scrollBar.reset();
|
|
220
|
-
|
|
221
|
-
EventHandler.trigger(this._element, EVENT_KEY_HIDDEN);
|
|
222
217
|
}
|
|
223
218
|
}
|
|
224
219
|
|
|
@@ -120,6 +120,8 @@ class VGSidebar extends BaseModule {
|
|
|
120
120
|
const hideEvent = EventHandler.trigger(this._element, EVENT_KEY_HIDE);
|
|
121
121
|
if (hideEvent.defaultPrevented) return;
|
|
122
122
|
|
|
123
|
+
document.body.classList.remove(CLASS_NAME_OPEN);
|
|
124
|
+
|
|
123
125
|
setTimeout(() => {
|
|
124
126
|
this._element.setAttribute('aria-expanded', false);
|
|
125
127
|
this._element.classList.remove(CLASS_NAME_SHOW);
|
|
@@ -133,18 +135,17 @@ class VGSidebar extends BaseModule {
|
|
|
133
135
|
}
|
|
134
136
|
});
|
|
135
137
|
}
|
|
136
|
-
}
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
if (this._params.overflow) {
|
|
140
|
+
Overflow.destroy();
|
|
141
|
+
}
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
if (this._params.hash) {
|
|
144
|
+
history.pushState("", document.title, window.location.pathname + window.location.search);
|
|
145
|
+
}
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
EventHandler.trigger(this._element, EVENT_KEY_HIDDEN);
|
|
148
|
+
}
|
|
148
149
|
}
|
|
149
150
|
this._queueCallback(completeCallback, this._element, true);
|
|
150
151
|
}, this._params.animation.delay);
|
|
@@ -17,24 +17,30 @@ class Params {
|
|
|
17
17
|
merge(params, element) {
|
|
18
18
|
let mParams = mergeDeepObject(params, this.fromElement(element));
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
function stringToNestedObjectWithValue(str, value, params) {
|
|
21
|
+
const keys = str.split('-');
|
|
22
|
+
let result = {};
|
|
23
|
+
let currentLevel = result;
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < keys.length; i++) {
|
|
26
|
+
const key = keys[i];
|
|
27
|
+
|
|
28
|
+
if (i < keys.length - 1) {
|
|
29
|
+
currentLevel[key] = {};
|
|
30
|
+
currentLevel = currentLevel[key];
|
|
31
|
+
} else {
|
|
32
|
+
currentLevel[key] = value;
|
|
29
33
|
}
|
|
30
|
-
|
|
31
|
-
delete mParams[key];
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
return mergeDeepObject(params, result);
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
for (let key in mParams) {
|
|
40
|
+
if (key.indexOf('-') !== -1) {
|
|
41
|
+
mParams = stringToNestedObjectWithValue(key, mParams[key], mParams);
|
|
42
|
+
delete mParams[key];
|
|
43
|
+
}
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
return mParams;
|
|
@@ -345,9 +345,24 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
|
|
|
345
345
|
return list[Math.max(0, Math.min(index, listLength - 1))]
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Рекурсивный поиск самого глубокого последнего потомка
|
|
350
|
+
* @param element
|
|
351
|
+
* @returns {*}
|
|
352
|
+
*/
|
|
353
|
+
function getDeepestLastChild(element) {
|
|
354
|
+
let current = element;
|
|
355
|
+
|
|
356
|
+
while (current.lastElementChild) {
|
|
357
|
+
current = current.lastElementChild;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return current;
|
|
361
|
+
}
|
|
362
|
+
|
|
348
363
|
/**
|
|
349
364
|
*
|
|
350
365
|
*/
|
|
351
366
|
const isRTL = () => document.documentElement.dir === 'rtl'
|
|
352
367
|
|
|
353
|
-
export {isElement, isVisible, isDisabled, isObject, isEmptyObj, mergeDeepObject, removeElementArray, normalizeData, execute, executeAfterTransition, reflow, noop, makeRandomString, isRTL, transliterate, getElement, getNextActiveElement}
|
|
368
|
+
export {getDeepestLastChild, isElement, isVisible, isDisabled, isObject, isEmptyObj, mergeDeepObject, removeElementArray, normalizeData, execute, executeAfterTransition, reflow, noop, makeRandomString, isRTL, transliterate, getElement, getNextActiveElement}
|