vgapp 0.8.1 → 0.8.3

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 CHANGED
@@ -1,3 +1,13 @@
1
+ # VEGAS-APP 0.8.2 (Январь, 4, 2025)
2
+ * Оптимизирован модуль VGRollup, см. файл readme.md
3
+ * Оптимизирован модуль VGSidebar, см. файл readme.md
4
+ * Оптимизирован модуль VGTabs, см. файл readme.md
5
+ * Оптимизирован модуль VGSpy, см. файл readme.md
6
+ * Оптимизирован модуль VGToast, см. файл readme.md
7
+ * Оптимизирован и дополнен модуль VGSelect, см. файл readme.md
8
+
9
+ ---
10
+
1
11
  # VEGAS-APP 0.8.1 (Январь, 2, 2025)
2
12
  * Оптимизирован и дополнен модуль VGLoadMore, см. файл readme.md
3
13
 
@@ -12,5 +12,13 @@
12
12
  "show": "I'm showing you...",
13
13
  "text-ajax": "Upload more",
14
14
  "text-more": "Show more"
15
+ },
16
+ "rollup": {
17
+ "less": "Roll up",
18
+ "show": "Show",
19
+ "more": " more "
20
+ },
21
+ "select": {
22
+ "load-more": "Upload more"
15
23
  }
16
24
  }
@@ -28,5 +28,8 @@
28
28
  "title": "Default header",
29
29
  "description": "Description of the current action",
30
30
  "reason": "Alert already open"
31
+ },
32
+ "select": {
33
+ "loading": "Loading"
31
34
  }
32
35
  }
@@ -2,5 +2,8 @@
2
2
  "errors": {
3
3
  "title": "Error",
4
4
  "titles": "Errors"
5
+ },
6
+ "select": {
7
+ "search": "Search..."
5
8
  }
6
9
  }
@@ -12,5 +12,13 @@
12
12
  "show": "Показываю...",
13
13
  "text-ajax": "Загрузить еще",
14
14
  "text-more": "Показать еще"
15
+ },
16
+ "rollup": {
17
+ "less": "Свернуть",
18
+ "show": "Показать",
19
+ "more": " еще "
20
+ },
21
+ "select": {
22
+ "load-more": "Загрузить еще"
15
23
  }
16
24
  }
@@ -28,5 +28,8 @@
28
28
  "title": "Заголовок по умолчанию",
29
29
  "description": "Описание текущего действия",
30
30
  "reason": "Алерт уже открыт"
31
+ },
32
+ "select": {
33
+ "loading": "Загрузка"
31
34
  }
32
35
  }
@@ -2,5 +2,8 @@
2
2
  "errors": {
3
3
  "title": "Ошибка",
4
4
  "titles": "Ошибки"
5
+ },
6
+ "select": {
7
+ "search": "Поиск..."
5
8
  }
6
9
  }
@@ -3,10 +3,65 @@ import EventHandler from "../../../utils/js/dom/event";
3
3
  import { execute, isObject, mergeDeepObject, normalizeData } from "../../../utils/js/functions";
4
4
  import Selectors from "../../../utils/js/dom/selectors";
5
5
  import { Manipulator } from "../../../utils/js/dom/manipulator";
6
- import {lang_buttons} from "../../../utils/js/components/lang";
6
+ import { lang_buttons } from "../../../utils/js/components/lang";
7
+
8
+ /**
9
+ * @typedef {Object} VGLoadMoreParams
10
+ * @property {string} [lang='ru'] - Язык интерфейса (используется для локализации)
11
+ * @property {number} limit - Количество элементов, загружаемых за один раз
12
+ * @property {number} offset - Начальный сдвиг при загрузке
13
+ * @property {boolean} output - Вставлять ли ответ в DOM
14
+ * @property {boolean} autohide - Автоматически скрывать/удалять кнопку при достижении конца
15
+ * @property {boolean} animate - Анимировать появление новых элементов
16
+ * @property {string} append - Позиция вставки: 'after' (в конец) или 'before' (в начало)
17
+ * @property {string} mode - Режим загрузки: 'button' или 'scroll'
18
+ * @property {number} threshold - Отступ в пикселях для срабатывания при прокрутке
19
+ * @property {boolean} debug - Включить отладочные сообщения в консоли
20
+ * @property {boolean} detach - Удалять кнопку из DOM после использования
21
+ * @property {Object} button - Настройки кнопки
22
+ * @property {string} button.text - Текст кнопки по умолчанию
23
+ * @property {string} button.send - Текст во время AJAX-загрузки
24
+ * @property {string} button.show - Текст во время статической загрузки
25
+ * @property {boolean} button.loader - Показывать лоадер
26
+ * @property {string[]} button.classes - CSS-классы кнопки
27
+ * @property {Object} ajax - Настройки AJAX-запроса
28
+ * @property {string} ajax.route - URL для загрузки данных
29
+ * @property {string} ajax.target - Селектор контейнера для вставки
30
+ * @property {string} ajax.method - HTTP-метод ('get', 'post')
31
+ * @property {boolean} ajax.loader - Использовать лоадер
32
+ * @property {boolean} ajax.once - Загружать только один раз
33
+ * @property {boolean} ajax.output - Выводить ли ответ
34
+ * @property {Object} ajax.data - Дополнительные данные для запроса
35
+ */
36
+
37
+ /**
38
+ * @class VGLoadMore
39
+ * @extends BaseModule
40
+ * @description
41
+ * Модуль подгрузки контента по кнопке или при прокрутке.
42
+ * Поддерживает как статическую подгрузку скрытых элементов из DOM,
43
+ * так и AJAX-загрузку с сервера. Имеет гибкую настройку через data-атрибуты,
44
+ * поддержку языков, анимаций и отладку.
45
+ *
46
+ * @example
47
+ * <!-- Простая подгрузка по кнопке -->
48
+ * <div data-vgloadmore data-limit="3" data-elements="item">
49
+ * <div class="item vg-collapse">Элемент 1</div>
50
+ * <div class="item vg-collapse">Элемент 2</div>
51
+ * ...
52
+ * </div>
53
+ *
54
+ * @example
55
+ * <!-- AJAX-подгрузка при прокрутке -->
56
+ * <div data-vgloadmore
57
+ * data-ajax-route="/api/load"
58
+ * data-mode="scroll"
59
+ * data-threshold="200">
60
+ * </div>
61
+ */
7
62
 
8
63
  const NAME = 'loadmore';
9
- const NAME_KEY = 'vg.loadmore';
64
+ const NAME_KEY = 'vg.' + NAME;
10
65
  const SELECTOR_DATA_TOGGLE = '[data-vg-toggle="loadmore"]';
11
66
  const SELECTOR_DATA_MODULE = '[data-vgloadmore]';
12
67
 
@@ -17,9 +72,29 @@ const CLASS_NAME_SHOW = 'show';
17
72
  const EVENT_KEY_CLICK_DATA_API = `click.${NAME_KEY}.data.api`;
18
73
 
19
74
  class VGLoadMore extends BaseModule {
75
+ /**
76
+ * Имя модуля
77
+ * @type {string}
78
+ */
79
+ static get NAME() { return NAME; }
80
+
81
+ /**
82
+ * Ключ события модуля
83
+ * @type {string}
84
+ */
85
+ static get NAME_KEY() { return NAME_KEY; }
86
+
87
+ /**
88
+ * @private
89
+ */
20
90
  constructor(element, params) {
21
91
  super(element, params);
22
92
 
93
+ /**
94
+ * Параметры модуля
95
+ * @type {VGLoadMoreParams}
96
+ * @private
97
+ */
23
98
  this._params = this._getParams(element, mergeDeepObject({
24
99
  lang: document.documentElement.lang || 'ru',
25
100
  limit: 0,
@@ -50,10 +125,28 @@ class VGLoadMore extends BaseModule {
50
125
  }
51
126
  }, params));
52
127
 
128
+ /**
129
+ * Обсервер пересечения (для режима scroll)
130
+ * @type {IntersectionObserver|null}
131
+ * @private
132
+ */
53
133
  this._observer = null;
134
+
135
+ /**
136
+ * Режим прокрутки включён
137
+ * @type {boolean}
138
+ * @private
139
+ */
54
140
  this._isScrollMode = this._params.mode === 'scroll';
141
+
142
+ /**
143
+ * Элемент является триггером (имеет data-vg-toggle)
144
+ * @type {boolean}
145
+ * @private
146
+ */
55
147
  this._isToggleElement = element.hasAttribute('data-vg-toggle');
56
148
 
149
+ // Локализация текстов кнопок
57
150
  this._params.button.send = lang_buttons(this._params.lang, NAME)['send'];
58
151
  this._params.button.show = lang_buttons(this._params.lang, NAME)['show'];
59
152
 
@@ -70,15 +163,20 @@ class VGLoadMore extends BaseModule {
70
163
  }
71
164
  }
72
165
 
73
- static get NAME() { return NAME; }
74
- static get NAME_KEY() { return NAME_KEY; }
75
-
166
+ /**
167
+ * Инициализация, если элемент кнопка-триггер
168
+ * @private
169
+ */
76
170
  _initializeAsButton() {
77
171
  if (this._isScrollMode) {
78
172
  this._initScrollMode();
79
173
  }
80
174
  }
81
175
 
176
+ /**
177
+ * Инициализация контейнера с элементами
178
+ * @private
179
+ */
82
180
  _initializeContainer() {
83
181
  const { elements: itemClass, limit } = this._params;
84
182
  const container = this._element;
@@ -104,6 +202,11 @@ class VGLoadMore extends BaseModule {
104
202
  }
105
203
  }
106
204
 
205
+ /**
206
+ * Создаёт и вставляет кнопку управления
207
+ * @param {HTMLElement} container - Контейнер, рядом с которым вставляется кнопка
208
+ * @private
209
+ */
107
210
  _createAndInsertButton(container) {
108
211
  const button = document.createElement('button');
109
212
  const buttonText = normalizeData(container.dataset.buttonText) || this._params.button.text;
@@ -136,11 +239,19 @@ class VGLoadMore extends BaseModule {
136
239
  container.parentNode.insertBefore(button, container.nextSibling);
137
240
  }
138
241
 
242
+ /**
243
+ * Инициализирует режим прокрутки
244
+ * @private
245
+ */
139
246
  _initScrollMode() {
140
247
  this._setupIntersectionObserver();
141
248
  this._observeLastVisibleItem();
142
249
  }
143
250
 
251
+ /**
252
+ * Настраивает IntersectionObserver для отслеживания видимости последнего элемента
253
+ * @private
254
+ */
144
255
  _setupIntersectionObserver() {
145
256
  if (this._observer) return;
146
257
 
@@ -158,6 +269,10 @@ class VGLoadMore extends BaseModule {
158
269
  });
159
270
  }
160
271
 
272
+ /**
273
+ * Начинает отслеживание последнего видимого элемента
274
+ * @private
275
+ */
161
276
  _observeLastVisibleItem() {
162
277
  if (!this._observer) return;
163
278
 
@@ -173,6 +288,13 @@ class VGLoadMore extends BaseModule {
173
288
  }
174
289
  }
175
290
 
291
+ /**
292
+ * Основной метод подгрузки — вызывается по клику или при прокрутке
293
+ * @param {Function} [callback] - Колбэк, вызываемый после загрузки
294
+ * @fires VGLoadMore#vg.loadmore.before.load
295
+ * @fires VGLoadMore#vg.loadmore.loaded
296
+ * @public
297
+ */
176
298
  toggle(callback) {
177
299
  this._params.debug && console.log('[VGLoadMore] toggle()');
178
300
 
@@ -187,6 +309,11 @@ class VGLoadMore extends BaseModule {
187
309
  this._params.ajax.route ? this.ajax(callback) : this.staticLoad(callback);
188
310
  }
189
311
 
312
+ /**
313
+ * Выполняет AJAX-запрос для подгрузки данных
314
+ * @param {Function} [callback] - Колбэк после завершения
315
+ * @private
316
+ */
190
317
  ajax(callback) {
191
318
  const targetSelector = this._params.ajax.target?.trim();
192
319
  let targetEl = null;
@@ -194,16 +321,16 @@ class VGLoadMore extends BaseModule {
194
321
  if (targetSelector) {
195
322
  targetEl = Selectors.find(targetSelector);
196
323
  } else {
197
- targetEl = this._element
324
+ targetEl = this._element;
198
325
  }
199
326
 
200
- const originalText = this._params.button.text;
201
-
202
327
  if (!targetEl) {
203
328
  console.error('[VGLoadMore] target элемент не найден:', this._params.ajax.target);
204
329
  return;
205
330
  }
206
331
 
332
+ const originalText = this._params.button.text;
333
+
207
334
  this._params.ajax.data = { limit: this._params.limit, offset: this._params.offset };
208
335
 
209
336
  this._route((status, data, responseTarget) => {
@@ -233,6 +360,11 @@ class VGLoadMore extends BaseModule {
233
360
  });
234
361
  }
235
362
 
363
+ /**
364
+ * Подгружает элементы из DOM (статический режим)
365
+ * @param {Function} [callback] - Колбэк после завершения
366
+ * @private
367
+ */
236
368
  staticLoad(callback) {
237
369
  const container = Selectors.find(this._params.target) || this._element.parentNode;
238
370
  const items = Selectors.findAll(`.${this._params.elements}`, container);
@@ -270,6 +402,11 @@ class VGLoadMore extends BaseModule {
270
402
  execute(callback, [this, this._element]);
271
403
  }
272
404
 
405
+ /**
406
+ * Восстанавливает состояние кнопки (включает, устанавливает текст)
407
+ * @param {string} text - Текст кнопки
408
+ * @private
409
+ */
273
410
  _restoreElementState(text) {
274
411
  const isButton = this._isToggleElement || this._element.tagName === 'BUTTON';
275
412
  if (isButton && !this._isScrollMode) {
@@ -278,6 +415,10 @@ class VGLoadMore extends BaseModule {
278
415
  }
279
416
  }
280
417
 
418
+ /**
419
+ * Автоматически скрывает или удаляет элемент при завершении
420
+ * @private
421
+ */
281
422
  _autohideTrigger() {
282
423
  if (this._isScrollMode) {
283
424
  this._observer?.disconnect();
@@ -287,12 +428,19 @@ class VGLoadMore extends BaseModule {
287
428
  }
288
429
  }
289
430
 
431
+ /**
432
+ * Полная деинициализация модуля
433
+ * @override
434
+ */
290
435
  dispose() {
291
436
  this._observer?.disconnect();
292
437
  super.dispose();
293
438
  }
294
439
  }
295
440
 
441
+ /**
442
+ * Автоматическая инициализация на элементах с data-vgloadmore
443
+ */
296
444
  EventHandler.on(document, 'DOMContentLoaded', () => {
297
445
  Selectors.findAll(SELECTOR_DATA_MODULE).forEach(el => {
298
446
  !el.dataset.initialized && VGLoadMore.getOrCreateInstance(el);
@@ -300,6 +448,9 @@ EventHandler.on(document, 'DOMContentLoaded', () => {
300
448
  });
301
449
  });
302
450
 
451
+ /**
452
+ * Обработка кликов по элементам с data-vg-toggle="loadmore"
453
+ */
303
454
  EventHandler.on(document, EVENT_KEY_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
304
455
  ['A', 'AREA'].includes(this.tagName) && event.preventDefault();
305
456
  VGLoadMore.getOrCreateInstance(this).toggle();