vgapp 1.4.7 → 1.4.9

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 (85) hide show
  1. package/README.md +24 -2
  2. package/app/modules/base-module.js +14 -2
  3. package/app/modules/module-fn.js +5 -4
  4. package/app/modules/vgalert/js/vgalert.js +21 -1
  5. package/app/modules/vgalert/scss/vgalert.scss +48 -0
  6. package/app/modules/vgdropdown/js/vgdropdown.js +58 -27
  7. package/app/modules/vgfilepreview/js/renderers/video-modal.js +5 -1
  8. package/app/modules/vgfilepreview/js/renderers/video.js +6 -1
  9. package/app/modules/vgfilepreview/js/vgfilepreview.js +5 -1
  10. package/app/modules/vgfiles/js/base.js +14 -5
  11. package/app/modules/vgfiles/js/droppable.js +37 -31
  12. package/app/modules/vgfiles/js/vgfiles.js +5 -2
  13. package/app/modules/vgfiles/scss/_variables.scss +3 -1
  14. package/app/modules/vgfiles/scss/vgfiles.scss +55 -10
  15. package/app/modules/vgformsender/js/vgformsender.js +5 -2
  16. package/app/modules/vgloadmore/js/vgloadmore.js +35 -7
  17. package/app/modules/vgnestable/js/vgnestable.js +140 -0
  18. package/app/modules/vgnestable/scss/_variables.scss +16 -9
  19. package/app/modules/vgnestable/scss/vgnestable.scss +35 -2
  20. package/app/modules/vgtable/index.js +3 -0
  21. package/app/modules/vgtable/js/_columns.js +567 -0
  22. package/app/modules/vgtable/js/_expandable.js +242 -0
  23. package/app/modules/vgtable/js/_filters.js +264 -0
  24. package/app/modules/vgtable/js/_fixed-columns.js +249 -0
  25. package/app/modules/vgtable/js/_i18n.js +75 -0
  26. package/app/modules/vgtable/js/_options.js +428 -0
  27. package/app/modules/vgtable/js/_pagination.js +491 -0
  28. package/app/modules/vgtable/js/_panning.js +124 -0
  29. package/app/modules/vgtable/js/_params-groups.js +21 -0
  30. package/app/modules/vgtable/js/_remote.js +395 -0
  31. package/app/modules/vgtable/js/_row-reorder.js +268 -0
  32. package/app/modules/vgtable/js/_search.js +134 -0
  33. package/app/modules/vgtable/js/_selection.js +113 -0
  34. package/app/modules/vgtable/js/_skeleton.js +123 -0
  35. package/app/modules/vgtable/js/_sorting.js +340 -0
  36. package/app/modules/vgtable/js/_states.js +143 -0
  37. package/app/modules/vgtable/js/_sticky-header.js +193 -0
  38. package/app/modules/vgtable/js/_url-state.js +178 -0
  39. package/app/modules/vgtable/js/vgtable.js +1444 -0
  40. package/app/modules/vgtable/readme.md +922 -0
  41. package/app/modules/vgtable/scss/_columns.scss +52 -0
  42. package/app/modules/vgtable/scss/_expandable.scss +54 -0
  43. package/app/modules/vgtable/scss/_fixed-columns.scss +117 -0
  44. package/app/modules/vgtable/scss/_pagination.scss +191 -0
  45. package/app/modules/vgtable/scss/_row-reorder.scss +45 -0
  46. package/app/modules/vgtable/scss/_skeleton.scss +65 -0
  47. package/app/modules/vgtable/scss/_sorting.scss +89 -0
  48. package/app/modules/vgtable/scss/_states.scss +70 -0
  49. package/app/modules/vgtable/scss/_sticky-header.scss +121 -0
  50. package/app/modules/vgtable/scss/_variables.scss +296 -0
  51. package/app/modules/vgtable/scss/vgtable.scss +206 -0
  52. package/app/utils/js/components/placement.js +64 -10
  53. package/app/vgapp.js +3 -3
  54. package/build/vgapp.css +1 -1
  55. package/build/vgapp.css.map +1 -1
  56. package/build/vgapp.js +1 -1
  57. package/build/vgapp.js.map +1 -1
  58. package/index.js +1 -1
  59. package/index.scss +3 -3
  60. package/package.json +5 -5
  61. package/app/modules/vgdynamictable/index.js +0 -4
  62. package/app/modules/vgdynamictable/js/editable.js +0 -438
  63. package/app/modules/vgdynamictable/js/expandable.js +0 -248
  64. package/app/modules/vgdynamictable/js/filters.js +0 -450
  65. package/app/modules/vgdynamictable/js/fixed.js +0 -566
  66. package/app/modules/vgdynamictable/js/options.js +0 -650
  67. package/app/modules/vgdynamictable/js/pagination.js +0 -623
  68. package/app/modules/vgdynamictable/js/search.js +0 -82
  69. package/app/modules/vgdynamictable/js/skeleton.js +0 -144
  70. package/app/modules/vgdynamictable/js/sortable.js +0 -442
  71. package/app/modules/vgdynamictable/js/summary-footer.js +0 -284
  72. package/app/modules/vgdynamictable/js/table-remote.js +0 -821
  73. package/app/modules/vgdynamictable/js/table-state.js +0 -243
  74. package/app/modules/vgdynamictable/js/table-url-state.js +0 -444
  75. package/app/modules/vgdynamictable/js/utils/common.js +0 -48
  76. package/app/modules/vgdynamictable/js/vgdynamictable.js +0 -3870
  77. package/app/modules/vgdynamictable/js/viewport.js +0 -322
  78. package/app/modules/vgdynamictable/readme.md +0 -251
  79. package/app/modules/vgdynamictable/scss/_actions.scss +0 -196
  80. package/app/modules/vgdynamictable/scss/_pagination.scss +0 -186
  81. package/app/modules/vgdynamictable/scss/_skeleton.scss +0 -63
  82. package/app/modules/vgdynamictable/scss/_sortable.scss +0 -66
  83. package/app/modules/vgdynamictable/scss/_table.scss +0 -137
  84. package/app/modules/vgdynamictable/scss/_variables.scss +0 -138
  85. package/app/modules/vgdynamictable/scss/vgdynamictable.scss +0 -264
@@ -1,248 +0,0 @@
1
- class Expandable {
2
- constructor(table, params = {}) {
3
- this._table = table;
4
- this._params = params && typeof params === 'object' ? params : {};
5
- this._collapsed = new Set();
6
- this._boundClick = this._handleClick.bind(this);
7
- this._initialized = false;
8
- }
9
-
10
- init() {
11
- if (!this._isEnabled() || this._initialized) {
12
- return;
13
- }
14
- this._table.addEventListener('click', this._boundClick);
15
- this._initialized = true;
16
- this.refresh();
17
- }
18
-
19
- destroy() {
20
- if (!this._initialized) {
21
- return;
22
- }
23
- this._table.removeEventListener('click', this._boundClick);
24
- this._initialized = false;
25
- }
26
-
27
- refresh() {
28
- if (!this._isEnabled()) {
29
- return;
30
- }
31
-
32
- const rows = this._getRows();
33
- if (!rows.length) {
34
- return;
35
- }
36
-
37
- this._resetExpandHidden(rows);
38
- this._rememberBaseVisibility(rows);
39
-
40
- const idAttr = this._getIdAttr();
41
- const parentAttr = this._getParentAttr();
42
- const rowById = new Map();
43
- const parentById = new Map();
44
- const childrenByParent = new Map();
45
-
46
- rows.forEach((row, index) => {
47
- const fallbackId = `row-${index + 1}`;
48
- const rowId = String(row.getAttribute(idAttr) || fallbackId).trim() || fallbackId;
49
- row.setAttribute(idAttr, rowId);
50
- rowById.set(rowId, row);
51
-
52
- const parentId = String(row.getAttribute(parentAttr) || '').trim();
53
- parentById.set(rowId, parentId);
54
- if (parentId) {
55
- if (!childrenByParent.has(parentId)) {
56
- childrenByParent.set(parentId, []);
57
- }
58
- childrenByParent.get(parentId).push(rowId);
59
- }
60
- });
61
-
62
- const depthCache = new Map();
63
- const getDepth = (rowId) => {
64
- if (depthCache.has(rowId)) {
65
- return depthCache.get(rowId);
66
- }
67
- const parentId = String(parentById.get(rowId) || '').trim();
68
- if (!parentId) {
69
- depthCache.set(rowId, 0);
70
- return 0;
71
- }
72
- if (!rowById.has(parentId) || parentId === rowId) {
73
- depthCache.set(rowId, 0);
74
- return 0;
75
- }
76
- const depth = Math.max(0, getDepth(parentId) + 1);
77
- depthCache.set(rowId, depth);
78
- return depth;
79
- };
80
-
81
- const isAncestorCollapsed = (rowId) => {
82
- let parentId = String(parentById.get(rowId) || '').trim();
83
- while (parentId) {
84
- if (this._collapsed.has(parentId)) {
85
- return true;
86
- }
87
- parentId = String(parentById.get(parentId) || '').trim();
88
- }
89
- return false;
90
- };
91
-
92
- rowById.forEach((row, rowId) => {
93
- const depth = getDepth(rowId);
94
- row.setAttribute('data-expand-depth', String(depth));
95
- row.style.setProperty('--vgdt-expand-depth', String(depth));
96
-
97
- const hasChildren = childrenByParent.has(rowId) && childrenByParent.get(rowId).length > 0;
98
- const seeded = row.getAttribute('data-expand-seeded') === '1';
99
- if (hasChildren && !seeded) {
100
- if (this._isInitiallyCollapsed(row)) {
101
- this._collapsed.add(rowId);
102
- }
103
- row.setAttribute('data-expand-seeded', '1');
104
- }
105
- this._syncToggleNode(row, rowId, hasChildren);
106
-
107
- const baseHidden = row.getAttribute('data-expand-base-hidden') === '1';
108
- const collapseHidden = isAncestorCollapsed(rowId);
109
- const nextHidden = baseHidden || collapseHidden;
110
- row.hidden = nextHidden;
111
- if (collapseHidden) {
112
- row.setAttribute('data-expand-hidden', '1');
113
- } else {
114
- row.removeAttribute('data-expand-hidden');
115
- }
116
- });
117
- }
118
-
119
- _handleClick(event) {
120
- const toggleSelector = this._getToggleSelector();
121
- const rawTarget = event.target || null;
122
- const target = rawTarget && rawTarget.nodeType === 3 ? rawTarget.parentElement : rawTarget;
123
- const toggle = target && target.closest ? target.closest(toggleSelector) : null;
124
- if (!toggle || !this._table.contains(toggle)) {
125
- return;
126
- }
127
- event.preventDefault();
128
-
129
- const row = toggle.closest('tr');
130
- if (!row) {
131
- return;
132
- }
133
- const rowId = String(row.getAttribute(this._getIdAttr()) || '').trim();
134
- if (!rowId) {
135
- return;
136
- }
137
-
138
- const collapsed = !this._collapsed.has(rowId);
139
- if (collapsed) {
140
- this._collapsed.add(rowId);
141
- } else {
142
- this._collapsed.delete(rowId);
143
- }
144
- this.refresh();
145
-
146
- const payload = {
147
- id: rowId,
148
- collapsed,
149
- row,
150
- };
151
- if (typeof this._params.onToggle === 'function') {
152
- this._params.onToggle(payload);
153
- }
154
- }
155
-
156
- _syncToggleNode(row, rowId, hasChildren) {
157
- const selector = this._getToggleSelector();
158
- let toggle = row.querySelector(selector);
159
- if (!toggle && hasChildren) {
160
- const firstCell = row.cells && row.cells[0] ? row.cells[0] : null;
161
- if (firstCell) {
162
- toggle = document.createElement('button');
163
- toggle.type = 'button';
164
- toggle.className = 'vgdt-expand-toggle';
165
- toggle.setAttribute('data-expand-toggle', '1');
166
- firstCell.prepend(toggle);
167
- }
168
- }
169
- if (!toggle) {
170
- return;
171
- }
172
-
173
- // Keep visual spacing stable even if CSS bundle is outdated.
174
- toggle.style.marginInlineEnd = '10px';
175
- toggle.style.cursor = 'pointer';
176
-
177
- const nextNode = toggle.nextSibling;
178
- const hasLeadingSpace = nextNode
179
- && nextNode.nodeType === 3
180
- && /^\s/.test(String(nextNode.textContent || ''));
181
- if (!hasLeadingSpace) {
182
- toggle.after(document.createTextNode(' '));
183
- }
184
-
185
- toggle.setAttribute('data-expand-toggle', rowId);
186
- toggle.setAttribute('aria-expanded', this._collapsed.has(rowId) ? 'false' : 'true');
187
- toggle.hidden = !hasChildren;
188
- if (!hasChildren) {
189
- return;
190
- }
191
- const collapsed = this._collapsed.has(rowId);
192
- toggle.textContent = collapsed ? '+' : '−';
193
- }
194
-
195
- _getRows() {
196
- const body = this._table.tBodies && this._table.tBodies[0];
197
- if (!body) {
198
- return [];
199
- }
200
- return Array.from(body.rows).filter((row) => !row.querySelector('[data-table-state]'));
201
- }
202
-
203
- _resetExpandHidden(rows) {
204
- rows.forEach((row) => {
205
- if (row.getAttribute('data-expand-hidden') === '1') {
206
- row.hidden = false;
207
- row.removeAttribute('data-expand-hidden');
208
- }
209
- });
210
- }
211
-
212
- _rememberBaseVisibility(rows) {
213
- rows.forEach((row) => {
214
- row.setAttribute('data-expand-base-hidden', row.hidden ? '1' : '0');
215
- });
216
- }
217
-
218
- _isInitiallyCollapsed(row) {
219
- const attr = row.getAttribute('data-expand-collapsed');
220
- if (attr !== null) {
221
- return this._isTruthy(attr);
222
- }
223
- return Boolean(this._params.collapsed);
224
- }
225
-
226
- _isEnabled() {
227
- return Boolean(this._params.enable);
228
- }
229
-
230
- _getIdAttr() {
231
- return String(this._params.idAttr || 'data-expand-id').trim() || 'data-expand-id';
232
- }
233
-
234
- _getParentAttr() {
235
- return String(this._params.parentAttr || 'data-expand-parent-id').trim() || 'data-expand-parent-id';
236
- }
237
-
238
- _getToggleSelector() {
239
- return String(this._params.toggleSelector || '[data-expand-toggle]').trim() || '[data-expand-toggle]';
240
- }
241
-
242
- _isTruthy(value) {
243
- const normalized = String(value || '').toLowerCase().trim();
244
- return normalized !== '' && normalized !== '0' && normalized !== 'false' && normalized !== 'off' && normalized !== 'no';
245
- }
246
- }
247
-
248
- export default Expandable;
@@ -1,450 +0,0 @@
1
- import {normalizeNonNegativeInt, safeQuerySelector} from "./utils/common";
2
-
3
- class Filters {
4
- constructor(options = {}) {
5
- this._options = Object.assign({
6
- enabled: true,
7
- formSelector: '',
8
- formNode: null,
9
- debounceMs: 300,
10
- applyMode: 'auto', // auto | manual
11
- button: {
12
- apply: '[data-filter-apply]',
13
- reset: '[data-filter-reset]',
14
- },
15
- fieldAttr: 'data-filter-field',
16
- partAttr: 'data-filter-part',
17
- typeAttr: 'data-filter-type',
18
- valueAttr: 'data-filter-value',
19
- operatorAttr: 'data-filter-operator',
20
- defaultOperator: 'eq',
21
- skipEmpty: true,
22
- trimValues: true,
23
- emitOnInit: false,
24
- initialValues: {},
25
- onChange: null,
26
- onReset: null,
27
- }, options);
28
-
29
- this._form = null;
30
- this._timer = null;
31
- this._controls = [];
32
- this._boundInput = this._handleInput.bind(this);
33
- this._boundChange = this._handleChange.bind(this);
34
- this._boundClick = this._handleClick.bind(this);
35
- this._boundSubmit = this._handleSubmit.bind(this);
36
- }
37
-
38
- init() {
39
- if (!this._options.enabled) {
40
- return;
41
- }
42
-
43
- const form = this._resolveFormNode();
44
- if (!form) {
45
- return;
46
- }
47
-
48
- this._form = form;
49
- this._syncCachedNodes();
50
- this._form.addEventListener('input', this._boundInput);
51
- this._form.addEventListener('change', this._boundChange);
52
- this._form.addEventListener('click', this._boundClick);
53
- this._form.addEventListener('submit', this._boundSubmit);
54
-
55
- this.setValues(this._options.initialValues || {}, { emit: false });
56
- if (this._options.emitOnInit) {
57
- this._emit();
58
- }
59
- }
60
-
61
- destroy() {
62
- if (!this._form) {
63
- return;
64
- }
65
- this._form.removeEventListener('input', this._boundInput);
66
- this._form.removeEventListener('change', this._boundChange);
67
- this._form.removeEventListener('click', this._boundClick);
68
- this._form.removeEventListener('submit', this._boundSubmit);
69
- this._form = null;
70
- clearTimeout(this._timer);
71
- this._timer = null;
72
- this._controls = [];
73
- }
74
-
75
- getState() {
76
- return this._collectState();
77
- }
78
-
79
- getValues() {
80
- return this._collectState().params;
81
- }
82
-
83
- getFields() {
84
- const unique = new Set();
85
- this._getControls().forEach((control) => {
86
- const field = this._getField(control);
87
- if (field) {
88
- unique.add(field);
89
- }
90
- });
91
- return Array.from(unique);
92
- }
93
-
94
- setValues(nextValues = {}, options = {}) {
95
- if (!this._form) {
96
- return;
97
- }
98
- this._getControls().forEach((control) => {
99
- const field = this._getField(control);
100
- if (!field) {
101
- return;
102
- }
103
- const part = this._getPart(control);
104
- const key = part === 'operator' ? `${field}_op` : field;
105
- const hasOwn = Object.prototype.hasOwnProperty.call(nextValues, key);
106
- const nextValue = hasOwn ? nextValues[key] : '';
107
- this._setControlValue(control, nextValue);
108
- });
109
- if (options.emit) {
110
- this._emit();
111
- }
112
- }
113
-
114
- _resolveFormNode() {
115
- if (this._options.formNode && this._options.formNode.nodeType === 1) {
116
- return this._options.formNode;
117
- }
118
- const selector = String(this._options.formSelector || '').trim();
119
- if (!selector) {
120
- return null;
121
- }
122
- return safeQuerySelector(selector);
123
- }
124
-
125
- _handleInput(event) {
126
- if (!this._isFilterControl(event.target)) {
127
- return;
128
- }
129
- if (this._isManualMode()) {
130
- return;
131
- }
132
- const type = String(event.target.type || '').toLowerCase();
133
- if (type === 'checkbox' || type === 'radio' || event.target.tagName === 'SELECT') {
134
- this._emit();
135
- return;
136
- }
137
- clearTimeout(this._timer);
138
- this._timer = setTimeout(() => this._emit(), normalizeNonNegativeInt(this._options.debounceMs, 300));
139
- }
140
-
141
- _handleChange(event) {
142
- if (!this._isFilterControl(event.target)) {
143
- return;
144
- }
145
- if (this._isManualMode()) {
146
- return;
147
- }
148
- clearTimeout(this._timer);
149
- this._emit();
150
- }
151
-
152
- _handleClick(event) {
153
- if (!this._form) {
154
- return;
155
- }
156
- const button = this._options.button || {};
157
- const applySelector = String(button.apply || '[data-filter-apply]').trim();
158
- const resetSelector = String(button.reset || '[data-filter-reset]').trim();
159
-
160
- const applyButton = applySelector ? event.target.closest(applySelector) : null;
161
- if (applyButton) {
162
- event.preventDefault();
163
- clearTimeout(this._timer);
164
- this._emit();
165
- return;
166
- }
167
-
168
- const resetButton = resetSelector ? event.target.closest(resetSelector) : null;
169
- if (!resetButton) {
170
- return;
171
- }
172
- event.preventDefault();
173
- this._reset();
174
- if (typeof this._options.onReset === 'function') {
175
- this._options.onReset();
176
- }
177
- clearTimeout(this._timer);
178
- this._emit();
179
- }
180
-
181
- _handleSubmit(event) {
182
- if (!this._isManualMode()) {
183
- return;
184
- }
185
- event.preventDefault();
186
- clearTimeout(this._timer);
187
- this._emit();
188
- }
189
-
190
- _emit() {
191
- if (!this._form || typeof this._options.onChange !== 'function') {
192
- return;
193
- }
194
- this._options.onChange(this._collectState());
195
- }
196
-
197
- _collectState() {
198
- const groups = new Map();
199
- this._getControls().forEach((control) => {
200
- const field = this._getField(control);
201
- if (!field) {
202
- return;
203
- }
204
- if (!groups.has(field)) {
205
- groups.set(field, {
206
- field,
207
- type: this._getType(control),
208
- operator: this._getStaticOperator(control),
209
- value: '',
210
- values: [],
211
- });
212
- }
213
- const item = groups.get(field);
214
- const part = this._getPart(control);
215
- const value = this._readControlValue(control);
216
- const controlType = String(control.type || '').toLowerCase();
217
- if (part === 'operator') {
218
- item.operator = String(value || '').trim() || item.operator || this._getDefaultOperator();
219
- return;
220
- }
221
- if (part === 'type') {
222
- item.type = String(value || '').trim() || item.type || 'text';
223
- return;
224
- }
225
- // Ignore unchecked radio/checkbox values so they do not wipe selected values in a group.
226
- if ((controlType === 'checkbox' || controlType === 'radio') && value === '') {
227
- return;
228
- }
229
- if (Array.isArray(value)) {
230
- item.values = value.slice();
231
- item.value = item.values.join(',');
232
- return;
233
- }
234
- item.value = value;
235
- });
236
-
237
- const filters = {};
238
- const params = {};
239
- groups.forEach((item, field) => {
240
- const normalized = this._normalizeFilterItem(item);
241
- if (!normalized) {
242
- return;
243
- }
244
- filters[field] = normalized;
245
-
246
- if (normalized.values.length > 0) {
247
- params[field] = normalized.values.slice();
248
- } else {
249
- params[field] = normalized.value;
250
- }
251
- if (normalized.operator) {
252
- params[`${field}_op`] = normalized.operator;
253
- }
254
- });
255
-
256
- return {
257
- filters,
258
- params,
259
- fields: Object.keys(filters),
260
- meta: {
261
- count: Object.keys(filters).length,
262
- },
263
- };
264
- }
265
-
266
- _normalizeFilterItem(item) {
267
- const type = String(item.type || 'text').trim() || 'text';
268
- const operator = String(item.operator || this._getDefaultOperator()).trim();
269
- let value = item.value;
270
- let values = Array.isArray(item.values) ? item.values.slice() : [];
271
-
272
- if (this._options.trimValues) {
273
- if (typeof value === 'string') {
274
- value = value.trim();
275
- }
276
- values = values.map((entry) => String(entry || '').trim()).filter((entry) => entry !== '');
277
- }
278
-
279
- if (this._options.skipEmpty) {
280
- const isEmptyArray = values.length === 0;
281
- const isEmptyValue = value === undefined || value === null || String(value) === '';
282
- if (isEmptyArray && isEmptyValue) {
283
- return null;
284
- }
285
- }
286
-
287
- return {
288
- field: String(item.field || '').trim(),
289
- type,
290
- operator,
291
- value: value === undefined || value === null ? '' : value,
292
- values,
293
- };
294
- }
295
-
296
- _setControlValue(control, nextValue) {
297
- const type = String(control.type || '').toLowerCase();
298
- if (type === 'checkbox') {
299
- const normalized = String(nextValue || '').toLowerCase();
300
- control.checked = normalized === String(control.value || '').toLowerCase()
301
- || normalized === '1'
302
- || normalized === 'true'
303
- || normalized === 'on';
304
- return;
305
- }
306
- if (type === 'radio') {
307
- control.checked = String(control.value || '') === String(nextValue || '');
308
- return;
309
- }
310
- if (control.tagName === 'SELECT' && control.multiple) {
311
- const rawValues = Array.isArray(nextValue)
312
- ? nextValue
313
- : String(nextValue || '').split(',');
314
- const selected = new Set(rawValues
315
- .map((value) => String(value || '').trim())
316
- .filter((value) => value !== ''));
317
- Array.from(control.options || []).forEach((option) => {
318
- option.selected = selected.has(String(option.value || '').trim());
319
- });
320
- return;
321
- }
322
- control.value = String(nextValue || '');
323
- }
324
-
325
- _readControlValue(control) {
326
- if (control.tagName === 'SELECT' && control.multiple) {
327
- return Array.from(control.selectedOptions || [])
328
- .map((option) => String(option.value || '').trim())
329
- .filter((value) => value !== '');
330
- }
331
- const type = String(control.type || '').toLowerCase();
332
- if (type === 'checkbox') {
333
- return control.checked ? (control.value || '1') : '';
334
- }
335
- if (type === 'radio') {
336
- return control.checked ? (control.value || '') : '';
337
- }
338
- return String(control.value || '');
339
- }
340
-
341
- _syncCachedNodes() {
342
- if (!this._form) {
343
- this._controls = [];
344
- return;
345
- }
346
- const attr = this._getFieldAttr();
347
- this._controls = Array.from(this._form.querySelectorAll(`[${attr}]`))
348
- .filter((control) => this._isSupportedControl(control));
349
- }
350
-
351
- _getControls() {
352
- if (!this._form) {
353
- return [];
354
- }
355
- if (!Array.isArray(this._controls) || this._controls.length === 0) {
356
- this._syncCachedNodes();
357
- }
358
- return this._controls;
359
- }
360
-
361
- _reset() {
362
- this._getControls().forEach((control) => {
363
- const type = String(control.type || '').toLowerCase();
364
- if (type === 'checkbox' || type === 'radio') {
365
- control.checked = false;
366
- return;
367
- }
368
- if (control.tagName === 'SELECT') {
369
- if (control.multiple) {
370
- Array.from(control.options || []).forEach((option) => {
371
- option.selected = false;
372
- });
373
- return;
374
- }
375
- control.selectedIndex = 0;
376
- return;
377
- }
378
- control.value = '';
379
- });
380
- }
381
-
382
- _getFieldAttr() {
383
- return String(this._options.fieldAttr || 'data-filter-field').trim() || 'data-filter-field';
384
- }
385
-
386
- _getPartAttr() {
387
- return String(this._options.partAttr || 'data-filter-part').trim() || 'data-filter-part';
388
- }
389
-
390
- _getTypeAttr() {
391
- return String(this._options.typeAttr || 'data-filter-type').trim() || 'data-filter-type';
392
- }
393
-
394
- _getValueAttr() {
395
- return String(this._options.valueAttr || 'data-filter-value').trim() || 'data-filter-value';
396
- }
397
-
398
- _getOperatorAttr() {
399
- return String(this._options.operatorAttr || 'data-filter-operator').trim() || 'data-filter-operator';
400
- }
401
-
402
- _getDefaultOperator() {
403
- return String(this._options.defaultOperator || 'eq').trim() || 'eq';
404
- }
405
-
406
- _getField(control) {
407
- return String(control.getAttribute(this._getFieldAttr()) || '').trim();
408
- }
409
-
410
- _getPart(control) {
411
- const part = String(control.getAttribute(this._getPartAttr()) || 'value').toLowerCase().trim();
412
- if (part === 'operator' || part === 'type') {
413
- return part;
414
- }
415
- return 'value';
416
- }
417
-
418
- _getType(control) {
419
- const type = String(control.getAttribute(this._getTypeAttr()) || '').toLowerCase().trim();
420
- return type || 'text';
421
- }
422
-
423
- _getStaticOperator(control) {
424
- const operator = String(control.getAttribute(this._getOperatorAttr()) || '').trim();
425
- return operator || '';
426
- }
427
-
428
- _isFilterControl(node) {
429
- return Boolean(
430
- node
431
- && this._isSupportedControl(node)
432
- && typeof node.getAttribute === 'function'
433
- && String(node.getAttribute(this._getFieldAttr()) || '').trim() !== ''
434
- );
435
- }
436
-
437
- _isSupportedControl(node) {
438
- if (!node || typeof node.tagName !== 'string') {
439
- return false;
440
- }
441
- const tag = String(node.tagName || '').toUpperCase();
442
- return tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA';
443
- }
444
- _isManualMode() {
445
- const mode = String(this._options.applyMode || 'auto').toLowerCase().trim();
446
- return mode === 'manual';
447
- }
448
- }
449
-
450
- export default Filters;