vgapp 0.7.9 → 0.8.1
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 +9 -0
- package/app/langs/en/buttons.json +16 -0
- package/app/langs/en/messages.json +32 -0
- package/app/langs/en/titles.json +6 -0
- package/app/langs/ru/buttons.json +16 -0
- package/app/langs/ru/messages.json +32 -0
- package/app/langs/ru/titles.json +6 -0
- package/app/modules/base-module.js +12 -1
- package/app/modules/module-fn.js +20 -9
- package/app/modules/vgalert/js/vgalert.js +12 -6
- package/app/modules/vgalert/readme.md +1 -1
- package/app/modules/vgcollapse/readme.md +1 -1
- package/app/modules/vgdropdown/js/vgdropdown.js +140 -38
- package/app/modules/vgdropdown/readme.md +225 -0
- package/app/modules/vgfiles/js/base.js +499 -0
- package/app/modules/vgfiles/js/droppable.js +159 -0
- package/app/modules/vgfiles/js/loader.js +389 -0
- package/app/modules/vgfiles/js/render.js +83 -0
- package/app/modules/vgfiles/js/sortable.js +155 -0
- package/app/modules/vgfiles/js/vgfiles.js +796 -280
- package/app/modules/vgfiles/readme.md +193 -0
- package/app/modules/vgfiles/scss/_animations.scss +18 -0
- package/app/modules/vgfiles/scss/_mixins.scss +73 -0
- package/app/modules/vgfiles/scss/_variables.scss +103 -26
- package/app/modules/vgfiles/scss/vgfiles.scss +573 -60
- package/app/modules/vgformsender/js/vgformsender.js +5 -1
- package/app/modules/vgformsender/readme.md +1 -1
- package/app/modules/vglawcookie/js/vglawcookie.js +96 -62
- package/app/modules/vglawcookie/readme.md +102 -0
- package/app/modules/vgloadmore/js/vgloadmore.js +212 -112
- package/app/modules/vgloadmore/readme.md +145 -0
- package/app/modules/vgsidebar/js/vgsidebar.js +6 -4
- package/app/utils/js/components/ajax.js +172 -122
- package/app/utils/js/components/animation.js +124 -39
- package/app/utils/js/components/backdrop.js +54 -31
- package/app/utils/js/components/lang.js +69 -88
- package/app/utils/js/components/params.js +34 -31
- package/app/utils/js/components/scrollbar.js +118 -67
- package/app/utils/js/components/templater.js +14 -4
- package/app/utils/js/dom/cookie.js +107 -64
- package/app/utils/js/dom/data.js +68 -20
- package/app/utils/js/dom/event.js +272 -239
- package/app/utils/js/dom/manipulator.js +135 -62
- package/app/utils/js/dom/selectors.js +134 -59
- package/app/utils/js/functions.js +183 -349
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/package.json +1 -1
- package/app/utils/js/components/overflow.js +0 -28
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {mergeDeepObject, noop, normalizeData} from "../functions";
|
|
1
|
+
import { mergeDeepObject, noop, normalizeData } from "../functions";
|
|
2
2
|
|
|
3
3
|
class Ajax {
|
|
4
4
|
/**
|
|
@@ -10,25 +10,24 @@ class Ajax {
|
|
|
10
10
|
* @param {string} options._token - Токен (авто-чтение из meta)
|
|
11
11
|
*/
|
|
12
12
|
constructor(options = {}) {
|
|
13
|
-
this.baseUrl = options.baseUrl ||
|
|
13
|
+
this.baseUrl = options.baseUrl || "";
|
|
14
14
|
this.defaultHeaders = {
|
|
15
|
-
|
|
16
|
-
...options.headers
|
|
15
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
16
|
+
...options.headers,
|
|
17
17
|
};
|
|
18
18
|
this.withCredentials = options.withCredentials || false;
|
|
19
19
|
this.csrfToken = options._token || this._getCsrfToken();
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Получение
|
|
23
|
+
* Получение CSRF-токена из тега meta
|
|
24
24
|
* @returns {string}
|
|
25
|
-
* @private
|
|
26
25
|
*/
|
|
27
26
|
_getCsrfToken() {
|
|
28
27
|
const meta = document.querySelector('meta[name="csrf-token"]');
|
|
29
|
-
if (meta) return meta.getAttribute(
|
|
28
|
+
if (meta) return meta.getAttribute("content");
|
|
30
29
|
console.warn('CSRF-токен не найден в <meta name="csrf-token">');
|
|
31
|
-
return
|
|
30
|
+
return "";
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
/**
|
|
@@ -36,201 +35,252 @@ class Ajax {
|
|
|
36
35
|
* @param {string} url
|
|
37
36
|
* @param {Object} options
|
|
38
37
|
* @param {'GET'|'POST'|'PUT'|'DELETE'|'PATCH'} options.method
|
|
39
|
-
* @param {Object|FormData} options.body
|
|
40
|
-
* @param {Object} options.headers
|
|
41
|
-
* @param {
|
|
38
|
+
* @param {Object|FormData} options.body
|
|
39
|
+
* @param {Object} options.headers
|
|
40
|
+
* @param {AbortSignal} [options.signal] - Для отмены запроса
|
|
41
|
+
* @param {Function} [options.onProgress] - Только для POST/PUT с FormData
|
|
42
42
|
* @param {Function} options.onSuccess
|
|
43
43
|
* @param {Function} options.onError
|
|
44
|
-
* @param {Function} options.onUploadStart
|
|
45
|
-
* @param {Function} options.onUploadEnd
|
|
44
|
+
* @param {Function} [options.onUploadStart]
|
|
45
|
+
* @param {Function} [options.onUploadEnd]
|
|
46
46
|
*/
|
|
47
47
|
request(url, {
|
|
48
|
-
method =
|
|
48
|
+
method = "GET",
|
|
49
49
|
body = null,
|
|
50
50
|
headers = {},
|
|
51
|
+
signal = null,
|
|
51
52
|
onProgress = null,
|
|
52
|
-
onSuccess =
|
|
53
|
-
onError =
|
|
54
|
-
onUploadStart =
|
|
55
|
-
onUploadEnd =
|
|
53
|
+
onSuccess = noop,
|
|
54
|
+
onError = noop,
|
|
55
|
+
onUploadStart = noop,
|
|
56
|
+
onUploadEnd = noop,
|
|
56
57
|
} = {}) {
|
|
57
58
|
const fullUrl = this.baseUrl + url;
|
|
58
59
|
const isFormData = body instanceof FormData;
|
|
59
60
|
const requestHeaders = { ...this.defaultHeaders, ...headers };
|
|
60
|
-
const
|
|
61
|
+
const isGet = method.toUpperCase() === "GET";
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
_token: this.csrfToken
|
|
65
|
-
})
|
|
66
|
-
}
|
|
63
|
+
// Удаление тела для GET
|
|
64
|
+
if (isGet) body = null;
|
|
67
65
|
|
|
68
|
-
//
|
|
69
|
-
if (!
|
|
70
|
-
|
|
66
|
+
// Установка CSRF токена: в body, если не FormData
|
|
67
|
+
if (!isGet && !isFormData && this.csrfToken) {
|
|
68
|
+
if (!body) body = {};
|
|
69
|
+
if (typeof body === "object" && !Array.isArray(body)) {
|
|
70
|
+
body._token = this.csrfToken;
|
|
71
|
+
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
//
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
method,
|
|
77
|
-
headers: requestHeaders,
|
|
78
|
-
withCredentials: this.withCredentials
|
|
79
|
-
}, onSuccess, onError);
|
|
74
|
+
// Content-Type только для JSON
|
|
75
|
+
if (!isFormData && !("Content-Type" in headers)) {
|
|
76
|
+
requestHeaders["Content-Type"] = "application/json";
|
|
80
77
|
}
|
|
81
78
|
|
|
82
|
-
//
|
|
79
|
+
// Если нужно отслеживать прогресс или FormData — используем XHR
|
|
83
80
|
if (isFormData || onProgress) {
|
|
84
81
|
return this._makeXHR({
|
|
85
82
|
method,
|
|
86
83
|
url: fullUrl,
|
|
87
84
|
body,
|
|
88
85
|
headers: requestHeaders,
|
|
86
|
+
signal,
|
|
89
87
|
onProgress,
|
|
90
88
|
onSuccess,
|
|
91
89
|
onError,
|
|
92
90
|
onUploadStart,
|
|
93
|
-
onUploadEnd
|
|
91
|
+
onUploadEnd,
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
return this._makeFetch({
|
|
95
|
+
url: fullUrl,
|
|
96
|
+
method,
|
|
97
|
+
body: isGet ? undefined : this._serializeBody(body),
|
|
98
|
+
headers: requestHeaders,
|
|
99
|
+
signal,
|
|
100
|
+
withCredentials: this.withCredentials,
|
|
101
|
+
onSuccess,
|
|
102
|
+
onError,
|
|
94
103
|
});
|
|
95
104
|
}
|
|
96
|
-
|
|
97
|
-
// Остальные случаи — fetch
|
|
98
|
-
return this._makeFetch(fullUrl, mergeDeepObject({
|
|
99
|
-
method,
|
|
100
|
-
headers: requestHeaders,
|
|
101
|
-
withCredentials: this.withCredentials
|
|
102
|
-
}, token), onSuccess, onError);
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
/**
|
|
106
|
-
*
|
|
108
|
+
* fetch-реализация (для JSON)
|
|
107
109
|
*/
|
|
108
|
-
_makeFetch(
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
_makeFetch({
|
|
111
|
+
url,
|
|
112
|
+
method,
|
|
113
|
+
body,
|
|
114
|
+
headers,
|
|
115
|
+
signal,
|
|
116
|
+
withCredentials,
|
|
117
|
+
onSuccess,
|
|
118
|
+
onError,
|
|
119
|
+
}) {
|
|
120
|
+
const config = {
|
|
121
|
+
method,
|
|
122
|
+
headers,
|
|
123
|
+
signal,
|
|
124
|
+
withCredentials,
|
|
125
|
+
...(body !== undefined && { body }),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
fetch(url, config)
|
|
129
|
+
.then((response) => {
|
|
130
|
+
const contentType = response.headers.get("content-type");
|
|
131
|
+
const isJson = contentType && contentType.includes("application/json");
|
|
132
|
+
|
|
111
133
|
if (!response.ok) {
|
|
112
|
-
|
|
134
|
+
return Promise.reject(
|
|
135
|
+
normalizeData({
|
|
136
|
+
code: response.status,
|
|
137
|
+
response: isJson
|
|
138
|
+
? response.json().catch(() => response.text())
|
|
139
|
+
: response.text(),
|
|
140
|
+
})
|
|
141
|
+
);
|
|
113
142
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
143
|
+
|
|
144
|
+
let data = { code: response.status };
|
|
145
|
+
if (isJson) {
|
|
146
|
+
data.response = response.json();
|
|
147
|
+
} else {
|
|
148
|
+
data.response = response.text();
|
|
120
149
|
}
|
|
121
150
|
|
|
122
|
-
return
|
|
123
|
-
code: response.status,
|
|
124
|
-
response: response.text()
|
|
125
|
-
};
|
|
151
|
+
return data;
|
|
126
152
|
})
|
|
127
|
-
.then(data => {
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
response: text
|
|
134
|
-
})
|
|
135
|
-
})
|
|
136
|
-
} else {
|
|
137
|
-
onSuccess(data)
|
|
138
|
-
}
|
|
153
|
+
.then((data) => {
|
|
154
|
+
if (data && data.response instanceof Promise) {
|
|
155
|
+
data.response.then(
|
|
156
|
+
(resolved) => onSuccess({ ...data, response: resolved }),
|
|
157
|
+
() => {}
|
|
158
|
+
);
|
|
139
159
|
} else {
|
|
140
|
-
|
|
160
|
+
console.log(data)
|
|
161
|
+
onSuccess(data);
|
|
141
162
|
}
|
|
142
163
|
})
|
|
143
|
-
.catch(error =>
|
|
164
|
+
.catch((error) => {
|
|
165
|
+
if (error.name === "AbortError") return; // отмена — не ошибка
|
|
166
|
+
|
|
167
|
+
if (error && error.response instanceof Promise) {
|
|
168
|
+
error.response.then((errData) => {
|
|
169
|
+
onError({ ...error, response: errData });
|
|
170
|
+
}, () => {
|
|
171
|
+
onError({ ...error, response: "Request failed" });
|
|
172
|
+
});
|
|
173
|
+
} else {
|
|
174
|
+
onError(error);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
144
177
|
}
|
|
145
178
|
|
|
146
179
|
/**
|
|
147
|
-
*
|
|
180
|
+
* XHR-реализация (с прогрессом и AbortController)
|
|
148
181
|
*/
|
|
149
182
|
_makeXHR({
|
|
150
183
|
method,
|
|
151
184
|
url,
|
|
152
185
|
body,
|
|
153
186
|
headers,
|
|
187
|
+
signal,
|
|
154
188
|
onProgress,
|
|
155
189
|
onSuccess,
|
|
156
190
|
onError,
|
|
157
191
|
onUploadStart,
|
|
158
|
-
onUploadEnd
|
|
192
|
+
onUploadEnd,
|
|
159
193
|
}) {
|
|
160
|
-
|
|
161
|
-
const xhr = new XMLHttpRequest();
|
|
194
|
+
const xhr = new XMLHttpRequest();
|
|
162
195
|
|
|
163
|
-
|
|
164
|
-
|
|
196
|
+
xhr.open(method, url, true);
|
|
197
|
+
xhr.withCredentials = this.withCredentials;
|
|
165
198
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
199
|
+
// Установка заголовков
|
|
200
|
+
Object.keys(headers).forEach((key) => {
|
|
201
|
+
if (key.toLowerCase() !== "content-type" || !(body instanceof FormData)) {
|
|
202
|
+
xhr.setRequestHeader(key, headers[key]);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Прогресс
|
|
207
|
+
if (onProgress) {
|
|
208
|
+
xhr.upload.addEventListener("progress", (e) => {
|
|
209
|
+
if (e.lengthComputable) {
|
|
210
|
+
onProgress(Math.round((e.loaded / e.total) * 100), e);
|
|
170
211
|
}
|
|
171
212
|
});
|
|
213
|
+
}
|
|
172
214
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
215
|
+
// События
|
|
216
|
+
xhr.onload = () => {
|
|
217
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
218
|
+
const data = {
|
|
219
|
+
code: xhr.status,
|
|
220
|
+
response: normalizeData(xhr.responseText),
|
|
221
|
+
};
|
|
222
|
+
onSuccess(data);
|
|
223
|
+
} else {
|
|
224
|
+
const error = normalizeData({
|
|
225
|
+
code: xhr.status,
|
|
226
|
+
response: xhr.responseText || `HTTP ${xhr.status}`,
|
|
180
227
|
});
|
|
228
|
+
onError(error);
|
|
181
229
|
}
|
|
230
|
+
onUploadEnd();
|
|
231
|
+
};
|
|
182
232
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
response: normalizeData(xhr.responseText)
|
|
188
|
-
};
|
|
189
|
-
onSuccess(data);
|
|
190
|
-
resolve(data);
|
|
191
|
-
} else {
|
|
192
|
-
const error = new Error(`Ошибка ${xhr.status}: ${xhr.statusText}`);
|
|
193
|
-
let data = {
|
|
194
|
-
code: xhr.status,
|
|
195
|
-
response: error
|
|
196
|
-
}
|
|
197
|
-
onError(data);
|
|
198
|
-
reject(data);
|
|
199
|
-
}
|
|
200
|
-
onUploadEnd();
|
|
201
|
-
};
|
|
233
|
+
xhr.onerror = () => {
|
|
234
|
+
onError(normalizeData({ code: 0, response: "Network Error" }));
|
|
235
|
+
onUploadEnd();
|
|
236
|
+
};
|
|
202
237
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
onUploadEnd();
|
|
208
|
-
};
|
|
238
|
+
xhr.ontimeout = () => {
|
|
239
|
+
onError(normalizeData({ code: 0, response: "Request Timeout" }));
|
|
240
|
+
onUploadEnd();
|
|
241
|
+
};
|
|
209
242
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
243
|
+
// Привязка AbortController
|
|
244
|
+
if (signal) {
|
|
245
|
+
signal.addEventListener("abort", () => {
|
|
246
|
+
xhr.abort();
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
onUploadStart();
|
|
251
|
+
xhr.send(body);
|
|
252
|
+
|
|
253
|
+
return xhr; // для отмены снаружи
|
|
213
254
|
}
|
|
214
255
|
|
|
215
256
|
// === Сокращённые методы ===
|
|
257
|
+
|
|
216
258
|
get(url, options = {}) {
|
|
217
|
-
return this.request(url, { method:
|
|
259
|
+
return this.request(url, { method: "GET", ...options });
|
|
218
260
|
}
|
|
219
261
|
|
|
220
262
|
post(url, body, options = {}) {
|
|
221
|
-
return this.request(url, { method:
|
|
263
|
+
return this.request(url, { method: "POST", body, ...options });
|
|
222
264
|
}
|
|
223
265
|
|
|
224
266
|
put(url, body, options = {}) {
|
|
225
|
-
return this.request(url, { method:
|
|
267
|
+
return this.request(url, { method: "PUT", body, ...options });
|
|
226
268
|
}
|
|
227
269
|
|
|
228
270
|
delete(url, options = {}) {
|
|
229
|
-
return this.request(url, { method:
|
|
271
|
+
return this.request(url, { method: "DELETE", ...options });
|
|
230
272
|
}
|
|
231
273
|
|
|
232
274
|
patch(url, body, options = {}) {
|
|
233
|
-
return this.request(url, { method:
|
|
275
|
+
return this.request(url, { method: "PATCH", body, ...options });
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Сериализация тела (если не FormData)
|
|
280
|
+
*/
|
|
281
|
+
_serializeBody(body) {
|
|
282
|
+
if (!body || body instanceof FormData) return undefined;
|
|
283
|
+
return JSON.stringify(body);
|
|
234
284
|
}
|
|
235
285
|
}
|
|
236
286
|
|
|
@@ -1,61 +1,146 @@
|
|
|
1
|
-
import {isElement, mergeDeepObject} from "../functions";
|
|
1
|
+
import { isElement, mergeDeepObject } from "../functions";
|
|
2
2
|
import EventHandler from "../dom/event";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Анимация на основе Animate.css
|
|
6
|
+
* Поддерживает модули с событиях: show, shown, hide, hidden
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* @see https://animate.style/
|
|
9
9
|
*/
|
|
10
10
|
class Animation {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
static get DEFAULTS() {
|
|
12
|
+
return {
|
|
13
13
|
enable: false,
|
|
14
|
-
in: '
|
|
15
|
-
out: '
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
in: 'animate__fadeIn', // Анимация при появлении
|
|
15
|
+
out: 'animate__fadeOut', // Анимация при скрытии
|
|
16
|
+
duration: 500, // Длительность анимации (мс)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor(element, key, userParams = {}) {
|
|
21
|
+
this._element = element;
|
|
22
|
+
this._nameKey = key;
|
|
23
|
+
|
|
24
|
+
// Объединение параметров
|
|
25
|
+
this._params = mergeDeepObject(Animation.DEFAULTS, userParams);
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
// Ранний выход, если анимация отключена или элемент не валиден
|
|
28
|
+
if (!this._params.enable || !isElement(element)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this._classes = {
|
|
21
33
|
animated: 'animate__animated',
|
|
22
|
-
duration: '
|
|
34
|
+
duration: 'animate__fast' // Используем классы animate.css
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
this._init();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Инициализация анимации
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
_init() {
|
|
45
|
+
const { classList } = this._element;
|
|
46
|
+
|
|
47
|
+
// Добавляем общие классы
|
|
48
|
+
classList.add(this._classes.animated, this._classes.duration);
|
|
49
|
+
|
|
50
|
+
// Удаляем стандартный класс 'fade', если используется animate.css
|
|
51
|
+
if (classList.contains('fade')) {
|
|
52
|
+
classList.remove('fade');
|
|
23
53
|
}
|
|
24
54
|
|
|
25
|
-
|
|
26
|
-
|
|
55
|
+
// Назначаем обработчики событий
|
|
56
|
+
this._setupEventListeners();
|
|
57
|
+
}
|
|
27
58
|
|
|
28
|
-
|
|
29
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Назначение обработчиков событий
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
_setupEventListeners() {
|
|
64
|
+
EventHandler.on(this._element, `${this._nameKey}.show`, this._handleShow.bind(this), null);
|
|
65
|
+
EventHandler.on(this._element, `${this._nameKey}.shown`, this._handleShown.bind(this), null);
|
|
66
|
+
EventHandler.on(this._element, `${this._nameKey}.hide`, this._handleHide.bind(this), null);
|
|
67
|
+
EventHandler.on(this._element, `${this._nameKey}.hidden`, this._handleHidden.bind(this), null);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Обработка события "show" — запуск анимации входа
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
_handleShow() {
|
|
75
|
+
const { classList } = this._element;
|
|
76
|
+
const { in: inClass, out: outClass } = this._params;
|
|
77
|
+
|
|
78
|
+
// Убираем выходную анимацию, если была
|
|
79
|
+
if (classList.contains(outClass)) {
|
|
80
|
+
classList.remove(outClass);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Добавляем входную анимацию
|
|
84
|
+
classList.add(inClass);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Обработка события "shown" — завершение анимации входа
|
|
89
|
+
* @private
|
|
90
|
+
*/
|
|
91
|
+
_handleShown() {
|
|
92
|
+
this._element.classList.add(this._classes.animated);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Обработка события "hide" — запуск анимации выхода
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
_handleHide() {
|
|
100
|
+
const { classList } = this._element;
|
|
101
|
+
const { in: inClass, out: outClass } = this._params;
|
|
102
|
+
|
|
103
|
+
// Убираем входную анимацию
|
|
104
|
+
if (classList.contains(inClass)) {
|
|
105
|
+
classList.remove(inClass);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Добавляем выходную анимацию
|
|
109
|
+
classList.add(outClass);
|
|
110
|
+
}
|
|
30
111
|
|
|
31
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Обработка события "hidden" — очистка анимационных классов
|
|
114
|
+
* @private
|
|
115
|
+
*/
|
|
116
|
+
_handleHidden() {
|
|
117
|
+
const { classList } = this._element;
|
|
118
|
+
const { in: inClass, out: outClass } = this._params;
|
|
32
119
|
|
|
33
|
-
|
|
120
|
+
// Удаляем все анимационные классы animate.css
|
|
121
|
+
[...classList]
|
|
122
|
+
.filter(cls => cls.startsWith('animate__'))
|
|
123
|
+
.forEach(cls => classList.remove(cls));
|
|
34
124
|
|
|
35
|
-
|
|
125
|
+
// Восстанавливаем базовые классы для будущих анимаций
|
|
126
|
+
classList.add(this._classes.animated, this._classes.duration);
|
|
36
127
|
}
|
|
37
128
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
43
|
-
EventHandler.
|
|
44
|
-
|
|
45
|
-
});
|
|
129
|
+
/**
|
|
130
|
+
* Уничтожение экземпляра (очистка событий)
|
|
131
|
+
*/
|
|
132
|
+
dispose() {
|
|
133
|
+
EventHandler.off(this._element, `${this._nameKey}.show`, null, null);
|
|
134
|
+
EventHandler.off(this._element, `${this._nameKey}.shown`, null, null);
|
|
135
|
+
EventHandler.off(this._element, `${this._nameKey}.hide`, null, null);
|
|
136
|
+
EventHandler.off(this._element, `${this._nameKey}.hidden`, null, null);
|
|
46
137
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
138
|
+
// Очищаем анимационные классы
|
|
139
|
+
[...this._element.classList]
|
|
140
|
+
.filter(cls => cls.startsWith('animate__'))
|
|
141
|
+
.forEach(cls => this._element.classList.remove(cls));
|
|
51
142
|
|
|
52
|
-
|
|
53
|
-
[... this._element.classList].forEach((cl) => {
|
|
54
|
-
if (cl.indexOf('animate__') !== -1) {
|
|
55
|
-
this._element.classList.remove(cl);
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
});
|
|
143
|
+
this._element = null;
|
|
59
144
|
}
|
|
60
145
|
}
|
|
61
146
|
|