vgapp 1.2.5 → 1.2.6
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 +58 -35
- package/agents.md +2 -2
- package/app/modules/base-module.js +87 -10
- package/app/modules/vgalert/js/vgalert.js +3 -3
- package/app/modules/vgdynamictable/index.js +5 -0
- package/app/modules/vgdynamictable/js/editable.js +438 -0
- package/app/modules/vgdynamictable/js/expandable.js +248 -0
- package/app/modules/vgdynamictable/js/filters.js +450 -0
- package/app/modules/vgdynamictable/js/fixed.js +566 -0
- package/app/modules/vgdynamictable/js/options.js +646 -0
- package/app/modules/vgdynamictable/js/pagination.js +623 -0
- package/app/modules/vgdynamictable/js/search.js +82 -0
- package/app/modules/vgdynamictable/js/skeleton.js +136 -0
- package/app/modules/vgdynamictable/js/sortable.js +442 -0
- package/app/modules/vgdynamictable/js/summary-footer.js +284 -0
- package/app/modules/vgdynamictable/js/table-remote.js +821 -0
- package/app/modules/vgdynamictable/js/table-state.js +243 -0
- package/app/modules/vgdynamictable/js/table-url-state.js +444 -0
- package/app/modules/vgdynamictable/js/utils/common.js +48 -0
- package/app/modules/vgdynamictable/js/vgdynamictable.js +3829 -0
- package/app/modules/vgdynamictable/js/viewport.js +322 -0
- package/app/modules/vgdynamictable/readme.md +251 -0
- package/app/modules/vgdynamictable/scss/_actions.scss +193 -0
- package/app/modules/vgdynamictable/scss/_pagination.scss +183 -0
- package/app/modules/vgdynamictable/scss/_skeleton.scss +60 -0
- package/app/modules/vgdynamictable/scss/_sortable.scss +63 -0
- package/app/modules/vgdynamictable/scss/_table.scss +157 -0
- package/app/modules/vgdynamictable/scss/_variables.scss +130 -0
- package/app/modules/vgdynamictable/scss/vgdynamictable.scss +267 -0
- package/app/modules/vgrangeslider/index.js +3 -0
- package/app/modules/vgrangeslider/js/skins.js +222 -0
- package/app/modules/vgrangeslider/js/vgrangeslider.js +704 -0
- package/app/modules/vgrangeslider/readme.md +523 -0
- package/app/modules/vgrangeslider/scss/_variables.scss +53 -0
- package/app/modules/vgrangeslider/scss/vgrangeslider.scss +240 -0
- package/app/utils/js/components/ajax.js +116 -7
- package/build/vgapp.css +2 -3246
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +2 -30
- package/index.js +2 -0
- package/index.scss +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
const fixedColumnsMethods = {
|
|
2
|
+
_getFixedColumnsConfigRaw() {
|
|
3
|
+
const fixedOptions = this._params && this._params.fixed && typeof this._params.fixed === 'object'
|
|
4
|
+
? this._params.fixed
|
|
5
|
+
: {};
|
|
6
|
+
const optionRaw = fixedOptions.columns;
|
|
7
|
+
const attrRaw = this._element
|
|
8
|
+
? this._element.getAttribute('data-fixed-columns')
|
|
9
|
+
: null;
|
|
10
|
+
const raw = attrRaw !== null && attrRaw !== undefined && String(attrRaw).trim() !== ''
|
|
11
|
+
? attrRaw
|
|
12
|
+
: optionRaw;
|
|
13
|
+
return String(raw || '').trim();
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
_hasFixedColumnsConfig() {
|
|
17
|
+
const attr = this._getFixedColumnsConfigRaw();
|
|
18
|
+
if (attr !== '') {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const headers = this._element && this._element.tHead
|
|
22
|
+
? Array.from(this._element.tHead.querySelectorAll('th'))
|
|
23
|
+
: [];
|
|
24
|
+
return headers.some((header) => {
|
|
25
|
+
const fixedAttr = String(header.getAttribute('data-fixed') || '').toLowerCase().trim();
|
|
26
|
+
const fixedColumnAttr = String(header.getAttribute('data-fixed-column') || '').toLowerCase().trim();
|
|
27
|
+
return fixedAttr === 'left' || fixedAttr === 'right' || fixedColumnAttr === 'left' || fixedColumnAttr === 'right';
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
_buildFixedColumnsStateMap(fixed) {
|
|
32
|
+
const state = new Map();
|
|
33
|
+
const left = Array.isArray(fixed && fixed.left) ? fixed.left : [];
|
|
34
|
+
const right = Array.isArray(fixed && fixed.right) ? fixed.right : [];
|
|
35
|
+
left.forEach((index) => {
|
|
36
|
+
if (Number.isInteger(index) && index >= 0) {
|
|
37
|
+
state.set(index, 'left');
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
right.forEach((index) => {
|
|
41
|
+
if (Number.isInteger(index) && index >= 0 && !state.has(index)) {
|
|
42
|
+
state.set(index, 'right');
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return state;
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
_collectFixedColumnsTransitions(nextState) {
|
|
49
|
+
const previousState = this._fixedColumnsLastStateMap instanceof Map
|
|
50
|
+
? this._fixedColumnsLastStateMap
|
|
51
|
+
: new Map();
|
|
52
|
+
const transitions = [];
|
|
53
|
+
nextState.forEach((side, index) => {
|
|
54
|
+
if (previousState.get(index) !== side) {
|
|
55
|
+
transitions.push({ index, side });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
this._fixedColumnsLastStateMap = nextState;
|
|
59
|
+
return transitions;
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
_applyFixedColumnsLayout() {
|
|
63
|
+
if (!this._element) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const suppressFixedColumns = Boolean(this._fixedColumnsSuppressed);
|
|
67
|
+
|
|
68
|
+
const sourceHeaders = this._element.tHead ? Array.from(this._element.tHead.querySelectorAll('th')) : [];
|
|
69
|
+
const sourceFixedRaw = this._getFixedColumnsByHeaders(sourceHeaders, {
|
|
70
|
+
parseTableAttr: true,
|
|
71
|
+
fallbackByPosition: true,
|
|
72
|
+
});
|
|
73
|
+
const sourceFixed = suppressFixedColumns
|
|
74
|
+
? { left: [], right: [] }
|
|
75
|
+
: this._applyMobileFixedColumnsGuard(this._element, sourceFixedRaw);
|
|
76
|
+
const hasSourceFixed = sourceFixed.left.length > 0 || sourceFixed.right.length > 0;
|
|
77
|
+
this._element.classList.toggle('table-fixed-cols', hasSourceFixed);
|
|
78
|
+
if (this._parent) {
|
|
79
|
+
this._parent.classList.toggle('table-fixed-cols', hasSourceFixed);
|
|
80
|
+
}
|
|
81
|
+
const sourceFixedTransitions = this._collectFixedColumnsTransitions(
|
|
82
|
+
this._buildFixedColumnsStateMap(sourceFixed)
|
|
83
|
+
);
|
|
84
|
+
this._applyFixedColumnsToTable(this._element, sourceFixed, {
|
|
85
|
+
includeBody: true,
|
|
86
|
+
emitAction: true,
|
|
87
|
+
transitionedColumns: sourceFixedTransitions,
|
|
88
|
+
});
|
|
89
|
+
this._toggleFixedColumnsScrollBinding(hasSourceFixed);
|
|
90
|
+
|
|
91
|
+
const cloneTable = this._cloneStickyState && this._cloneStickyState.table
|
|
92
|
+
? this._cloneStickyState.table
|
|
93
|
+
: null;
|
|
94
|
+
if (cloneTable) {
|
|
95
|
+
const cloneHeaders = cloneTable.tHead ? Array.from(cloneTable.tHead.querySelectorAll('th')) : [];
|
|
96
|
+
const cloneFixedRaw = this._getFixedColumnsByHeaders(cloneHeaders, {
|
|
97
|
+
parseTableAttr: false,
|
|
98
|
+
fallbackByPosition: false,
|
|
99
|
+
});
|
|
100
|
+
const cloneFixed = hasSourceFixed
|
|
101
|
+
? this._applyMobileFixedColumnsGuard(cloneTable, cloneFixedRaw)
|
|
102
|
+
: { left: [], right: [] };
|
|
103
|
+
this._applyFixedColumnsToTable(cloneTable, cloneFixed, {
|
|
104
|
+
includeBody: false,
|
|
105
|
+
emitAction: false,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
this._rebuildFixedColumnsCellsCache();
|
|
109
|
+
this._syncFixedColumnsScroll({ immediate: true });
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
_applyMobileFixedColumnsGuard(table, fixed) {
|
|
113
|
+
const next = {
|
|
114
|
+
left: Array.isArray(fixed && fixed.left) ? fixed.left.slice() : [],
|
|
115
|
+
right: Array.isArray(fixed && fixed.right) ? fixed.right.slice() : [],
|
|
116
|
+
};
|
|
117
|
+
if (!this._isTouchDevice()) {
|
|
118
|
+
return next;
|
|
119
|
+
}
|
|
120
|
+
const viewportMetrics = this._getViewportWidthMetrics();
|
|
121
|
+
const viewportWidth = viewportMetrics
|
|
122
|
+
? viewportMetrics.effectiveWidth
|
|
123
|
+
: (table ? table.getBoundingClientRect().width : 0);
|
|
124
|
+
const isMobileViewport = viewportWidth > 0 && viewportWidth <= 768;
|
|
125
|
+
if (!isMobileViewport) {
|
|
126
|
+
return next;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const fixedIndexes = next.left.concat(next.right);
|
|
130
|
+
if (fixedIndexes.length <= 0) {
|
|
131
|
+
return next;
|
|
132
|
+
}
|
|
133
|
+
if (fixedIndexes.length > 1) {
|
|
134
|
+
return { left: [], right: [] };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const headerCells = table && table.tHead ? Array.from(table.tHead.querySelectorAll('th')) : [];
|
|
138
|
+
const fixedIndex = fixedIndexes[0];
|
|
139
|
+
const header = Number.isInteger(fixedIndex) && fixedIndex >= 0 && fixedIndex < headerCells.length
|
|
140
|
+
? headerCells[fixedIndex]
|
|
141
|
+
: null;
|
|
142
|
+
if (!header) {
|
|
143
|
+
return next;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const columnWidth = header.getBoundingClientRect().width || 0;
|
|
147
|
+
if (columnWidth > viewportWidth * 0.5) {
|
|
148
|
+
return { left: [], right: [] };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return next;
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
_getFixedColumnsByHeaders(headers, options = {}) {
|
|
155
|
+
const list = Array.isArray(headers) ? headers : [];
|
|
156
|
+
const parseTableAttr = options.parseTableAttr !== false;
|
|
157
|
+
const fallbackByPosition = options.fallbackByPosition !== false;
|
|
158
|
+
const byField = new Map();
|
|
159
|
+
const leftSet = new Set();
|
|
160
|
+
const rightSet = new Set();
|
|
161
|
+
const autoIndexes = [];
|
|
162
|
+
|
|
163
|
+
list.forEach((header, index) => {
|
|
164
|
+
const field = String(header.getAttribute('data-field') || '').trim();
|
|
165
|
+
if (field !== '') {
|
|
166
|
+
byField.set(field, index);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
list.forEach((header, index) => {
|
|
171
|
+
const fixedAttr = String(header.getAttribute('data-fixed') || '').toLowerCase().trim();
|
|
172
|
+
const fixedColumnAttr = String(header.getAttribute('data-fixed-column') || '').toLowerCase().trim();
|
|
173
|
+
const side = fixedAttr === 'left' || fixedAttr === 'right'
|
|
174
|
+
? fixedAttr
|
|
175
|
+
: (fixedColumnAttr === 'left' || fixedColumnAttr === 'right' ? fixedColumnAttr : '');
|
|
176
|
+
if (side === 'left') {
|
|
177
|
+
leftSet.add(index);
|
|
178
|
+
} else if (side === 'right') {
|
|
179
|
+
rightSet.add(index);
|
|
180
|
+
} else if (!parseTableAttr) {
|
|
181
|
+
const clonedSide = String(header.getAttribute('data-fixed-side') || '').toLowerCase().trim();
|
|
182
|
+
if (clonedSide === 'left') {
|
|
183
|
+
leftSet.add(index);
|
|
184
|
+
} else if (clonedSide === 'right') {
|
|
185
|
+
rightSet.add(index);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (parseTableAttr && this._element) {
|
|
191
|
+
const attrRaw = this._getFixedColumnsConfigRaw();
|
|
192
|
+
if (attrRaw !== '') {
|
|
193
|
+
const groups = attrRaw.split(';').map((item) => item.trim()).filter(Boolean);
|
|
194
|
+
groups.forEach((group) => {
|
|
195
|
+
const sideMatch = group.match(/^(left|right)\s*:\s*(.+)$/i);
|
|
196
|
+
const explicitSide = sideMatch ? sideMatch[1].toLowerCase() : '';
|
|
197
|
+
const valuesRaw = sideMatch ? sideMatch[2] : group;
|
|
198
|
+
const values = valuesRaw.split(',').map((item) => item.trim()).filter(Boolean);
|
|
199
|
+
values.forEach((name) => {
|
|
200
|
+
const index = byField.has(name) ? byField.get(name) : Number.parseInt(name, 10);
|
|
201
|
+
if (!Number.isInteger(index) || index < 0 || index >= list.length) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (explicitSide === 'left') {
|
|
205
|
+
leftSet.add(index);
|
|
206
|
+
} else if (explicitSide === 'right') {
|
|
207
|
+
rightSet.add(index);
|
|
208
|
+
} else {
|
|
209
|
+
autoIndexes.push(index);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
autoIndexes.forEach((index) => {
|
|
217
|
+
if (leftSet.has(index) || rightSet.has(index)) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const distanceLeft = index;
|
|
221
|
+
const distanceRight = Math.max(0, list.length - 1 - index);
|
|
222
|
+
if (distanceLeft <= distanceRight || !fallbackByPosition) {
|
|
223
|
+
leftSet.add(index);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
rightSet.add(index);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const left = Array.from(leftSet).sort((a, b) => a - b);
|
|
230
|
+
const right = Array.from(rightSet)
|
|
231
|
+
.filter((index) => !leftSet.has(index))
|
|
232
|
+
.sort((a, b) => a - b);
|
|
233
|
+
|
|
234
|
+
return { left, right };
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
_applyFixedColumnsToTable(table, fixed, options = {}) {
|
|
238
|
+
if (!table) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const includeBody = options.includeBody !== false;
|
|
242
|
+
const shouldEmitAction = options.emitAction !== false;
|
|
243
|
+
const transitionedColumns = Array.isArray(options.transitionedColumns)
|
|
244
|
+
? options.transitionedColumns
|
|
245
|
+
: [];
|
|
246
|
+
const sections = [];
|
|
247
|
+
if (table.tHead) {
|
|
248
|
+
sections.push(table.tHead);
|
|
249
|
+
}
|
|
250
|
+
if (includeBody && table.tBodies && table.tBodies.length) {
|
|
251
|
+
sections.push(...Array.from(table.tBodies));
|
|
252
|
+
}
|
|
253
|
+
if (includeBody && table.tFoot) {
|
|
254
|
+
sections.push(table.tFoot);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const rows = [];
|
|
258
|
+
sections.forEach((section) => {
|
|
259
|
+
rows.push(...Array.from(section.rows || []));
|
|
260
|
+
});
|
|
261
|
+
const hasFixed = fixed && (fixed.left.length > 0 || fixed.right.length > 0);
|
|
262
|
+
rows.forEach((row) => {
|
|
263
|
+
Array.from(row.cells || []).forEach((cell) => {
|
|
264
|
+
cell.removeAttribute('data-fixed-side');
|
|
265
|
+
cell.removeAttribute('data-fixed-edge');
|
|
266
|
+
cell.removeAttribute('data-fixed-shift');
|
|
267
|
+
cell.removeAttribute('data-fixed-shadow');
|
|
268
|
+
cell.removeAttribute('data-fixed-overlap');
|
|
269
|
+
cell.style.removeProperty('z-index');
|
|
270
|
+
cell.style.removeProperty('transform');
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
if (!hasFixed) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const headerCells = table.tHead ? Array.from(table.tHead.querySelectorAll('th')) : [];
|
|
279
|
+
const tableRect = table.getBoundingClientRect();
|
|
280
|
+
const viewportMetrics = this._getViewportWidthMetrics();
|
|
281
|
+
const viewportWidth = viewportMetrics
|
|
282
|
+
? viewportMetrics.effectiveWidth
|
|
283
|
+
: tableRect.width;
|
|
284
|
+
const metrics = {};
|
|
285
|
+
headerCells.forEach((cell, index) => {
|
|
286
|
+
const rect = cell.getBoundingClientRect();
|
|
287
|
+
metrics[index] = {
|
|
288
|
+
width: Math.max(0, rect.width),
|
|
289
|
+
left: Math.max(0, rect.left - tableRect.left),
|
|
290
|
+
height: Math.max(0, rect.height),
|
|
291
|
+
top: Math.max(0, rect.top - tableRect.top),
|
|
292
|
+
};
|
|
293
|
+
});
|
|
294
|
+
const leftOffsets = {};
|
|
295
|
+
let leftOffset = 0;
|
|
296
|
+
fixed.left.forEach((index) => {
|
|
297
|
+
const width = metrics[index] ? metrics[index].width : 0;
|
|
298
|
+
leftOffsets[index] = leftOffset;
|
|
299
|
+
leftOffset += width;
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
const rightOffsets = {};
|
|
303
|
+
let rightOffset = 0;
|
|
304
|
+
fixed.right.slice().sort((a, b) => b - a).forEach((index) => {
|
|
305
|
+
const width = metrics[index] ? metrics[index].width : 0;
|
|
306
|
+
rightOffsets[index] = rightOffset;
|
|
307
|
+
rightOffset += width;
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const leftEdgeIndex = fixed.left.length ? fixed.left[fixed.left.length - 1] : -1;
|
|
311
|
+
const rightEdgeIndex = fixed.right.length ? fixed.right[0] : -1;
|
|
312
|
+
rows.forEach((row) => {
|
|
313
|
+
const isHeaderRow = row.parentElement && row.parentElement.tagName === 'THEAD';
|
|
314
|
+
const zIndex = isHeaderRow ? 6 : 2;
|
|
315
|
+
|
|
316
|
+
fixed.left.forEach((index) => {
|
|
317
|
+
const cell = row.cells && row.cells[index] ? row.cells[index] : null;
|
|
318
|
+
if (!cell) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const metric = metrics[index] || { left: 0 };
|
|
322
|
+
const baseShift = leftOffsets[index] - metric.left;
|
|
323
|
+
cell.setAttribute('data-fixed-side', 'left');
|
|
324
|
+
cell.setAttribute('data-fixed-shift', String(baseShift));
|
|
325
|
+
cell.style.zIndex = String(zIndex);
|
|
326
|
+
if (index === leftEdgeIndex) {
|
|
327
|
+
cell.setAttribute('data-fixed-edge', 'right');
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
fixed.right.forEach((index) => {
|
|
332
|
+
const cell = row.cells && row.cells[index] ? row.cells[index] : null;
|
|
333
|
+
if (!cell) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const metric = metrics[index] || { left: 0, width: 0 };
|
|
337
|
+
const desiredLeft = viewportWidth - rightOffsets[index] - metric.width;
|
|
338
|
+
const baseShift = desiredLeft - metric.left;
|
|
339
|
+
cell.setAttribute('data-fixed-side', 'right');
|
|
340
|
+
cell.setAttribute('data-fixed-shift', String(baseShift));
|
|
341
|
+
cell.style.zIndex = String(zIndex);
|
|
342
|
+
if (index === rightEdgeIndex) {
|
|
343
|
+
cell.setAttribute('data-fixed-edge', 'left');
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
if (!shouldEmitAction || typeof this._emitAction !== 'function' || !transitionedColumns.length) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
transitionedColumns.forEach((entry) => {
|
|
353
|
+
const index = Number.isInteger(entry && entry.index) ? entry.index : -1;
|
|
354
|
+
const side = entry && (entry.side === 'left' || entry.side === 'right')
|
|
355
|
+
? entry.side
|
|
356
|
+
: '';
|
|
357
|
+
const headerCell = index >= 0 && index < headerCells.length
|
|
358
|
+
? headerCells[index]
|
|
359
|
+
: null;
|
|
360
|
+
if (!headerCell || !side) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const metric = metrics[index] || { left: 0, width: 0, top: 0, height: 0 };
|
|
365
|
+
const width = metric.width || 0;
|
|
366
|
+
const height = metric.height || 0;
|
|
367
|
+
const left = side === 'left'
|
|
368
|
+
? (leftOffsets[index] || 0)
|
|
369
|
+
: Math.max(0, viewportWidth - (rightOffsets[index] || 0) - width);
|
|
370
|
+
const right = side === 'right'
|
|
371
|
+
? (rightOffsets[index] || 0)
|
|
372
|
+
: Math.max(0, viewportWidth - left - width);
|
|
373
|
+
const top = metric.top || 0;
|
|
374
|
+
const bottom = Math.max(0, tableRect.height - top - height);
|
|
375
|
+
const field = String(headerCell.getAttribute('data-field') || '').trim();
|
|
376
|
+
const fallbackBaseShift = left - (metric.left || 0);
|
|
377
|
+
const attrBaseShift = Number.parseFloat(headerCell.getAttribute('data-fixed-shift') || '');
|
|
378
|
+
const baseShift = Number.isFinite(attrBaseShift) ? attrBaseShift : fallbackBaseShift;
|
|
379
|
+
const scrollLeft = this._tableViewport ? (this._tableViewport.scrollLeft || 0) : 0;
|
|
380
|
+
const fixedAtTs = Date.now();
|
|
381
|
+
|
|
382
|
+
this._emitAction('columnfixed', {
|
|
383
|
+
columnIndex: index,
|
|
384
|
+
side,
|
|
385
|
+
phase: 'fixed',
|
|
386
|
+
field,
|
|
387
|
+
column: {
|
|
388
|
+
index,
|
|
389
|
+
side,
|
|
390
|
+
field,
|
|
391
|
+
width,
|
|
392
|
+
height,
|
|
393
|
+
element: headerCell,
|
|
394
|
+
},
|
|
395
|
+
offsets: {
|
|
396
|
+
left,
|
|
397
|
+
right,
|
|
398
|
+
top,
|
|
399
|
+
bottom,
|
|
400
|
+
},
|
|
401
|
+
shift: {
|
|
402
|
+
base: baseShift,
|
|
403
|
+
current: baseShift + scrollLeft,
|
|
404
|
+
scrollLeft,
|
|
405
|
+
},
|
|
406
|
+
fixedAt: {
|
|
407
|
+
timestamp: fixedAtTs,
|
|
408
|
+
iso: new Date(fixedAtTs).toISOString(),
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
_toggleFixedColumnsScrollBinding(enabled) {
|
|
415
|
+
if (!this._tableViewport) {
|
|
416
|
+
this._resetFixedColumnsScrollSyncState();
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (enabled && !this._fixedColumnsScrollBound) {
|
|
420
|
+
this._tableViewport.addEventListener('scroll', this._boundFixedColumnsScroll, { passive: true });
|
|
421
|
+
this._fixedColumnsScrollBound = true;
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (!enabled && this._fixedColumnsScrollBound) {
|
|
425
|
+
this._tableViewport.removeEventListener('scroll', this._boundFixedColumnsScroll);
|
|
426
|
+
this._fixedColumnsScrollBound = false;
|
|
427
|
+
}
|
|
428
|
+
if (!enabled) {
|
|
429
|
+
this._resetFixedColumnsScrollSyncState();
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
|
|
433
|
+
_resetFixedColumnsScrollSyncState() {
|
|
434
|
+
if (this._fixedColumnsSyncFrame && typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function') {
|
|
435
|
+
window.cancelAnimationFrame(this._fixedColumnsSyncFrame);
|
|
436
|
+
}
|
|
437
|
+
this._fixedColumnsSyncFrame = 0;
|
|
438
|
+
this._fixedColumnsLastScrollLeft = 0;
|
|
439
|
+
this._fixedColumnsLastAppliedScrollLeft = Number.NaN;
|
|
440
|
+
this._fixedColumnsLastShadowStateKey = '';
|
|
441
|
+
this._fixedColumnsCellsCache = [];
|
|
442
|
+
this._fixedColumnsShadowTargetsCache = [];
|
|
443
|
+
this._fixedColumnsLastStateMap = new Map();
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
_rebuildFixedColumnsCellsCache() {
|
|
447
|
+
const tables = [this._element];
|
|
448
|
+
if (this._cloneStickyState && this._cloneStickyState.table) {
|
|
449
|
+
tables.push(this._cloneStickyState.table);
|
|
450
|
+
}
|
|
451
|
+
const normalizedTables = tables.filter(Boolean);
|
|
452
|
+
this._fixedColumnsCellsCache = normalizedTables
|
|
453
|
+
.map((table) => {
|
|
454
|
+
return Array.from(table.querySelectorAll('[data-fixed-side][data-fixed-shift]'))
|
|
455
|
+
.map((cell) => {
|
|
456
|
+
const baseShift = Number.parseFloat(cell.getAttribute('data-fixed-shift') || '0');
|
|
457
|
+
return {
|
|
458
|
+
cell,
|
|
459
|
+
baseShift: Number.isFinite(baseShift) ? baseShift : 0,
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
})
|
|
463
|
+
.filter((cells) => cells.length > 0);
|
|
464
|
+
this._fixedColumnsShadowTargetsCache = normalizedTables
|
|
465
|
+
.map((table) => {
|
|
466
|
+
return {
|
|
467
|
+
table,
|
|
468
|
+
edges: Array.from(table.querySelectorAll('[data-fixed-edge]')),
|
|
469
|
+
fixedCells: Array.from(table.querySelectorAll('[data-fixed-side]')),
|
|
470
|
+
};
|
|
471
|
+
})
|
|
472
|
+
.filter((entry) => entry.edges.length > 0 || entry.fixedCells.length > 0);
|
|
473
|
+
this._fixedColumnsLastAppliedScrollLeft = Number.NaN;
|
|
474
|
+
this._fixedColumnsLastShadowStateKey = '';
|
|
475
|
+
},
|
|
476
|
+
|
|
477
|
+
_syncFixedColumnsScroll(options = {}) {
|
|
478
|
+
if (!this._tableViewport) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const nextScrollLeft = this._tableViewport.scrollLeft || 0;
|
|
483
|
+
this._fixedColumnsLastScrollLeft = nextScrollLeft;
|
|
484
|
+
const immediate = Boolean(options && options.immediate);
|
|
485
|
+
if (!immediate && this._fixedColumnsLastAppliedScrollLeft === nextScrollLeft) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
if (immediate || typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function') {
|
|
489
|
+
this._flushFixedColumnsScrollSync(nextScrollLeft);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (this._fixedColumnsSyncFrame) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
this._fixedColumnsSyncFrame = window.requestAnimationFrame(() => {
|
|
496
|
+
this._fixedColumnsSyncFrame = 0;
|
|
497
|
+
this._flushFixedColumnsScrollSync(this._fixedColumnsLastScrollLeft);
|
|
498
|
+
});
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
_flushFixedColumnsScrollSync(scrollLeft) {
|
|
502
|
+
if (!this._fixedColumnsCellsCache.length) {
|
|
503
|
+
this._rebuildFixedColumnsCellsCache();
|
|
504
|
+
}
|
|
505
|
+
this._fixedColumnsCellsCache.forEach((cells) => {
|
|
506
|
+
cells.forEach(({ cell, baseShift }) => {
|
|
507
|
+
if (!cell || !cell.isConnected) {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const shift = baseShift + scrollLeft;
|
|
511
|
+
cell.style.transform = `translate3d(${shift}px, 0px, 0px)`;
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
this._fixedColumnsLastAppliedScrollLeft = scrollLeft;
|
|
515
|
+
this._syncFixedColumnsShadows();
|
|
516
|
+
},
|
|
517
|
+
|
|
518
|
+
_syncFixedColumnsShadows() {
|
|
519
|
+
if (!Array.isArray(this._fixedColumnsShadowTargetsCache) || !this._fixedColumnsShadowTargetsCache.length) {
|
|
520
|
+
this._rebuildFixedColumnsCellsCache();
|
|
521
|
+
}
|
|
522
|
+
const targets = Array.isArray(this._fixedColumnsShadowTargetsCache)
|
|
523
|
+
? this._fixedColumnsShadowTargetsCache
|
|
524
|
+
: [];
|
|
525
|
+
if (!targets.length) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const viewport = this._tableViewport;
|
|
530
|
+
const canScroll = Boolean(viewport && viewport.scrollWidth > viewport.clientWidth + 1);
|
|
531
|
+
const scrollLeft = viewport ? (viewport.scrollLeft || 0) : 0;
|
|
532
|
+
const maxScrollLeft = viewport ? Math.max(0, viewport.scrollWidth - viewport.clientWidth) : 0;
|
|
533
|
+
const showLeftFixedShadow = canScroll && scrollLeft > 0;
|
|
534
|
+
const showRightFixedShadow = canScroll && scrollLeft < maxScrollLeft - 1;
|
|
535
|
+
const nextStateKey = `${showLeftFixedShadow ? 1 : 0}:${showRightFixedShadow ? 1 : 0}`;
|
|
536
|
+
if (this._fixedColumnsLastShadowStateKey === nextStateKey) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
this._fixedColumnsLastShadowStateKey = nextStateKey;
|
|
540
|
+
|
|
541
|
+
targets.forEach(({ edges, fixedCells }) => {
|
|
542
|
+
edges.forEach((cell) => {
|
|
543
|
+
const edge = String(cell.getAttribute('data-fixed-edge') || '').toLowerCase().trim();
|
|
544
|
+
const shouldShow = (edge === 'right' && showLeftFixedShadow) || (edge === 'left' && showRightFixedShadow);
|
|
545
|
+
if (shouldShow) {
|
|
546
|
+
cell.setAttribute('data-fixed-shadow', '1');
|
|
547
|
+
} else {
|
|
548
|
+
cell.removeAttribute('data-fixed-shadow');
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
fixedCells.forEach((cell) => {
|
|
553
|
+
const side = String(cell.getAttribute('data-fixed-side') || '').toLowerCase().trim();
|
|
554
|
+
const hasOverlap = (side === 'left' && showLeftFixedShadow) || (side === 'right' && showRightFixedShadow);
|
|
555
|
+
if (hasOverlap) {
|
|
556
|
+
cell.setAttribute('data-fixed-overlap', '1');
|
|
557
|
+
} else {
|
|
558
|
+
cell.removeAttribute('data-fixed-overlap');
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
},
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
export default fixedColumnsMethods;
|
|
566
|
+
|