vgapp 1.1.0 → 1.1.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.
|
@@ -274,13 +274,18 @@ class VGFormSender extends BaseModule {
|
|
|
274
274
|
* @param {FormData|null} data - Дополнительные данные для отправки
|
|
275
275
|
*/
|
|
276
276
|
request(event, data = null) {
|
|
277
|
-
const _this = this;
|
|
278
|
-
const mergeFormData = (target, source) => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
277
|
+
const _this = this;
|
|
278
|
+
const mergeFormData = (target, source) => {
|
|
279
|
+
const replacedKeys = new Set();
|
|
280
|
+
source.forEach((value, key) => {
|
|
281
|
+
if (!replacedKeys.has(key)) {
|
|
282
|
+
target.delete(key);
|
|
283
|
+
replacedKeys.add(key);
|
|
284
|
+
}
|
|
285
|
+
target.append(key, value);
|
|
286
|
+
});
|
|
287
|
+
return target;
|
|
288
|
+
}
|
|
284
289
|
|
|
285
290
|
_this._alertBefore();
|
|
286
291
|
|
|
@@ -777,4 +782,4 @@ EventHandler.on(document, EVENT_SUBMIT_DATA_API, function (event) {
|
|
|
777
782
|
}
|
|
778
783
|
})
|
|
779
784
|
|
|
780
|
-
export default VGFormSender;
|
|
785
|
+
export default VGFormSender;
|
|
@@ -88,7 +88,13 @@ class VGRollup extends BaseModule {
|
|
|
88
88
|
button: {
|
|
89
89
|
enabled: true,
|
|
90
90
|
more: "Показать",
|
|
91
|
-
less: "Свернуть"
|
|
91
|
+
less: "Свернуть",
|
|
92
|
+
classes: ''
|
|
93
|
+
},
|
|
94
|
+
callbacks: {
|
|
95
|
+
init: () => {},
|
|
96
|
+
expand: () => {},
|
|
97
|
+
collapse: () => {}
|
|
92
98
|
}
|
|
93
99
|
}, params));
|
|
94
100
|
|
|
@@ -255,6 +261,8 @@ class VGRollup extends BaseModule {
|
|
|
255
261
|
} else if (content === 'elements') {
|
|
256
262
|
this._setupElementsContent(element, elementClass, cnt, fade, transition, isEllipsis, isButton, showNum);
|
|
257
263
|
}
|
|
264
|
+
|
|
265
|
+
execute(this._params.callbacks.init, [element, this])
|
|
258
266
|
}
|
|
259
267
|
|
|
260
268
|
/**
|
|
@@ -336,7 +344,7 @@ class VGRollup extends BaseModule {
|
|
|
336
344
|
|
|
337
345
|
const btnTextMore = this._params.button.more;
|
|
338
346
|
const btnHTML = `<div class="${this.classes.button}">
|
|
339
|
-
<a href="#" aria-expanded="false" data-vg-toggle="rollup" data-vg-target="#${element.id}">
|
|
347
|
+
<a href="#" aria-expanded="false" data-vg-toggle="rollup" class="${this._params.button.classes}" data-vg-target="#${element.id}">
|
|
340
348
|
${btnTextMore}${textNum}
|
|
341
349
|
</a>
|
|
342
350
|
</div>`;
|
|
@@ -369,6 +377,8 @@ class VGRollup extends BaseModule {
|
|
|
369
377
|
|
|
370
378
|
if (this._params.fade) Classes.add(el, this.classes.fade);
|
|
371
379
|
if (this._params.transition) Classes.add(el, this.classes.transition);
|
|
380
|
+
|
|
381
|
+
execute(this._params.callbacks.expand, [el, this])
|
|
372
382
|
} else if (content === 'elements') {
|
|
373
383
|
const items = Selectors.findAll('.' + this._params.elements, el);
|
|
374
384
|
items.forEach((item, index) => {
|
|
@@ -376,6 +386,8 @@ class VGRollup extends BaseModule {
|
|
|
376
386
|
Classes.add(item, CLASS_NAME_HIDE);
|
|
377
387
|
}
|
|
378
388
|
});
|
|
389
|
+
|
|
390
|
+
execute(this._params.callbacks.collapse, [el, items, this])
|
|
379
391
|
}
|
|
380
392
|
|
|
381
393
|
Classes.add(el, this.classes.container);
|
|
@@ -388,6 +400,8 @@ class VGRollup extends BaseModule {
|
|
|
388
400
|
const items = Selectors.findAll('.' + this._params.elements, el);
|
|
389
401
|
items.forEach(item => Classes.remove(item, CLASS_NAME_HIDE));
|
|
390
402
|
}
|
|
403
|
+
|
|
404
|
+
execute(this._params.callbacks.expand, [el, this])
|
|
391
405
|
}
|
|
392
406
|
}
|
|
393
407
|
|
|
@@ -52,6 +52,7 @@ const SELECTOR_DROPDOWN = `.${CLASS_NAME_DROPDOWN}`;
|
|
|
52
52
|
const SELECTOR_SEARCH_INPUT = `.${CLASS_NAME_SEARCH} input`;
|
|
53
53
|
const SELECTOR_LIST = `.${CLASS_NAME_LIST}`;
|
|
54
54
|
const SELECTOR_LOAD_MORE_BTN = `.${CLASS_NAME_LOAD_MORE}`;
|
|
55
|
+
const DATA_ATTR_COPY_EXCLUDE_DEFAULT = ['inited', 'updating', 'exclude'];
|
|
55
56
|
|
|
56
57
|
/**
|
|
57
58
|
* Класс VGSelect
|
|
@@ -67,8 +68,8 @@ class VGSelect extends BaseModule {
|
|
|
67
68
|
constructor(element, params = {}) {
|
|
68
69
|
super(element, params);
|
|
69
70
|
|
|
70
|
-
this._params = this._getParams(element, mergeDeepObject({
|
|
71
|
-
lang: document.documentElement.lang || 'ru',
|
|
71
|
+
this._params = this._getParams(element, mergeDeepObject({
|
|
72
|
+
lang: document.documentElement.lang || 'ru',
|
|
72
73
|
// Dropdown placement behavior:
|
|
73
74
|
// - none: default CSS positioning (no JS)
|
|
74
75
|
// - auto: choose top/bottom based on available space in overflow ancestor/viewport
|
|
@@ -87,9 +88,10 @@ class VGSelect extends BaseModule {
|
|
|
87
88
|
perpage: 20,
|
|
88
89
|
loadMoreText: 'Загрузить ещё',
|
|
89
90
|
},
|
|
90
|
-
close: true,
|
|
91
|
-
tree: false,
|
|
92
|
-
|
|
91
|
+
close: true,
|
|
92
|
+
tree: false,
|
|
93
|
+
exclude: 'data-filter-param',
|
|
94
|
+
placeholder: '',
|
|
93
95
|
onInit: null,
|
|
94
96
|
onShow: null,
|
|
95
97
|
onHide: null,
|
|
@@ -147,46 +149,46 @@ class VGSelect extends BaseModule {
|
|
|
147
149
|
* @param {HTMLElement} drop - Контейнер выпадающего списка
|
|
148
150
|
* @returns {HTMLElement} - Обновлённый список
|
|
149
151
|
*/
|
|
150
|
-
static buildListOptions(selector, drop, params = {}) {
|
|
151
|
-
let list = drop.querySelector(`.${CLASS_NAME_LIST}`);
|
|
152
|
-
if (!list) {
|
|
153
|
-
list = document.createElement('ul');
|
|
152
|
+
static buildListOptions(selector, drop, params = {}) {
|
|
153
|
+
let list = drop.querySelector(`.${CLASS_NAME_LIST}`);
|
|
154
|
+
if (!list) {
|
|
155
|
+
list = document.createElement('ul');
|
|
154
156
|
Classes.add(list, CLASS_NAME_LIST);
|
|
155
157
|
drop.appendChild(list);
|
|
156
158
|
} else {
|
|
157
159
|
list.innerHTML = '';
|
|
158
160
|
}
|
|
159
161
|
|
|
160
|
-
const optGroups = Selectors.findAll('optgroup', selector);
|
|
161
|
-
const fragment = document.createDocumentFragment();
|
|
162
|
-
const isTree = this._isTreeEnabled(selector, params);
|
|
163
|
-
|
|
164
|
-
if (optGroups.length > 0) {
|
|
165
|
-
optGroups.forEach(optGroup => {
|
|
166
|
-
const ol = document.createElement('ol');
|
|
167
|
-
Classes.add(ol, CLASS_NAME_OPTGROUP);
|
|
162
|
+
const optGroups = Selectors.findAll('optgroup', selector);
|
|
163
|
+
const fragment = document.createDocumentFragment();
|
|
164
|
+
const isTree = this._isTreeEnabled(selector, params);
|
|
165
|
+
|
|
166
|
+
if (optGroups.length > 0) {
|
|
167
|
+
optGroups.forEach(optGroup => {
|
|
168
|
+
const ol = document.createElement('ol');
|
|
169
|
+
Classes.add(ol, CLASS_NAME_OPTGROUP);
|
|
168
170
|
|
|
169
171
|
const label = document.createElement('li');
|
|
170
|
-
label.textContent = optGroup.label.trim();
|
|
171
|
-
Classes.add(label, CLASS_NAME_OPTGROUP_TITLE);
|
|
172
|
-
ol.appendChild(label);
|
|
173
|
-
|
|
174
|
-
VGSelect._createListItems(Selectors.findAll('option', optGroup), ol, selector, {
|
|
175
|
-
tree: isTree,
|
|
176
|
-
depth: isTree ? 1 : 0,
|
|
177
|
-
});
|
|
178
|
-
fragment.appendChild(ol);
|
|
179
|
-
});
|
|
180
|
-
list.appendChild(fragment);
|
|
181
|
-
} else {
|
|
182
|
-
VGSelect._createListItems(selector.options, list, selector, {
|
|
183
|
-
tree: isTree,
|
|
184
|
-
depth: 0,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return list;
|
|
189
|
-
}
|
|
172
|
+
label.textContent = optGroup.label.trim();
|
|
173
|
+
Classes.add(label, CLASS_NAME_OPTGROUP_TITLE);
|
|
174
|
+
ol.appendChild(label);
|
|
175
|
+
|
|
176
|
+
VGSelect._createListItems(Selectors.findAll('option', optGroup), ol, selector, {
|
|
177
|
+
tree: isTree,
|
|
178
|
+
depth: isTree ? 1 : 0,
|
|
179
|
+
});
|
|
180
|
+
fragment.appendChild(ol);
|
|
181
|
+
});
|
|
182
|
+
list.appendChild(fragment);
|
|
183
|
+
} else {
|
|
184
|
+
VGSelect._createListItems(selector.options, list, selector, {
|
|
185
|
+
tree: isTree,
|
|
186
|
+
depth: 0,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return list;
|
|
191
|
+
}
|
|
190
192
|
|
|
191
193
|
/**
|
|
192
194
|
* Создаёт <li> элементы из списка <option>
|
|
@@ -195,13 +197,13 @@ class VGSelect extends BaseModule {
|
|
|
195
197
|
* @param {HTMLSelectElement} selector - Исходный <select>
|
|
196
198
|
* @private
|
|
197
199
|
*/
|
|
198
|
-
static _createListItems(options, parent, selector, config = {}) {
|
|
199
|
-
const frag = document.createDocumentFragment();
|
|
200
|
-
const baseDepth = Number.isInteger(config.depth) ? config.depth : 0;
|
|
201
|
-
const treeEnabled = !!config.tree;
|
|
202
|
-
|
|
203
|
-
[...options].forEach((option) => {
|
|
204
|
-
if (option.hidden) return;
|
|
200
|
+
static _createListItems(options, parent, selector, config = {}) {
|
|
201
|
+
const frag = document.createDocumentFragment();
|
|
202
|
+
const baseDepth = Number.isInteger(config.depth) ? config.depth : 0;
|
|
203
|
+
const treeEnabled = !!config.tree;
|
|
204
|
+
|
|
205
|
+
[...options].forEach((option) => {
|
|
206
|
+
if (option.hidden) return;
|
|
205
207
|
|
|
206
208
|
// value атрибута может не быть или он может быть пустым -> для маппинга используем индекс
|
|
207
209
|
const rawValueAttr = option.getAttribute('value'); // null если атрибута нет
|
|
@@ -212,16 +214,16 @@ class VGSelect extends BaseModule {
|
|
|
212
214
|
const li = document.createElement('li');
|
|
213
215
|
li.textContent = text;
|
|
214
216
|
li.dataset.index = String(option.index);
|
|
215
|
-
li.dataset.value = value;
|
|
216
|
-
li.classList.add(CLASS_NAME_OPTION);
|
|
217
|
-
Manipulator.set(li, 'data-vg-toggle', 'select-option');
|
|
218
|
-
if (treeEnabled) {
|
|
219
|
-
const optionLevelRaw = option.dataset.level;
|
|
220
|
-
const optionLevel = Number.isFinite(Number(optionLevelRaw)) ? parseInt(optionLevelRaw, 10) : null;
|
|
221
|
-
const level = Math.max(0, optionLevel == null ? baseDepth : optionLevel);
|
|
222
|
-
li.dataset.level = String(level);
|
|
223
|
-
li.style.paddingLeft = `${16 + (level * 16)}px`;
|
|
224
|
-
}
|
|
217
|
+
li.dataset.value = value;
|
|
218
|
+
li.classList.add(CLASS_NAME_OPTION);
|
|
219
|
+
Manipulator.set(li, 'data-vg-toggle', 'select-option');
|
|
220
|
+
if (treeEnabled) {
|
|
221
|
+
const optionLevelRaw = option.dataset.level;
|
|
222
|
+
const optionLevel = Number.isFinite(Number(optionLevelRaw)) ? parseInt(optionLevelRaw, 10) : null;
|
|
223
|
+
const level = Math.max(0, optionLevel == null ? baseDepth : optionLevel);
|
|
224
|
+
li.dataset.level = String(level);
|
|
225
|
+
li.style.paddingLeft = `${16 + (level * 16)}px`;
|
|
226
|
+
}
|
|
225
227
|
|
|
226
228
|
// Раньше подсветка зависела от "явно выбранных" option (атрибут selected),
|
|
227
229
|
// из-за этого UI мог показывать placeholder, но DOM считал, что выбрана 1-я опция.
|
|
@@ -249,16 +251,35 @@ class VGSelect extends BaseModule {
|
|
|
249
251
|
frag.appendChild(li);
|
|
250
252
|
});
|
|
251
253
|
|
|
252
|
-
parent.appendChild(frag);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
static _isTreeEnabled(selector, params = {}) {
|
|
256
|
-
if (typeof params.tree === 'boolean') return params.tree;
|
|
257
|
-
if (selector?.dataset && typeof selector.dataset.tree !== 'undefined') {
|
|
258
|
-
return normalizeData(selector.dataset.tree) === true;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return false;
|
|
254
|
+
parent.appendChild(frag);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static _isTreeEnabled(selector, params = {}) {
|
|
258
|
+
if (typeof params.tree === 'boolean') return params.tree;
|
|
259
|
+
if (selector?.dataset && typeof selector.dataset.tree !== 'undefined') {
|
|
260
|
+
return normalizeData(selector.dataset.tree) === true;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
static _getDataAttrCopyExclusions(selector, params = {}) {
|
|
267
|
+
const rawExclude = typeof params.exclude === 'string'
|
|
268
|
+
? params.exclude
|
|
269
|
+
: (selector.dataset.exclude || '');
|
|
270
|
+
const customExcluded = rawExclude
|
|
271
|
+
.split(',')
|
|
272
|
+
.map(item => this._normalizeDataAttrKey(item))
|
|
273
|
+
.filter(Boolean);
|
|
274
|
+
|
|
275
|
+
return new Set([...DATA_ATTR_COPY_EXCLUDE_DEFAULT, ...customExcluded]);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static _normalizeDataAttrKey(value) {
|
|
279
|
+
return String(value || '')
|
|
280
|
+
.trim()
|
|
281
|
+
.replace(/^data-/, '')
|
|
282
|
+
.toLowerCase();
|
|
262
283
|
}
|
|
263
284
|
|
|
264
285
|
/**
|
|
@@ -319,7 +340,9 @@ class VGSelect extends BaseModule {
|
|
|
319
340
|
|
|
320
341
|
const elData = Manipulator.get(selector);
|
|
321
342
|
if (!isEmptyObj(elData)) {
|
|
343
|
+
const excludeDataAttrs = this._getDataAttrCopyExclusions(selector, params);
|
|
322
344
|
Object.keys(elData).forEach(key => {
|
|
345
|
+
if (excludeDataAttrs.has(key)) return;
|
|
323
346
|
Manipulator.set(container, `data-${key}`, elData[key]);
|
|
324
347
|
});
|
|
325
348
|
}
|
|
@@ -339,11 +362,11 @@ class VGSelect extends BaseModule {
|
|
|
339
362
|
tags.classList.add(CLASS_NAME_TAGS);
|
|
340
363
|
current.appendChild(tags);
|
|
341
364
|
|
|
342
|
-
const input = document.createElement('input');
|
|
343
|
-
input.type = 'text';
|
|
344
|
-
input.className = 'vg-select-multiple-input';
|
|
345
|
-
input.style.cssText = 'border:0;outline:none;background:transparent;padding:0;margin:0;min-width:1px;width:1px;height:1px;line-height:1;font:inherit;opacity:0;';
|
|
346
|
-
tags.appendChild(input);
|
|
365
|
+
const input = document.createElement('input');
|
|
366
|
+
input.type = 'text';
|
|
367
|
+
input.className = 'vg-select-multiple-input';
|
|
368
|
+
input.style.cssText = 'border:0;outline:none;background:transparent;padding:0;margin:0;min-width:1px;width:1px;height:1px;line-height:1;font:inherit;opacity:0;';
|
|
369
|
+
tags.appendChild(input);
|
|
347
370
|
|
|
348
371
|
input.addEventListener('focus', () => {
|
|
349
372
|
const inst = VGSelect.getInstance(input.closest(`.${CLASS_NAME_CONTAINER}`));
|
|
@@ -368,7 +391,7 @@ class VGSelect extends BaseModule {
|
|
|
368
391
|
dropdown.classList.add(CLASS_NAME_DROPDOWN);
|
|
369
392
|
container.appendChild(dropdown);
|
|
370
393
|
|
|
371
|
-
this.buildListOptions(selector, dropdown, params);
|
|
394
|
+
this.buildListOptions(selector, dropdown, params);
|
|
372
395
|
|
|
373
396
|
selector.insertAdjacentElement('afterend', container);
|
|
374
397
|
selector.dataset.inited = 'true';
|
|
@@ -571,7 +594,7 @@ class VGSelect extends BaseModule {
|
|
|
571
594
|
}
|
|
572
595
|
|
|
573
596
|
const drop = this._element.querySelector(SELECTOR_DROPDOWN);
|
|
574
|
-
VGSelect.buildListOptions(select, drop, this._params);
|
|
597
|
+
VGSelect.buildListOptions(select, drop, this._params);
|
|
575
598
|
VGSelect.updateUI(select);
|
|
576
599
|
}
|
|
577
600
|
|
|
@@ -765,26 +788,28 @@ class VGSelect extends BaseModule {
|
|
|
765
788
|
* @param {string} value - Значение для выбора
|
|
766
789
|
* @param {Object} [data] - Дополнительные данные
|
|
767
790
|
*/
|
|
768
|
-
static changeSelector(select, value, data = {}) {
|
|
769
|
-
const container = select.nextElementSibling;
|
|
770
|
-
const instance = container ? VGSelect.getInstance(container) : null;
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
const opt = select.querySelector(`option[value="${CSS.escape(normalizeData(value))}"]`);
|
|
791
|
+
static changeSelector(select, value, data = {}) {
|
|
792
|
+
const container = select.nextElementSibling;
|
|
793
|
+
const instance = container ? VGSelect.getInstance(container) : null;
|
|
794
|
+
|
|
795
|
+
select.setAttribute('data-updating', 'true');
|
|
796
|
+
try {
|
|
797
|
+
const opt = select.querySelector(`option[value="${CSS.escape(normalizeData(value))}"]`);
|
|
776
798
|
if (!opt) {
|
|
777
799
|
instance?._triggerEvent(EVENT_KEY_ERROR, { error: 'Option not found', value });
|
|
778
800
|
return;
|
|
779
801
|
}
|
|
780
802
|
|
|
781
|
-
const
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
803
|
+
const wasSelected = opt.selected;
|
|
804
|
+
const selectedText = opt.textContent.trim();
|
|
805
|
+
|
|
806
|
+
if (select.multiple) {
|
|
807
|
+
opt.selected = data?.selected === false ? false : true;
|
|
808
|
+
} else {
|
|
809
|
+
[...select.options].forEach(o => o.selected = false);
|
|
810
|
+
opt.selected = true;
|
|
811
|
+
select.value = opt.value;
|
|
812
|
+
}
|
|
788
813
|
|
|
789
814
|
this.updateUI(select);
|
|
790
815
|
|
|
@@ -807,9 +832,9 @@ class VGSelect extends BaseModule {
|
|
|
807
832
|
* @param {number} index
|
|
808
833
|
* @param {Object} [data]
|
|
809
834
|
*/
|
|
810
|
-
static changeSelectorByIndex(select, index, data = {}) {
|
|
811
|
-
const container = select.nextElementSibling;
|
|
812
|
-
const instance = container ? VGSelect.getInstance(container) : null;
|
|
835
|
+
static changeSelectorByIndex(select, index, data = {}) {
|
|
836
|
+
const container = select.nextElementSibling;
|
|
837
|
+
const instance = container ? VGSelect.getInstance(container) : null;
|
|
813
838
|
|
|
814
839
|
select.setAttribute('data-updating', 'true');
|
|
815
840
|
try {
|
|
@@ -819,13 +844,17 @@ class VGSelect extends BaseModule {
|
|
|
819
844
|
return;
|
|
820
845
|
}
|
|
821
846
|
|
|
822
|
-
const wasSelected = opt.selected;
|
|
823
|
-
const selectedText = opt.textContent.trim();
|
|
824
|
-
const value = opt.value;
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
847
|
+
const wasSelected = opt.selected;
|
|
848
|
+
const selectedText = opt.textContent.trim();
|
|
849
|
+
const value = opt.value;
|
|
850
|
+
|
|
851
|
+
if (select.multiple) {
|
|
852
|
+
opt.selected = data?.selected === false ? false : true;
|
|
853
|
+
} else {
|
|
854
|
+
[...select.options].forEach(o => o.selected = false);
|
|
855
|
+
opt.selected = true;
|
|
856
|
+
select.value = opt.value;
|
|
857
|
+
}
|
|
829
858
|
|
|
830
859
|
this.updateUI(select);
|
|
831
860
|
|
|
@@ -1131,13 +1160,13 @@ class VGSelect extends BaseModule {
|
|
|
1131
1160
|
optionsData = data.results;
|
|
1132
1161
|
}
|
|
1133
1162
|
|
|
1134
|
-
if (!Array.isArray(optionsData)) {
|
|
1135
|
-
instance?._triggerEvent(EVENT_KEY_ERROR, { error: 'Invalid data format: expected array' });
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
const treeEnabled = this._isTreeEnabled(select, instance?._params || {});
|
|
1139
|
-
|
|
1140
|
-
if (!preserve) {
|
|
1163
|
+
if (!Array.isArray(optionsData)) {
|
|
1164
|
+
instance?._triggerEvent(EVENT_KEY_ERROR, { error: 'Invalid data format: expected array' });
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
const treeEnabled = this._isTreeEnabled(select, instance?._params || {});
|
|
1168
|
+
|
|
1169
|
+
if (!preserve) {
|
|
1141
1170
|
// Удаление только не помеченных как data-preserve
|
|
1142
1171
|
[...select.querySelectorAll('option')].forEach(option => {
|
|
1143
1172
|
const parentOptGroup = option.closest('optgroup');
|
|
@@ -1151,62 +1180,62 @@ class VGSelect extends BaseModule {
|
|
|
1151
1180
|
if (og.children.length === 0 && !og.hasAttribute('data-preserve')) {
|
|
1152
1181
|
og.remove();
|
|
1153
1182
|
}
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
const appendOption = (item, parent, level = null) => {
|
|
1158
|
-
const option = document.createElement('option');
|
|
1159
|
-
const hasChildren = Array.isArray(item.children) && item.children.length > 0;
|
|
1160
|
-
|
|
1161
|
-
option.value = item.id || '';
|
|
1162
|
-
option.textContent = item.text || '';
|
|
1163
|
-
if (item.selected) option.selected = true;
|
|
1164
|
-
if (item.disabled) option.disabled = true;
|
|
1165
|
-
if (treeEnabled && Number.isInteger(level)) {
|
|
1166
|
-
option.setAttribute('data-level', String(level));
|
|
1167
|
-
if (hasChildren && !option.value) {
|
|
1168
|
-
option.disabled = true;
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
const dataAttrs = Object.keys(item).filter(k => !['id', 'text', 'selected', 'disabled', 'children'].includes(k));
|
|
1173
|
-
dataAttrs.forEach(key => {
|
|
1174
|
-
option.setAttribute(`data-${key}`, item[key]);
|
|
1175
|
-
});
|
|
1176
|
-
|
|
1177
|
-
parent.appendChild(option);
|
|
1178
|
-
};
|
|
1179
|
-
|
|
1180
|
-
const appendTreeOptions = (items, parent, level = 0) => {
|
|
1181
|
-
items.forEach(item => {
|
|
1182
|
-
appendOption(item, parent, level);
|
|
1183
|
-
if (Array.isArray(item.children) && item.children.length > 0) {
|
|
1184
|
-
appendTreeOptions(item.children, parent, level + 1);
|
|
1185
|
-
}
|
|
1186
|
-
});
|
|
1187
|
-
};
|
|
1188
|
-
|
|
1189
|
-
if (treeEnabled) {
|
|
1190
|
-
appendTreeOptions(optionsData, select, 0);
|
|
1191
|
-
} else {
|
|
1192
|
-
optionsData.forEach(item => {
|
|
1193
|
-
if (item.children && Array.isArray(item.children)) {
|
|
1194
|
-
const optgroup = document.createElement('optgroup');
|
|
1195
|
-
optgroup.label = item.text || '';
|
|
1196
|
-
if (item.disabled) optgroup.disabled = true;
|
|
1197
|
-
|
|
1198
|
-
item.children.forEach(child => appendOption(child, optgroup));
|
|
1199
|
-
|
|
1200
|
-
select.appendChild(optgroup);
|
|
1201
|
-
} else {
|
|
1202
|
-
appendOption(item, select);
|
|
1203
|
-
}
|
|
1204
|
-
});
|
|
1205
|
-
}
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
const appendOption = (item, parent, level = null) => {
|
|
1187
|
+
const option = document.createElement('option');
|
|
1188
|
+
const hasChildren = Array.isArray(item.children) && item.children.length > 0;
|
|
1189
|
+
|
|
1190
|
+
option.value = item.id || '';
|
|
1191
|
+
option.textContent = item.text || '';
|
|
1192
|
+
if (item.selected) option.selected = true;
|
|
1193
|
+
if (item.disabled) option.disabled = true;
|
|
1194
|
+
if (treeEnabled && Number.isInteger(level)) {
|
|
1195
|
+
option.setAttribute('data-level', String(level));
|
|
1196
|
+
if (hasChildren && !option.value) {
|
|
1197
|
+
option.disabled = true;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
const dataAttrs = Object.keys(item).filter(k => !['id', 'text', 'selected', 'disabled', 'children'].includes(k));
|
|
1202
|
+
dataAttrs.forEach(key => {
|
|
1203
|
+
option.setAttribute(`data-${key}`, item[key]);
|
|
1204
|
+
});
|
|
1205
|
+
|
|
1206
|
+
parent.appendChild(option);
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1209
|
+
const appendTreeOptions = (items, parent, level = 0) => {
|
|
1210
|
+
items.forEach(item => {
|
|
1211
|
+
appendOption(item, parent, level);
|
|
1212
|
+
if (Array.isArray(item.children) && item.children.length > 0) {
|
|
1213
|
+
appendTreeOptions(item.children, parent, level + 1);
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1218
|
+
if (treeEnabled) {
|
|
1219
|
+
appendTreeOptions(optionsData, select, 0);
|
|
1220
|
+
} else {
|
|
1221
|
+
optionsData.forEach(item => {
|
|
1222
|
+
if (item.children && Array.isArray(item.children)) {
|
|
1223
|
+
const optgroup = document.createElement('optgroup');
|
|
1224
|
+
optgroup.label = item.text || '';
|
|
1225
|
+
if (item.disabled) optgroup.disabled = true;
|
|
1226
|
+
|
|
1227
|
+
item.children.forEach(child => appendOption(child, optgroup));
|
|
1228
|
+
|
|
1229
|
+
select.appendChild(optgroup);
|
|
1230
|
+
} else {
|
|
1231
|
+
appendOption(item, select);
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1206
1235
|
|
|
1207
1236
|
if (isRebuild) {
|
|
1208
1237
|
const drop = container.querySelector(`.${CLASS_NAME_DROPDOWN}`);
|
|
1209
|
-
VGSelect.buildListOptions(select, drop, instance?._params || {});
|
|
1238
|
+
VGSelect.buildListOptions(select, drop, instance?._params || {});
|
|
1210
1239
|
instance?._triggerEvent(EVENT_KEY_REBUILD);
|
|
1211
1240
|
} else {
|
|
1212
1241
|
this.updateUI(select);
|