vgapp 0.8.0 → 0.8.2
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 +16 -1
- package/app/langs/en/buttons.json +14 -0
- package/app/langs/en/messages.json +3 -0
- package/app/langs/en/titles.json +3 -0
- package/app/langs/ru/buttons.json +14 -0
- package/app/langs/ru/messages.json +3 -0
- package/app/langs/ru/titles.json +3 -0
- package/app/modules/vgloadmore/js/vgloadmore.js +363 -112
- package/app/modules/vgloadmore/readme.md +145 -0
- package/app/modules/vgrollup/js/vgrollup.js +328 -160
- package/app/modules/vgrollup/readme.md +196 -0
- package/app/modules/vgselect/js/handlers.js +220 -0
- package/app/modules/vgselect/js/vgselect.js +783 -298
- package/app/modules/vgselect/readme.md +180 -0
- package/app/modules/vgselect/scss/_variables.scss +20 -0
- package/app/modules/vgselect/scss/vgselect.scss +42 -2
- package/app/modules/vgsidebar/js/vgsidebar.js +194 -84
- package/app/modules/vgsidebar/readme.md +157 -0
- package/app/modules/vgspy/js/vgspy.js +236 -132
- package/app/modules/vgspy/readme.md +105 -0
- package/app/modules/vgtabs/js/vgtabs.js +290 -182
- package/app/modules/vgtabs/readme.md +156 -0
- package/app/modules/vgtoast/js/vgtoast.js +260 -156
- package/app/modules/vgtoast/readme.md +145 -0
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
import BaseModule from "../../base-module";
|
|
2
|
-
import {execute, isDisabled, mergeDeepObject} from "../../../utils/js/functions";
|
|
2
|
+
import { execute, isDisabled, mergeDeepObject } from "../../../utils/js/functions";
|
|
3
3
|
import EventHandler from "../../../utils/js/dom/event";
|
|
4
4
|
import Selectors from "../../../utils/js/dom/selectors";
|
|
5
|
+
import {lang_buttons} from "../../../utils/js/components/lang";
|
|
6
|
+
import {Classes, Manipulator} from "../../../utils/js/dom/manipulator";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @class VGRollup
|
|
10
|
+
* @extends BaseModule
|
|
11
|
+
* @description
|
|
12
|
+
* Модуль "Rollup" — реализует функционал сворачивания/разворачивания контента.
|
|
13
|
+
* Поддерживает два режима: текст (ограничение по высоте) и элементы (ограничение по количеству).
|
|
14
|
+
* Автоматически создаёт кнопку управления, если включена.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Инициализация через JS
|
|
18
|
+
* VGRollup.init(document.querySelector('.rollup'), {
|
|
19
|
+
* height: 100,
|
|
20
|
+
* button: {
|
|
21
|
+
* enabled: true,
|
|
22
|
+
* more: "Показать",
|
|
23
|
+
* less: "Свернуть"
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // Инициализация через data-атрибут
|
|
28
|
+
* // <div class="rollup" data-vg-rollup='{"height": 80, "button": {"more": "Еще"}}'>...</div>
|
|
29
|
+
*/
|
|
5
30
|
|
|
6
31
|
/**
|
|
7
32
|
* Constants
|
|
@@ -10,18 +35,46 @@ const NAME = 'rollup';
|
|
|
10
35
|
const NAME_KEY = 'vg.rollup';
|
|
11
36
|
const CLASS_NAME_SHOW = 'show';
|
|
12
37
|
const CLASS_NAME_HIDE = 'vg-rollup-display--none';
|
|
13
|
-
const SELECTOR_DATA_TOGGLE= '[data-vg-toggle="rollup"]'
|
|
14
|
-
|
|
15
|
-
const EVENT_KEY_HIDE = `${NAME_KEY}.hide`;
|
|
16
|
-
const EVENT_KEY_SHOW = `${NAME_KEY}.show`;
|
|
38
|
+
const SELECTOR_DATA_TOGGLE = '[data-vg-toggle="rollup"]';
|
|
17
39
|
|
|
40
|
+
const EVENT_KEY_HIDE = `${NAME_KEY}.hide`;
|
|
41
|
+
const EVENT_KEY_SHOW = `${NAME_KEY}.show`;
|
|
18
42
|
const EVENT_KEY_CLICK_DATA_API = `click.${NAME_KEY}.data.api`;
|
|
19
43
|
|
|
20
|
-
class VGRollup
|
|
44
|
+
class VGRollup extends BaseModule {
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @constructor
|
|
48
|
+
* @param {HTMLElement} element - Основной контейнер контента.
|
|
49
|
+
* @param {Object} params - Параметры конфигурации.
|
|
50
|
+
* @param {Object} [params.lang = 'ru'] - Локализация
|
|
51
|
+
* @param {string} [params.content='text'] - Режим: `'text'` (ограничение по высоте) или `'elements'` (по количеству).
|
|
52
|
+
* @param {number} [params.cnt=0] - Количество видимых элементов в режиме `'elements'`.
|
|
53
|
+
* @param {boolean} [params.fade=true] - Добавлять эффект затухания.
|
|
54
|
+
* @param {boolean} [params.transition=false] - Включить CSS-анимацию при переключении.
|
|
55
|
+
* @param {boolean} [params.number=false] - Показывать количество скрытых элементов.
|
|
56
|
+
* @param {number} [params.height=0] - Высота в px, до которой сворачивается текст.
|
|
57
|
+
* @param {Object} [params.ellipsis] - Настройки для многоточия.
|
|
58
|
+
* @param {number|null} [params.ellipsis.line=null] - Количество строк перед обрезкой (только для `display: -webkit-box`).
|
|
59
|
+
* @param {string} [params.more=' еще '] - Текст для отображения количества скрытых элементов.
|
|
60
|
+
* @param {Object} [params.button] - Настройки кнопки.
|
|
61
|
+
* @param {boolean} [params.button.enabled=true] - Показывать кнопку управления.
|
|
62
|
+
* @param {string} [params.button.more="Показать"] - Текст кнопки для раскрытия.
|
|
63
|
+
* @param {string} [params.button.less="Свернуть"] - Текст кнопки для сворачивания.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* new VGRollup(document.querySelector('.rollup'), {
|
|
67
|
+
* content: 'elements',
|
|
68
|
+
* elements: 'item',
|
|
69
|
+
* cnt: 3,
|
|
70
|
+
* button: { more: 'Показать ещё', less: 'Свернуть' }
|
|
71
|
+
* });
|
|
72
|
+
*/
|
|
21
73
|
constructor(element, params = {}) {
|
|
22
74
|
super(element, params);
|
|
23
75
|
|
|
24
76
|
this._params = this._getParams(element, mergeDeepObject({
|
|
77
|
+
lang: document.documentElement.lang || 'ru',
|
|
25
78
|
content: 'text',
|
|
26
79
|
cnt: 0,
|
|
27
80
|
fade: true,
|
|
@@ -33,12 +86,22 @@ class VGRollup extends BaseModule {
|
|
|
33
86
|
},
|
|
34
87
|
more: ' еще ',
|
|
35
88
|
button: {
|
|
36
|
-
|
|
89
|
+
enabled: true,
|
|
37
90
|
more: "Показать",
|
|
38
91
|
less: "Свернуть"
|
|
39
92
|
}
|
|
40
93
|
}, params));
|
|
41
94
|
|
|
95
|
+
/**
|
|
96
|
+
* CSS-классы, используемые модулем.
|
|
97
|
+
* @type {Object}
|
|
98
|
+
* @property {string} container - Базовый класс контейнера.
|
|
99
|
+
* @property {string} hidden - Класс для скрытого состояния.
|
|
100
|
+
* @property {string} fade - Класс для эффекта затухания.
|
|
101
|
+
* @property {string} ellipsis - Класс для многоточия.
|
|
102
|
+
* @property {string} button - Класс контейнера кнопки.
|
|
103
|
+
* @property {string} transition - Класс для анимации.
|
|
104
|
+
*/
|
|
42
105
|
this.classes = {
|
|
43
106
|
container: 'vg-rollup',
|
|
44
107
|
hidden: "vg-rollup-content--hidden",
|
|
@@ -48,201 +111,306 @@ class VGRollup extends BaseModule {
|
|
|
48
111
|
transition: "vg-rollup-content--transition"
|
|
49
112
|
};
|
|
50
113
|
|
|
51
|
-
|
|
52
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Общее количество элементов (в режиме `elements`).
|
|
116
|
+
* @type {number}
|
|
117
|
+
*/
|
|
118
|
+
this.total = 0;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Количество видимых элементов (в режиме `elements`).
|
|
122
|
+
* @type {number}
|
|
123
|
+
*/
|
|
124
|
+
this.count = 0;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Смещение для подгрузки (если используется).
|
|
128
|
+
* @type {number}
|
|
129
|
+
*/
|
|
130
|
+
this.offset = 0;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Флаг активности режима смещения.
|
|
134
|
+
* @type {boolean}
|
|
135
|
+
*/
|
|
136
|
+
this.isOffset = false;
|
|
137
|
+
|
|
138
|
+
// Локализация текстов кнопок
|
|
139
|
+
this._params.button.more = lang_buttons(this._params.lang, NAME)['show'];
|
|
140
|
+
this._params.button.less = lang_buttons(this._params.lang, NAME)['less'];
|
|
141
|
+
this._params.more = lang_buttons(this._params.lang, NAME)['more'];
|
|
53
142
|
|
|
54
143
|
this.build();
|
|
55
144
|
}
|
|
56
145
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Имя модуля
|
|
148
|
+
* @type {string}
|
|
149
|
+
*/
|
|
150
|
+
static get NAME() { return NAME; }
|
|
60
151
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Ключ модуля (пространство имён событий)
|
|
154
|
+
* @type {string}
|
|
155
|
+
*/
|
|
156
|
+
static get NAME_KEY() { return NAME_KEY; }
|
|
64
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Переключает состояние контента (свёрнут/развёрнут).
|
|
160
|
+
* @param {HTMLElement} target - Целевой контейнер контента.
|
|
161
|
+
* @param {HTMLElement} relatedTarget - Кнопка, вызвавшая переключение.
|
|
162
|
+
* @static
|
|
163
|
+
* @example
|
|
164
|
+
* VGRollup.toggle(document.querySelector('.rollup'), buttonEl);
|
|
165
|
+
*/
|
|
65
166
|
static toggle(target, relatedTarget) {
|
|
66
167
|
const instance = VGRollup.getOrCreateInstance(target);
|
|
67
|
-
|
|
168
|
+
const isShown = instance.isShow();
|
|
68
169
|
|
|
69
170
|
if (!isShown) {
|
|
70
|
-
instance.
|
|
71
|
-
relatedTarget.innerHTML = instance._params.button.less;
|
|
72
|
-
relatedTarget.setAttribute("aria-expanded", true);
|
|
73
|
-
|
|
74
|
-
if (instance.offset > 0) {
|
|
75
|
-
if (instance.isOffset) {
|
|
76
|
-
relatedTarget.innerHTML = instance._params.button.more;
|
|
77
|
-
relatedTarget.setAttribute("aria-expanded", true);
|
|
78
|
-
} else {
|
|
79
|
-
relatedTarget.innerHTML = instance._params.button.less;
|
|
80
|
-
relatedTarget.setAttribute("aria-expanded", false);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
instance.switch(instance._element, false);
|
|
85
|
-
EventHandler.trigger(instance._element, EVENT_KEY_SHOW, { relatedTarget });
|
|
171
|
+
instance._show(relatedTarget);
|
|
86
172
|
} else {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
173
|
+
instance._hide(relatedTarget);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
90
176
|
|
|
91
|
-
|
|
92
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Открывает (разворачивает) контент.
|
|
179
|
+
* @param {HTMLElement} relatedTarget - Элемент, вызвавший событие (кнопка).
|
|
180
|
+
* @private
|
|
181
|
+
*/
|
|
182
|
+
_show(relatedTarget) {
|
|
183
|
+
Classes.add(this._element, CLASS_NAME_SHOW);
|
|
184
|
+
relatedTarget.innerHTML = this._params.button.less;
|
|
185
|
+
Manipulator.set(relatedTarget, 'aria-expanded', 'true');
|
|
186
|
+
|
|
187
|
+
if (this.offset > 0) {
|
|
188
|
+
relatedTarget.innerHTML = this.isOffset ? this._params.button.more : this._params.button.less;
|
|
189
|
+
Manipulator.set(relatedTarget, 'aria-expanded', this.isOffset ? "true" : "false");
|
|
190
|
+
}
|
|
93
191
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
192
|
+
this.switch(this._element, false);
|
|
193
|
+
EventHandler.trigger(this._element, EVENT_KEY_SHOW, { relatedTarget });
|
|
194
|
+
}
|
|
98
195
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Закрывает (сворачивает) контент.
|
|
198
|
+
* @param {HTMLElement} relatedTarget - Элемент, вызвавший событие (кнопка).
|
|
199
|
+
* @private
|
|
200
|
+
*/
|
|
201
|
+
_hide(relatedTarget) {
|
|
202
|
+
let buttonText = this._params.button.more;
|
|
203
|
+
const isShowNum = this._params.number;
|
|
204
|
+
|
|
205
|
+
if (isShowNum) {
|
|
206
|
+
const sum = this.total - this.count;
|
|
207
|
+
if (sum > 0) {
|
|
208
|
+
buttonText += this._params.more + sum;
|
|
103
209
|
}
|
|
210
|
+
}
|
|
104
211
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
212
|
+
Classes.remove(this._element, CLASS_NAME_SHOW);
|
|
213
|
+
Manipulator.set(relatedTarget, 'aria-expanded', 'false');
|
|
214
|
+
relatedTarget.textContent = buttonText;
|
|
108
215
|
|
|
109
|
-
|
|
110
|
-
}
|
|
216
|
+
this.switch(this._element, true);
|
|
217
|
+
EventHandler.trigger(this._element, EVENT_KEY_HIDE, { relatedTarget });
|
|
111
218
|
}
|
|
112
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Инициализирует отображение контента и создаёт кнопку (если нужно).
|
|
222
|
+
* @param {HTMLElement|null} el - Элемент, который нужно инициализировать.
|
|
223
|
+
* @param {boolean} isButtonAppend - Разрешено ли добавление кнопки.
|
|
224
|
+
* @example
|
|
225
|
+
* instance.build(); // перестроить текущий элемент
|
|
226
|
+
*/
|
|
113
227
|
build(el = null, isButtonAppend = true) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
items = element.querySelectorAll('.' + elementClass),
|
|
139
|
-
cnt = _this._params.cnt || 5,
|
|
140
|
-
i = 1;
|
|
141
|
-
|
|
142
|
-
_this.total = items.length;
|
|
143
|
-
_this.count = cnt;
|
|
144
|
-
|
|
145
|
-
for (const item of items) {
|
|
146
|
-
if (i > cnt) {
|
|
147
|
-
item.classList.add(CLASS_NAME_HIDE)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
i++;
|
|
151
|
-
}
|
|
228
|
+
const element = el || this._element;
|
|
229
|
+
const selfHeight = element.clientHeight;
|
|
230
|
+
const setHeight = this._params.height || (selfHeight / 2);
|
|
231
|
+
|
|
232
|
+
const {
|
|
233
|
+
fade,
|
|
234
|
+
transition,
|
|
235
|
+
button,
|
|
236
|
+
number: showNum,
|
|
237
|
+
content,
|
|
238
|
+
elements: elementClass,
|
|
239
|
+
cnt,
|
|
240
|
+
ellipsis: ellipsisCfg
|
|
241
|
+
} = this._params;
|
|
242
|
+
|
|
243
|
+
const isEllipsis = ellipsisCfg.line !== null;
|
|
244
|
+
const isButton = button.enabled && isButtonAppend;
|
|
245
|
+
|
|
246
|
+
Classes.add(element, this.classes.container);
|
|
247
|
+
|
|
248
|
+
if (!isButtonAppend) {
|
|
249
|
+
this.switch(element);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
152
252
|
|
|
153
|
-
|
|
253
|
+
if (content === 'text' && selfHeight > setHeight) {
|
|
254
|
+
this._setupTextContent(element, setHeight, fade, transition, isEllipsis, ellipsisCfg.line, isButton, showNum);
|
|
255
|
+
} else if (content === 'elements') {
|
|
256
|
+
this._setupElementsContent(element, elementClass, cnt, fade, transition, isEllipsis, isButton, showNum);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
154
259
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Настраивает контент типа 'text' (ограничение по высоте).
|
|
262
|
+
* @param {HTMLElement} element - Контейнер текста.
|
|
263
|
+
* @param {number} height - Высота, до которой обрезать.
|
|
264
|
+
* @param {boolean} fade - Использовать затухание.
|
|
265
|
+
* @param {boolean} transition - Использовать анимацию.
|
|
266
|
+
* @param {boolean} isEllipsis - Использовать многоточие.
|
|
267
|
+
* @param {number|null} line - Количество строк.
|
|
268
|
+
* @param {boolean} isButton - Показывать кнопку.
|
|
269
|
+
* @param {boolean} showNum - Показывать счётчик.
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
_setupTextContent(element, height, fade, transition, isEllipsis, line, isButton, showNum) {
|
|
273
|
+
Classes.add(element, this.classes.hidden);
|
|
274
|
+
element.style.height = height + "px";
|
|
275
|
+
|
|
276
|
+
if (isEllipsis && line) {
|
|
277
|
+
Classes.add(element, this.classes.ellipsis);
|
|
278
|
+
element.style.lineClamp = Number(line);
|
|
279
|
+
} else if (isEllipsis) {
|
|
280
|
+
console.error("Переменная [data-line] или параметр[line] не должны быть пустыми");
|
|
159
281
|
}
|
|
160
282
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
let line = _this._params.ellipsis.line;
|
|
164
|
-
isFade = false;
|
|
283
|
+
if (transition) Classes.add(element, this.classes.transition);
|
|
284
|
+
if (fade) Classes.add(element, this.classes.fade);
|
|
165
285
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
element.style.webkitLineClamp = line;
|
|
169
|
-
} else {
|
|
170
|
-
console.error("Переменная [data-line] или параметр[line] не должны быть пустыми");
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
286
|
+
if (isButton) this._createButton(element, '', showNum);
|
|
287
|
+
}
|
|
174
288
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
289
|
+
/**
|
|
290
|
+
* Настраивает контент типа 'elements' (ограничение по количеству).
|
|
291
|
+
* @param {HTMLElement} element - Контейнер элементов.
|
|
292
|
+
* @param {string} elementClass - Класс видимых элементов.
|
|
293
|
+
* @param {number} cnt - Количество видимых элементов.
|
|
294
|
+
* @param {boolean} fade - Использовать затухание.
|
|
295
|
+
* @param {boolean} transition - Использовать анимацию.
|
|
296
|
+
* @param {boolean} isEllipsis - Использовать многоточие.
|
|
297
|
+
* @param {boolean} isButton - Показывать кнопку.
|
|
298
|
+
* @param {boolean} showNum - Показывать счётчик.
|
|
299
|
+
* @private
|
|
300
|
+
*/
|
|
301
|
+
_setupElementsContent(element, elementClass, cnt, fade, transition, isEllipsis, isButton, showNum) {
|
|
302
|
+
const items = Selectors.findAll('.' + elementClass, element);
|
|
303
|
+
this.total = items.length;
|
|
304
|
+
this.count = cnt;
|
|
305
|
+
|
|
306
|
+
items.forEach((item, index) => {
|
|
307
|
+
if (index >= cnt) {
|
|
308
|
+
Classes.add(item, CLASS_NAME_HIDE);
|
|
179
309
|
}
|
|
180
|
-
}
|
|
310
|
+
});
|
|
181
311
|
|
|
182
|
-
|
|
183
|
-
if (isFade) {
|
|
184
|
-
element.classList.add(_this.classes.fade);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
312
|
+
const shouldShowButton = isButton && items.length > cnt;
|
|
187
313
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
314
|
+
if (isEllipsis) Classes.add(element, this.classes.ellipsis);
|
|
315
|
+
if (transition) Classes.add(element, this.classes.transition);
|
|
316
|
+
if (fade) Classes.add(element, this.classes.fade);
|
|
191
317
|
|
|
192
|
-
|
|
193
|
-
|
|
318
|
+
if (shouldShowButton) {
|
|
319
|
+
const sum = this.total - this.count;
|
|
320
|
+
const textShowNum = showNum && sum > 0 ? this._params.more + sum : '';
|
|
321
|
+
this._createButton(element, textShowNum, false);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
194
324
|
|
|
195
|
-
|
|
196
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Создаёт кнопку управления разворачиванием.
|
|
327
|
+
* @param {HTMLElement} element - Целевой контейнер.
|
|
328
|
+
* @param {string} textNum - Дополнительный текст (например, количество).
|
|
329
|
+
* @param {boolean} showNum - Флаг отображения числа (не используется).
|
|
330
|
+
* @private
|
|
331
|
+
*/
|
|
332
|
+
_createButton(element, textNum = '', showNum = false) {
|
|
333
|
+
if (!element.id) {
|
|
334
|
+
element.id = `vg-rollup-${Math.random().toString(36).substr(2, 9)}`;
|
|
335
|
+
}
|
|
197
336
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
337
|
+
const btnTextMore = this._params.button.more;
|
|
338
|
+
const btnHTML = `<div class="${this.classes.button}">
|
|
339
|
+
<a href="#" aria-expanded="false" data-vg-toggle="rollup" data-vg-target="#${element.id}">
|
|
340
|
+
${btnTextMore}${textNum}
|
|
341
|
+
</a>
|
|
342
|
+
</div>`;
|
|
202
343
|
|
|
203
|
-
|
|
204
|
-
element.insertAdjacentHTML("afterend", "<div class=\"" + _this.classes.button + "\"><a href=\"#\" aria-expanded=\"false\" data-vg-toggle=\"rollup\" data-vg-target=\"#" + element.id + "\">" + btnTextMore + textShowNum + "</a></div>");
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
344
|
+
element.insertAdjacentHTML("afterend", btnHTML);
|
|
208
345
|
}
|
|
209
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Переключает состояние скрытия/показа контента.
|
|
349
|
+
* @param {HTMLElement} el - Элемент контента.
|
|
350
|
+
* @param {boolean} switcher - Если `true` — свернуть, иначе — полностью открыть.
|
|
351
|
+
* @example
|
|
352
|
+
* instance.switch(element, true); // свернуть
|
|
353
|
+
* instance.switch(element, false); // развернуть
|
|
354
|
+
*/
|
|
210
355
|
switch(el, switcher = false) {
|
|
211
356
|
if (switcher && !this.isOffset) {
|
|
212
|
-
this.
|
|
357
|
+
const { content } = this._params;
|
|
358
|
+
const selfHeight = el.clientHeight;
|
|
359
|
+
const setHeight = this._params.height || selfHeight / 2;
|
|
213
360
|
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
} else {
|
|
219
|
-
el.classList.remove(this.classes.hidden);
|
|
220
|
-
el.classList.remove(this.classes.ellipsis);
|
|
221
|
-
el.classList.remove(this.classes.fade);
|
|
361
|
+
if (content === 'text' && selfHeight > setHeight) {
|
|
362
|
+
Classes.add(el, this.classes.hidden);
|
|
363
|
+
el.style.height = setHeight + "px";
|
|
222
364
|
|
|
223
|
-
|
|
365
|
+
if (this._params.ellipsis.line) {
|
|
366
|
+
Classes.add(el, this.classes.ellipsis);
|
|
367
|
+
el.style.lineClamp = this._params.ellipsis.line;
|
|
368
|
+
}
|
|
224
369
|
|
|
225
|
-
|
|
226
|
-
|
|
370
|
+
if (this._params.fade) Classes.add(el, this.classes.fade);
|
|
371
|
+
if (this._params.transition) Classes.add(el, this.classes.transition);
|
|
372
|
+
} else if (content === 'elements') {
|
|
373
|
+
const items = Selectors.findAll('.' + this._params.elements, el);
|
|
374
|
+
items.forEach((item, index) => {
|
|
375
|
+
if (index >= this.count) {
|
|
376
|
+
Classes.add(item, CLASS_NAME_HIDE);
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
227
380
|
|
|
228
|
-
|
|
381
|
+
Classes.add(el, this.classes.container);
|
|
382
|
+
} else {
|
|
383
|
+
const { hidden, ellipsis, fade } = this.classes;
|
|
384
|
+
Classes.remove(el, [hidden, ellipsis, fade]);
|
|
385
|
+
Manipulator.remove(el, 'style');
|
|
229
386
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
387
|
+
if (this._params.content === 'elements') {
|
|
388
|
+
const items = Selectors.findAll('.' + this._params.elements, el);
|
|
389
|
+
items.forEach(item => Classes.remove(item, CLASS_NAME_HIDE));
|
|
233
390
|
}
|
|
234
391
|
}
|
|
235
392
|
}
|
|
236
393
|
|
|
394
|
+
/**
|
|
395
|
+
* Проверяет, развёрнут ли контент.
|
|
396
|
+
* @returns {boolean} `true`, если контент развёрнут.
|
|
397
|
+
* @example
|
|
398
|
+
* if (instance.isShow()) { ... }
|
|
399
|
+
*/
|
|
237
400
|
isShow() {
|
|
238
|
-
return this._element
|
|
401
|
+
return Classes.has(this._element, CLASS_NAME_SHOW);
|
|
239
402
|
}
|
|
240
403
|
|
|
241
404
|
/**
|
|
242
|
-
*
|
|
243
|
-
* @param element
|
|
244
|
-
* @param params
|
|
245
|
-
* @param callback
|
|
405
|
+
* Инициализирует экземпляр VGRollup для элемента.
|
|
406
|
+
* @param {HTMLElement} element - Целевой элемент.
|
|
407
|
+
* @param {Object} params - Параметры конфигурации.
|
|
408
|
+
* @param {Function} [callback] - Колбэк, вызываемый после инициализации.
|
|
409
|
+
* @static
|
|
410
|
+
* @example
|
|
411
|
+
* VGRollup.init(document.querySelector('.rollup'), { height: 100 }, (instance) => {
|
|
412
|
+
* console.log('Rollup инициализирован:', instance);
|
|
413
|
+
* });
|
|
246
414
|
*/
|
|
247
415
|
static init(element, params = {}, callback) {
|
|
248
416
|
const instance = VGRollup.getOrCreateInstance(element, params);
|
|
@@ -251,19 +419,19 @@ class VGRollup extends BaseModule {
|
|
|
251
419
|
}
|
|
252
420
|
|
|
253
421
|
/**
|
|
254
|
-
*
|
|
422
|
+
* Подключает обработчик кликов по data-атрибуту для автоматической инициализации.
|
|
423
|
+
* @listens click
|
|
424
|
+
* @event
|
|
255
425
|
*/
|
|
256
426
|
EventHandler.on(document, EVENT_KEY_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
|
257
|
-
const target = Selectors.getElementFromSelector(this);
|
|
258
|
-
if (!target) return;
|
|
259
|
-
|
|
260
427
|
if (['A', 'AREA'].includes(this.tagName)) {
|
|
261
|
-
event.preventDefault()
|
|
428
|
+
event.preventDefault();
|
|
262
429
|
}
|
|
263
430
|
|
|
264
|
-
if (isDisabled(this))
|
|
265
|
-
|
|
266
|
-
|
|
431
|
+
if (isDisabled(this)) return;
|
|
432
|
+
|
|
433
|
+
const target = Selectors.getElementFromSelector(this);
|
|
434
|
+
if (!target) return;
|
|
267
435
|
|
|
268
436
|
VGRollup.toggle(target, this);
|
|
269
437
|
});
|