vgapp 0.7.9 → 0.8.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/app/langs/en/buttons.json +10 -0
  3. package/app/langs/en/messages.json +32 -0
  4. package/app/langs/en/titles.json +6 -0
  5. package/app/langs/ru/buttons.json +10 -0
  6. package/app/langs/ru/messages.json +32 -0
  7. package/app/langs/ru/titles.json +6 -0
  8. package/app/modules/base-module.js +12 -1
  9. package/app/modules/module-fn.js +20 -9
  10. package/app/modules/vgalert/js/vgalert.js +12 -6
  11. package/app/modules/vgalert/readme.md +1 -1
  12. package/app/modules/vgcollapse/readme.md +1 -1
  13. package/app/modules/vgdropdown/js/vgdropdown.js +140 -38
  14. package/app/modules/vgdropdown/readme.md +225 -0
  15. package/app/modules/vgfiles/js/base.js +499 -0
  16. package/app/modules/vgfiles/js/droppable.js +159 -0
  17. package/app/modules/vgfiles/js/loader.js +389 -0
  18. package/app/modules/vgfiles/js/render.js +83 -0
  19. package/app/modules/vgfiles/js/sortable.js +155 -0
  20. package/app/modules/vgfiles/js/vgfiles.js +796 -280
  21. package/app/modules/vgfiles/readme.md +193 -0
  22. package/app/modules/vgfiles/scss/_animations.scss +18 -0
  23. package/app/modules/vgfiles/scss/_mixins.scss +73 -0
  24. package/app/modules/vgfiles/scss/_variables.scss +103 -26
  25. package/app/modules/vgfiles/scss/vgfiles.scss +573 -60
  26. package/app/modules/vgformsender/js/vgformsender.js +5 -1
  27. package/app/modules/vgformsender/readme.md +1 -1
  28. package/app/modules/vglawcookie/js/vglawcookie.js +96 -62
  29. package/app/modules/vglawcookie/readme.md +102 -0
  30. package/app/modules/vgsidebar/js/vgsidebar.js +6 -4
  31. package/app/utils/js/components/ajax.js +172 -122
  32. package/app/utils/js/components/animation.js +124 -39
  33. package/app/utils/js/components/backdrop.js +54 -31
  34. package/app/utils/js/components/lang.js +69 -88
  35. package/app/utils/js/components/params.js +34 -31
  36. package/app/utils/js/components/scrollbar.js +118 -67
  37. package/app/utils/js/components/templater.js +14 -4
  38. package/app/utils/js/dom/cookie.js +107 -64
  39. package/app/utils/js/dom/data.js +68 -20
  40. package/app/utils/js/dom/event.js +272 -239
  41. package/app/utils/js/dom/manipulator.js +135 -62
  42. package/app/utils/js/dom/selectors.js +134 -59
  43. package/app/utils/js/functions.js +183 -349
  44. package/build/vgapp.css +1 -1
  45. package/build/vgapp.css.map +1 -1
  46. package/package.json +1 -1
  47. package/app/utils/js/components/overflow.js +0 -28
@@ -1,127 +1,170 @@
1
1
  /*! js-cookie v3.0.1 | MIT */
2
2
 
3
- function assign (target) {
4
- for (let i = 1; i < arguments.length; i++) {
5
- let source = arguments[i];
6
- for (let key in source) {
3
+ 'use strict';
4
+
5
+ /**
6
+ * Объединяет несколько объектов в один (аналог Object.assign)
7
+ * @param {Object} target - целевой объект
8
+ * @param {...Object} sources - источники
9
+ * @returns {Object}
10
+ */
11
+ function assign(target) {
12
+ const sources = Array.prototype.slice.call(arguments, 1);
13
+ sources.forEach(source => {
14
+ if (!source) return;
15
+ Object.keys(source).forEach(key => {
7
16
  target[key] = source[key];
8
- }
9
- }
10
- return target
17
+ });
18
+ });
19
+ return target;
11
20
  }
12
21
 
13
- let defaultConverter = {
22
+ /**
23
+ * Конвертер для чтения и записи значений cookie
24
+ */
25
+ const defaultConverter = {
26
+ /**
27
+ * Читает значение cookie, убирая кавычки и декодируя
28
+ * @param {string} value
29
+ * @param {string} key
30
+ * @returns {string}
31
+ */
14
32
  read: function (value) {
15
33
  if (value[0] === '"') {
16
34
  value = value.slice(1, -1);
17
35
  }
18
- return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent)
36
+ return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
19
37
  },
38
+
39
+ /**
40
+ * Записывает значение cookie, кодируя его
41
+ * @param {string} value
42
+ * @param {string} key
43
+ * @returns {string}
44
+ */
20
45
  write: function (value) {
21
46
  return encodeURIComponent(value).replace(
22
47
  /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
23
48
  decodeURIComponent
24
- )
49
+ );
25
50
  }
26
51
  };
27
52
 
28
- function init (converter, defaultAttributes) {
29
- function set (key, value, attributes) {
30
- if (typeof document === 'undefined') {
31
- return
32
- }
33
-
53
+ /**
54
+ * Инициализация функционала работы с cookie
55
+ * @param {Object} converter - объект с методами read/write
56
+ * @param {Object} defaultAttributes - атрибуты по умолчанию (например, path, expires)
57
+ * @returns {Object} - API: set, get, remove, withAttributes, withConverter
58
+ */
59
+ function init(converter, defaultAttributes) {
60
+ /**
61
+ * Устанавливает cookie
62
+ */
63
+ function set(key, value, attributes) {
64
+ if (typeof document === 'undefined') return;
65
+
66
+ // Объединяем атрибуты: по умолчанию → экземпляр → вызов
34
67
  attributes = assign({}, defaultAttributes, attributes);
35
68
 
69
+ // Обработка expires: число → дата
36
70
  if (typeof attributes.expires === 'number') {
37
- attributes.expires = new Date(Date.now() + attributes.expires * 864e5);
71
+ const daysInMs = 864e5; // 24 * 60 * 60 * 1000
72
+ attributes.expires = new Date(Date.now() + attributes.expires * daysInMs);
38
73
  }
74
+
75
+ // Преобразуем дату в строку, если есть
39
76
  if (attributes.expires) {
40
77
  attributes.expires = attributes.expires.toUTCString();
41
78
  }
42
79
 
80
+ // Кодируем ключ
43
81
  key = encodeURIComponent(key)
44
82
  .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)
45
83
  .replace(/[()]/g, escape);
46
84
 
85
+ // Формируем строку атрибутов
47
86
  let stringifiedAttributes = '';
48
- for (let attributeName in attributes) {
49
- if (!attributes[attributeName]) {
50
- continue
51
- }
87
+ Object.keys(attributes).forEach(attributeName => {
88
+ if (!attributes[attributeName]) return;
52
89
 
53
90
  stringifiedAttributes += '; ' + attributeName;
54
91
 
55
- if (attributes[attributeName] === true) {
56
- continue
92
+ // Булевые атрибуты (например, Secure) не требуют значения
93
+ if (attributes[attributeName] !== true) {
94
+ // RFC 6265: обрезаем значение до первого `;`
95
+ const sanitizedValue = String(attributes[attributeName]).split(';')[0];
96
+ stringifiedAttributes += '=' + sanitizedValue;
57
97
  }
98
+ });
58
99
 
59
- // Considers RFC 6265 section 5.2:
60
- // ...
61
- // 3. If the remaining unparsed-attributes contains a %x3B (";")
62
- // character:
63
- // Consume the characters of the unparsed-attributes up to,
64
- // not including, the first %x3B (";") character.
65
- // ...
66
- stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
67
- }
68
-
69
- return (document.cookie =
70
- key + '=' + converter.write(value, key) + stringifiedAttributes)
100
+ // Устанавливаем cookie
101
+ return (document.cookie = key + '=' + converter.write(value, key) + stringifiedAttributes);
71
102
  }
72
103
 
73
- function get (key) {
104
+ /**
105
+ * Получает значение cookie по ключу
106
+ */
107
+ function get(key) {
74
108
  if (typeof document === 'undefined' || (arguments.length && !key)) {
75
- return
109
+ return;
76
110
  }
77
111
 
78
- // To prevent the for loop in the first place assign an empty array
79
- // in case there are no cookies at all.
80
- let cookies = document.cookie ? document.cookie.split('; ') : [];
81
- let jar = {};
112
+ const cookies = document.cookie ? document.cookie.split('; ') : [];
113
+ const jar = {};
114
+
82
115
  for (let i = 0; i < cookies.length; i++) {
83
- let parts = cookies[i].split('=');
84
- let value = parts.slice(1).join('=');
116
+ const parts = cookies[i].split('=');
117
+ const value = parts.slice(1).join('=');
118
+ const encodedKey = parts[0];
85
119
 
86
120
  try {
87
- let foundKey = decodeURIComponent(parts[0]);
121
+ const foundKey = decodeURIComponent(encodedKey);
88
122
  jar[foundKey] = converter.read(value, foundKey);
89
123
 
90
- if (key === foundKey) {
91
- break
92
- }
93
- } catch (e) {}
124
+ // Прерываем, если нашли нужный ключ
125
+ if (key === foundKey) break;
126
+ } catch (e) {
127
+ // Игнорируем поврежденные cookie
128
+ }
94
129
  }
95
130
 
96
- return key ? jar[key] : jar
131
+ return key ? jar[key] : jar;
97
132
  }
98
133
 
99
- return Object.create({
100
- set: set,
101
- get: get,
134
+ // Возвращаем API
135
+ return Object.create(
136
+ {
137
+ set,
138
+ get,
139
+ /**
140
+ * Удаляет cookie, устанавливая срок действия в прошлое
141
+ */
102
142
  remove: function (key, attributes) {
103
- set(
104
- key,
105
- '',
106
- assign({}, attributes, {
107
- expires: -1
108
- })
109
- );
143
+ set(key, '', assign({}, attributes, { expires: -1 }));
110
144
  },
145
+
146
+ /**
147
+ * Создаёт новый экземпляр с новыми атрибутами по умолчанию
148
+ */
111
149
  withAttributes: function (attributes) {
112
- return init(this.converter, assign({}, this.attributes, attributes))
150
+ return init(this.converter, assign({}, this.attributes, attributes));
113
151
  },
152
+
153
+ /**
154
+ * Создаёт новый экземпляр с новым конвертером
155
+ */
114
156
  withConverter: function (converter) {
115
- return init(assign({}, this.converter, converter), this.attributes)
157
+ return init(assign({}, this.converter, converter), this.attributes);
116
158
  }
117
159
  },
118
160
  {
119
161
  attributes: { value: Object.freeze(defaultAttributes) },
120
162
  converter: { value: Object.freeze(converter) }
121
163
  }
122
- )
164
+ );
123
165
  }
124
166
 
125
- let api = init(defaultConverter, { path: '/' });
167
+ // Экспорт по умолчанию: экземпляр с атрибутом path: '/'
168
+ const Cookies = init(defaultConverter, { path: '/' });
126
169
 
127
- export default api;
170
+ export default Cookies;
@@ -3,49 +3,97 @@
3
3
  * Bootstrap data.js
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
- * Скрипт работает с коллекцией модулей. Подробнее тут https://learn.javascript.ru/map-set
6
+ * Управление данными-экземплярами, привязанными к DOM-элементам.
7
+ * Использует Map для эффективного хранения и контроля уникальности.
7
8
  */
8
9
 
9
10
  /**
10
- * Константы
11
+ * Внутренняя карта для хранения данных по элементам.
12
+ * Структура: Element → Map<Key, Instance>
11
13
  */
14
+ const elementMap = new Map();
12
15
 
13
- const elementMap = new Map()
16
+ /**
17
+ * Утилита для безопасного получения вложенной карты экземпляров.
18
+ * @param {Element} element
19
+ * @returns {Map<string, any>|null}
20
+ */
21
+ function getInstanceMap(element) {
22
+ if (!elementMap.has(element)) {
23
+ return null;
24
+ }
25
+ return elementMap.get(element);
26
+ }
27
+
28
+ /**
29
+ * Утилита для создания новой вложенной карты для элемента.
30
+ * @param {Element} element
31
+ * @returns {Map<string, any>}
32
+ */
33
+ function createInstanceMap(element) {
34
+ const map = new Map();
35
+ elementMap.set(element, map);
36
+ return map;
37
+ }
14
38
 
15
39
  export default {
40
+ /**
41
+ * Устанавливает экземпляр для элемента по ключу.
42
+ * Запрещает несколько экземпляров на один элемент.
43
+ *
44
+ * @param {Element} element - DOM-элемент
45
+ * @param {string} key - уникальный ключ (например, имя компонента)
46
+ * @param {any} instance - экземпляр класса или объект
47
+ */
16
48
  set(element, key, instance) {
17
- if (!elementMap.has(element)) {
18
- elementMap.set(element, new Map())
49
+ if (!getInstanceMap(element)) {
50
+ createInstanceMap(element);
19
51
  }
20
52
 
21
- const instanceMap = elementMap.get(element)
22
- if (!instanceMap.has(key) && instanceMap.size !== 0) {
23
- console.error(`VGApp не допускает более одного экземпляра для каждого элемента. Связанный экземпляр: ${Array.from(instanceMap.keys())[0]}.`)
24
- return
53
+ const instanceMap = getInstanceMap(element);
54
+
55
+ // Проверяем, есть ли уже экземпляр (кроме случая, если это первая запись)
56
+ if (instanceMap.size > 0 && !instanceMap.has(key)) {
57
+ const existingKey = Array.from(instanceMap.keys())[0];
58
+ console.error(
59
+ `VGApp не допускает более одного экземпляра для каждого элемента. Связанный экземпляр: ${existingKey}.`
60
+ );
61
+ return;
25
62
  }
26
63
 
27
64
  instanceMap.set(key, instance);
28
65
  },
29
66
 
67
+ /**
68
+ * Получает экземпляр по элементу и ключу.
69
+ *
70
+ * @param {Element} element - DOM-элемент
71
+ * @param {string} key - ключ
72
+ * @returns {any|null} - экземпляр или null
73
+ */
30
74
  get(element, key) {
31
- if (elementMap.has(element)) {
32
- return elementMap.get(element).get(key) || null
33
- }
75
+ const instanceMap = getInstanceMap(element);
76
+ if (!instanceMap) return null;
34
77
 
35
- return null
78
+ return instanceMap.get(key) || null;
36
79
  },
37
80
 
81
+ /**
82
+ * Удаляет экземпляр по ключу.
83
+ * Если у элемента не остаётся экземпляров — удаляет и сам элемент из хранилища.
84
+ *
85
+ * @param {Element} element - DOM-элемент
86
+ * @param {string} key - ключ
87
+ */
38
88
  remove(element, key) {
39
- if (!elementMap.has(element)) {
40
- return
41
- }
42
-
43
- const instanceMap = elementMap.get(element)
89
+ const instanceMap = getInstanceMap(element);
90
+ if (!instanceMap) return;
44
91
 
45
92
  instanceMap.delete(key);
46
93
 
94
+ // Очищаем корневую запись, если больше нет экземпляров
47
95
  if (instanceMap.size === 0) {
48
- elementMap.delete(element)
96
+ elementMap.delete(element);
49
97
  }
50
98
  }
51
- }
99
+ };