@liedekef/ftable 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +5 -0
- package/ftable.esm.js +136 -100
- package/ftable.js +136 -100
- package/ftable.min.js +3 -3
- package/ftable.umd.js +136 -100
- package/package.json +1 -1
package/CHANGES.md
ADDED
package/ftable.esm.js
CHANGED
|
@@ -653,10 +653,6 @@ class FTableFormBuilder {
|
|
|
653
653
|
}
|
|
654
654
|
});
|
|
655
655
|
|
|
656
|
-
/*if (this.options.formCreated) {
|
|
657
|
-
this.options.formCreated(form, formType, record);
|
|
658
|
-
}*/
|
|
659
|
-
|
|
660
656
|
// Set up dependency listeners after all fields are created
|
|
661
657
|
this.setupDependencyListeners(form);
|
|
662
658
|
|
|
@@ -1335,7 +1331,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1335
1331
|
|
|
1336
1332
|
this.options = this.mergeOptions(options);
|
|
1337
1333
|
this.logger = new FTableLogger(this.options.logLevel);
|
|
1338
|
-
this.userPrefs = new FTableUserPreferences('', this.options.
|
|
1334
|
+
this.userPrefs = new FTableUserPreferences('', this.options.saveUserPreferencesMethod);
|
|
1339
1335
|
this.formBuilder = new FTableFormBuilder(this.options, this);
|
|
1340
1336
|
|
|
1341
1337
|
this.state = {
|
|
@@ -1351,6 +1347,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1351
1347
|
this.elements = {};
|
|
1352
1348
|
this.modals = {};
|
|
1353
1349
|
this.searchTimeout = null; // For debouncing
|
|
1350
|
+
this.lastSortEvent = null;
|
|
1354
1351
|
this._recalculatedOnce = false;
|
|
1355
1352
|
|
|
1356
1353
|
// store it on the DOM too, so people can access it
|
|
@@ -1368,23 +1365,28 @@ class FTable extends FTableEventEmitter {
|
|
|
1368
1365
|
animationsEnabled: true,
|
|
1369
1366
|
loadingAnimationDelay: 1000,
|
|
1370
1367
|
defaultDateFormat: 'yyyy-mm-dd',
|
|
1371
|
-
|
|
1372
|
-
|
|
1368
|
+
saveUserPreferences: true,
|
|
1369
|
+
saveUserPreferencesMethod: 'localStorage',
|
|
1373
1370
|
defaultSorting: '',
|
|
1374
1371
|
|
|
1375
1372
|
// Paging
|
|
1376
1373
|
paging: false,
|
|
1374
|
+
pageList: 'normal',
|
|
1377
1375
|
pageSize: 10,
|
|
1378
1376
|
gotoPageArea: 'combobox',
|
|
1379
1377
|
|
|
1380
1378
|
// Sorting
|
|
1381
1379
|
sorting: false,
|
|
1382
1380
|
multiSorting: false,
|
|
1381
|
+
multiSortingCtrlKey: true,
|
|
1383
1382
|
|
|
1384
1383
|
// Selection
|
|
1385
1384
|
selecting: false,
|
|
1386
1385
|
multiselect: false,
|
|
1387
1386
|
|
|
1387
|
+
// child tables
|
|
1388
|
+
openChildAsAccordion: false,
|
|
1389
|
+
|
|
1388
1390
|
// Toolbar search
|
|
1389
1391
|
toolbarsearch: false, // Enable/disable toolbar search row
|
|
1390
1392
|
toolbarreset: true, // Show reset button
|
|
@@ -1621,6 +1623,9 @@ class FTable extends FTableEventEmitter {
|
|
|
1621
1623
|
if (field.list === undefined) {
|
|
1622
1624
|
field.list = true;
|
|
1623
1625
|
}
|
|
1626
|
+
if (field.sorting === undefined) {
|
|
1627
|
+
field.sorting = true;
|
|
1628
|
+
}
|
|
1624
1629
|
if (!field.hasOwnProperty('visibility')) {
|
|
1625
1630
|
field.visibility = 'visible';
|
|
1626
1631
|
}
|
|
@@ -1748,9 +1753,9 @@ class FTable extends FTableEventEmitter {
|
|
|
1748
1753
|
});
|
|
1749
1754
|
|
|
1750
1755
|
// Add selecting column if enabled
|
|
1751
|
-
if (this.options.selecting) {
|
|
1756
|
+
if (this.options.selecting && this.options.selectingCheckboxes) {
|
|
1752
1757
|
const selectHeader = FTableDOMHelper.create('th', {
|
|
1753
|
-
className:
|
|
1758
|
+
className: `ftable-column-header ftable-column-header-select`,
|
|
1754
1759
|
parent: headerRow
|
|
1755
1760
|
});
|
|
1756
1761
|
|
|
@@ -1770,7 +1775,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1770
1775
|
this.columnList.forEach(fieldName => {
|
|
1771
1776
|
const field = this.options.fields[fieldName];
|
|
1772
1777
|
const th = FTableDOMHelper.create('th', {
|
|
1773
|
-
className:
|
|
1778
|
+
className: `ftable-column-header ${field.listClass || ''} ${field.listClassHeader || ''}`,
|
|
1774
1779
|
attributes: { 'data-field-name': fieldName },
|
|
1775
1780
|
parent: headerRow
|
|
1776
1781
|
});
|
|
@@ -1785,6 +1790,10 @@ class FTable extends FTableEventEmitter {
|
|
|
1785
1790
|
parent: th
|
|
1786
1791
|
});
|
|
1787
1792
|
|
|
1793
|
+
if (field.tooltip) {
|
|
1794
|
+
container.setAttribute('title', field.tooltip);
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1788
1797
|
FTableDOMHelper.create('span', {
|
|
1789
1798
|
className: 'ftable-column-header-text',
|
|
1790
1799
|
text: field.title || fieldName,
|
|
@@ -1794,7 +1803,12 @@ class FTable extends FTableEventEmitter {
|
|
|
1794
1803
|
// Make sortable if enabled
|
|
1795
1804
|
if (this.options.sorting && field.sorting !== false) {
|
|
1796
1805
|
FTableDOMHelper.addClass(th, 'ftable-column-header-sortable');
|
|
1797
|
-
th.addEventListener('click', () =>
|
|
1806
|
+
th.addEventListener('click', (e) => {
|
|
1807
|
+
e.preventDefault();
|
|
1808
|
+
// Store event for multiSortingCtrlKey logic
|
|
1809
|
+
this.lastSortEvent = e;
|
|
1810
|
+
this.sortByColumn(fieldName);
|
|
1811
|
+
});
|
|
1798
1812
|
}
|
|
1799
1813
|
|
|
1800
1814
|
// Add resize handler if column resizing is enabled
|
|
@@ -1845,7 +1859,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1845
1859
|
});
|
|
1846
1860
|
|
|
1847
1861
|
// Add empty cell for selecting column if enabled
|
|
1848
|
-
if (this.options.selecting) {
|
|
1862
|
+
if (this.options.selecting && this.options.selectingCheckboxes) {
|
|
1849
1863
|
FTableDOMHelper.create('th', { parent: searchRow });
|
|
1850
1864
|
}
|
|
1851
1865
|
|
|
@@ -2131,14 +2145,14 @@ class FTable extends FTableEventEmitter {
|
|
|
2131
2145
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
2132
2146
|
|
|
2133
2147
|
// Save column width preference if enabled
|
|
2134
|
-
if (this.options.
|
|
2148
|
+
if (this.options.saveUserPreferences) {
|
|
2135
2149
|
this.saveColumnSettings();
|
|
2136
2150
|
}
|
|
2137
2151
|
};
|
|
2138
2152
|
}
|
|
2139
2153
|
|
|
2140
2154
|
saveColumnSettings() {
|
|
2141
|
-
if (!this.options.
|
|
2155
|
+
if (!this.options.saveUserPreferences) return;
|
|
2142
2156
|
|
|
2143
2157
|
const settings = {};
|
|
2144
2158
|
this.columnList.forEach(fieldName => {
|
|
@@ -2156,7 +2170,7 @@ class FTable extends FTableEventEmitter {
|
|
|
2156
2170
|
}
|
|
2157
2171
|
|
|
2158
2172
|
saveState() {
|
|
2159
|
-
if (!this.options.
|
|
2173
|
+
if (!this.options.saveUserPreferences) return;
|
|
2160
2174
|
|
|
2161
2175
|
const state = {
|
|
2162
2176
|
sorting: this.state.sorting,
|
|
@@ -2167,7 +2181,7 @@ class FTable extends FTableEventEmitter {
|
|
|
2167
2181
|
}
|
|
2168
2182
|
|
|
2169
2183
|
loadColumnSettings() {
|
|
2170
|
-
if (!this.options.
|
|
2184
|
+
if (!this.options.saveUserPreferences) return;
|
|
2171
2185
|
|
|
2172
2186
|
const settingsJson = this.userPrefs.get('column-settings');
|
|
2173
2187
|
if (!settingsJson) return;
|
|
@@ -2187,7 +2201,7 @@ class FTable extends FTableEventEmitter {
|
|
|
2187
2201
|
}
|
|
2188
2202
|
|
|
2189
2203
|
loadState() {
|
|
2190
|
-
if (!this.options.
|
|
2204
|
+
if (!this.options.saveUserPreferences) return;
|
|
2191
2205
|
|
|
2192
2206
|
const stateJson = this.userPrefs.get('table-state');
|
|
2193
2207
|
if (!stateJson) return;
|
|
@@ -2266,9 +2280,6 @@ class FTable extends FTableEventEmitter {
|
|
|
2266
2280
|
onClick: () => {
|
|
2267
2281
|
this.modals.addRecord.close();
|
|
2268
2282
|
this.emit('formClosed', { form: this.currentForm, formType: 'create', record: null });
|
|
2269
|
-
/*if (this.options.formClosed) {
|
|
2270
|
-
this.options.formClosed(this.currentForm, 'create', null);
|
|
2271
|
-
}*/
|
|
2272
2283
|
}
|
|
2273
2284
|
},
|
|
2274
2285
|
{
|
|
@@ -2621,6 +2632,11 @@ class FTable extends FTableEventEmitter {
|
|
|
2621
2632
|
parent: this.elements.toolbarDiv
|
|
2622
2633
|
});
|
|
2623
2634
|
|
|
2635
|
+
// Add title/tooltip if provided
|
|
2636
|
+
if (item.tooltip) {
|
|
2637
|
+
button.setAttribute('title', item.tooltip);
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2624
2640
|
// Add icon if provided
|
|
2625
2641
|
if (item.icon) {
|
|
2626
2642
|
const img = FTableDOMHelper.create('img', {
|
|
@@ -2683,12 +2699,12 @@ class FTable extends FTableEventEmitter {
|
|
|
2683
2699
|
}
|
|
2684
2700
|
|
|
2685
2701
|
setupFTableUserPreferences() {
|
|
2686
|
-
if (this.options.
|
|
2702
|
+
if (this.options.saveUserPreferences) {
|
|
2687
2703
|
const prefix = this.userPrefs.generatePrefix(
|
|
2688
2704
|
this.options.tableId || '',
|
|
2689
2705
|
this.fieldList
|
|
2690
2706
|
);
|
|
2691
|
-
this.userPrefs = new FTableUserPreferences(prefix, this.options.
|
|
2707
|
+
this.userPrefs = new FTableUserPreferences(prefix, this.options.saveUserPreferencesMethod);
|
|
2692
2708
|
|
|
2693
2709
|
// Load saved column settings
|
|
2694
2710
|
this.loadState();
|
|
@@ -2860,7 +2876,7 @@ class FTable extends FTableEventEmitter {
|
|
|
2860
2876
|
row.recordData = record;
|
|
2861
2877
|
|
|
2862
2878
|
// Add selecting checkbox if enabled
|
|
2863
|
-
if (this.options.selecting) {
|
|
2879
|
+
if (this.options.selecting && this.options.selectingCheckboxes) {
|
|
2864
2880
|
this.addSelectingCell(row);
|
|
2865
2881
|
}
|
|
2866
2882
|
|
|
@@ -3085,10 +3101,7 @@ class FTable extends FTableEventEmitter {
|
|
|
3085
3101
|
this.modals.addRecord.close();
|
|
3086
3102
|
|
|
3087
3103
|
// Call formClosed
|
|
3088
|
-
|
|
3089
|
-
if (this.options.formClosed) {
|
|
3090
|
-
this.options.formClosed(this.currentForm, 'create', null);
|
|
3091
|
-
}
|
|
3104
|
+
this.emit('formClosed', { form: this.currentForm, formType: 'create', record: null });
|
|
3092
3105
|
|
|
3093
3106
|
if (result.Message) {
|
|
3094
3107
|
this.showInfo(result.Message);
|
|
@@ -3135,17 +3148,14 @@ class FTable extends FTableEventEmitter {
|
|
|
3135
3148
|
this.modals.editRecord.close();
|
|
3136
3149
|
|
|
3137
3150
|
// Call formClosed
|
|
3138
|
-
|
|
3139
|
-
if (this.options.formClosed) {
|
|
3140
|
-
this.options.formClosed(this.currentForm, 'edit', this.currentEditingRow.recordData);
|
|
3141
|
-
}
|
|
3151
|
+
this.emit('formClosed', { form: this.currentForm, formType: 'edit', record: this.currentEditingRow.recordData });
|
|
3142
3152
|
|
|
3143
3153
|
// Update the row with new data
|
|
3144
3154
|
this.updateRowData(this.currentEditingRow, result.Record || formData);
|
|
3145
3155
|
if (result.Message) {
|
|
3146
3156
|
this.showInfo(result.Message);
|
|
3147
3157
|
}
|
|
3148
|
-
this.emit('recordUpdated', { record: result.Record || formData });
|
|
3158
|
+
this.emit('recordUpdated', { record: result.Record || formData, row: this.currentEditingRow });
|
|
3149
3159
|
} else {
|
|
3150
3160
|
this.showError(result.Message || 'Update failed');
|
|
3151
3161
|
}
|
|
@@ -3451,25 +3461,42 @@ class FTable extends FTableEventEmitter {
|
|
|
3451
3461
|
|
|
3452
3462
|
// Sorting Methods
|
|
3453
3463
|
sortByColumn(fieldName) {
|
|
3464
|
+
const field = this.options.fields[fieldName];
|
|
3465
|
+
|
|
3466
|
+
if (!field || field.sorting === false) return;
|
|
3467
|
+
|
|
3454
3468
|
const existingSortIndex = this.state.sorting.findIndex(s => s.fieldName === fieldName);
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
this.state.sorting = [];
|
|
3458
|
-
}
|
|
3459
|
-
|
|
3469
|
+
let isSorted = true;
|
|
3470
|
+
let newDirection = 'ASC';
|
|
3460
3471
|
if (existingSortIndex >= 0) {
|
|
3461
|
-
const
|
|
3462
|
-
if (
|
|
3463
|
-
|
|
3472
|
+
const wasAsc = this.state.sorting[existingSortIndex].direction === 'ASC';
|
|
3473
|
+
if (wasAsc) {
|
|
3474
|
+
newDirection = 'DESC';
|
|
3475
|
+
this.state.sorting[existingSortIndex].direction = newDirection;
|
|
3464
3476
|
} else {
|
|
3465
|
-
this.state.sorting.splice(existingSortIndex,
|
|
3477
|
+
this.state.sorting.splice(existingSortIndex,1);
|
|
3478
|
+
isSorted = false;
|
|
3466
3479
|
}
|
|
3467
3480
|
} else {
|
|
3468
|
-
this.state.sorting.push({ fieldName, direction:
|
|
3481
|
+
this.state.sorting.push({ fieldName, direction: newDirection });
|
|
3469
3482
|
}
|
|
3470
|
-
|
|
3483
|
+
|
|
3484
|
+
// Handle multiSortingCtrlKey: did user press Ctrl/Cmd?
|
|
3485
|
+
const isCtrlPressed = this.lastSortEvent?.ctrlKey || this.lastSortEvent?.metaKey; // metaKey for Mac
|
|
3486
|
+
|
|
3487
|
+
if (this.options.multiSorting) {
|
|
3488
|
+
// If multiSorting is enabled, respect multiSortingCtrlKey
|
|
3489
|
+
if (this.options.multiSortingCtrlKey && !isCtrlPressed) {
|
|
3490
|
+
// Not using Ctrl → treat as single sort (clear others)
|
|
3491
|
+
this.state.sorting = isSorted ? [{ fieldName, direction: newDirection }] : [];
|
|
3492
|
+
}
|
|
3493
|
+
} else {
|
|
3494
|
+
// If multiSorting is disabled, always clear other sorts
|
|
3495
|
+
this.state.sorting = isSorted ? [{ fieldName, direction: newDirection }] : [];
|
|
3496
|
+
}
|
|
3497
|
+
|
|
3471
3498
|
this.updateSortingHeaders();
|
|
3472
|
-
this.load();
|
|
3499
|
+
this.load();
|
|
3473
3500
|
this.saveState();
|
|
3474
3501
|
}
|
|
3475
3502
|
|
|
@@ -3528,27 +3555,29 @@ class FTable extends FTableEventEmitter {
|
|
|
3528
3555
|
this.createPageButton('‹', this.state.currentPage - 1, this.state.currentPage === 1, 'ftable-page-number-previous');
|
|
3529
3556
|
|
|
3530
3557
|
// Page numbers
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3558
|
+
if (this.options.pageList == 'normal') {
|
|
3559
|
+
const pageNumbers = this.calculatePageNumbers(totalPages);
|
|
3560
|
+
let lastNumber = 0;
|
|
3561
|
+
|
|
3562
|
+
pageNumbers.forEach(pageNum => {
|
|
3563
|
+
if (pageNum - lastNumber > 1) {
|
|
3564
|
+
FTableDOMHelper.create('span', {
|
|
3565
|
+
className: 'ftable-page-number-space',
|
|
3566
|
+
text: '...',
|
|
3567
|
+
parent: this.elements.pagingListArea
|
|
3568
|
+
});
|
|
3569
|
+
}
|
|
3570
|
+
|
|
3571
|
+
this.createPageButton(
|
|
3572
|
+
pageNum.toString(),
|
|
3573
|
+
pageNum,
|
|
3574
|
+
false,
|
|
3575
|
+
pageNum === this.state.currentPage ? 'ftable-page-number ftable-page-number-active' : 'ftable-page-number'
|
|
3576
|
+
);
|
|
3577
|
+
|
|
3578
|
+
lastNumber = pageNum;
|
|
3579
|
+
});
|
|
3580
|
+
}
|
|
3552
3581
|
|
|
3553
3582
|
// Next and Last buttons
|
|
3554
3583
|
this.createPageButton('›', this.state.currentPage + 1, this.state.currentPage >= totalPages, 'ftable-page-number-next');
|
|
@@ -3956,7 +3985,7 @@ class FTable extends FTableEventEmitter {
|
|
|
3956
3985
|
if (columnIndex >= 0) {
|
|
3957
3986
|
// Calculate actual column index (accounting for selecting column)
|
|
3958
3987
|
let actualIndex = columnIndex + 1; // CSS nth-child is 1-based
|
|
3959
|
-
if (this.options.selecting) {
|
|
3988
|
+
if (this.options.selecting && this.options.selectingCheckboxes) {
|
|
3960
3989
|
actualIndex += 1; // Account for selecting column
|
|
3961
3990
|
}
|
|
3962
3991
|
|
|
@@ -3973,7 +4002,7 @@ class FTable extends FTableEventEmitter {
|
|
|
3973
4002
|
}
|
|
3974
4003
|
|
|
3975
4004
|
// Save column settings
|
|
3976
|
-
if (this.options.
|
|
4005
|
+
if (this.options.saveUserPreferences) {
|
|
3977
4006
|
this.saveColumnSettings();
|
|
3978
4007
|
this.saveState(); // sorting might affect state
|
|
3979
4008
|
}
|
|
@@ -4171,27 +4200,6 @@ class FTable extends FTableEventEmitter {
|
|
|
4171
4200
|
});
|
|
4172
4201
|
}
|
|
4173
4202
|
|
|
4174
|
-
// Performance optimization for large datasets
|
|
4175
|
-
enableVirtualScrolling(options = {}) {
|
|
4176
|
-
const virtualOptions = {
|
|
4177
|
-
rowHeight: 40,
|
|
4178
|
-
overscan: 5,
|
|
4179
|
-
...options
|
|
4180
|
-
};
|
|
4181
|
-
|
|
4182
|
-
// This would implement virtual scrolling for performance with large datasets
|
|
4183
|
-
// Simplified version - full implementation would be more complex
|
|
4184
|
-
this.virtualScrolling = {
|
|
4185
|
-
enabled: true,
|
|
4186
|
-
...virtualOptions,
|
|
4187
|
-
visibleRange: { start: 0, end: 0 },
|
|
4188
|
-
scrollContainer: null
|
|
4189
|
-
};
|
|
4190
|
-
|
|
4191
|
-
// Replace table body with virtual scroll container
|
|
4192
|
-
// Implementation would calculate visible rows and only render those
|
|
4193
|
-
}
|
|
4194
|
-
|
|
4195
4203
|
// Real-time updates via WebSocket
|
|
4196
4204
|
enableRealTimeUpdates(websocketUrl) {
|
|
4197
4205
|
if (!websocketUrl) return;
|
|
@@ -4315,6 +4323,15 @@ class FTable extends FTableEventEmitter {
|
|
|
4315
4323
|
return this;
|
|
4316
4324
|
}
|
|
4317
4325
|
|
|
4326
|
+
editRecordByKey(keyValue) {
|
|
4327
|
+
const row = this.getRowByKey(keyValue);
|
|
4328
|
+
if (row) {
|
|
4329
|
+
this.editRecord(row);
|
|
4330
|
+
} else {
|
|
4331
|
+
this.showError(`Record with key '${keyValue}' not found`);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4318
4335
|
async editRecordViaAjax(recordId, url, params = {}) {
|
|
4319
4336
|
try {
|
|
4320
4337
|
// Get the actual key field name (e.g., 'asset_id', 'user_id', etc.)
|
|
@@ -4354,6 +4371,10 @@ class FTable extends FTableEventEmitter {
|
|
|
4354
4371
|
}
|
|
4355
4372
|
|
|
4356
4373
|
openChildTable(parentRow, childOptions, onInit) {
|
|
4374
|
+
// Close any open child tables if accordion mode
|
|
4375
|
+
if (this.options.openChildAsAccordion) {
|
|
4376
|
+
this.closeAllChildTables();
|
|
4377
|
+
}
|
|
4357
4378
|
// Prevent multiple child tables
|
|
4358
4379
|
this.closeChildTable(parentRow);
|
|
4359
4380
|
|
|
@@ -4422,6 +4443,31 @@ class FTable extends FTableEventEmitter {
|
|
|
4422
4443
|
}
|
|
4423
4444
|
}
|
|
4424
4445
|
|
|
4446
|
+
closeAllChildTables() {
|
|
4447
|
+
Object.values(this.elements.tableRows).forEach(row => {
|
|
4448
|
+
if (row.childTable) {
|
|
4449
|
+
this.closeChildTable(row);
|
|
4450
|
+
}
|
|
4451
|
+
});
|
|
4452
|
+
}
|
|
4453
|
+
|
|
4454
|
+
getSortingInfo() {
|
|
4455
|
+
// Build sorted fields list with translated directions
|
|
4456
|
+
const messages = this.options.messages || {};
|
|
4457
|
+
const sortingInfo = this.state.sorting.map(s => {
|
|
4458
|
+
const field = this.options.fields[s.fieldName];
|
|
4459
|
+
const title = field?.title || s.fieldName;
|
|
4460
|
+
|
|
4461
|
+
// Translate direction
|
|
4462
|
+
const directionText = s.direction === 'ASC'
|
|
4463
|
+
? (messages.ascending || 'ascending')
|
|
4464
|
+
: (messages.descending || 'descending');
|
|
4465
|
+
|
|
4466
|
+
return `${title} (${directionText})`;
|
|
4467
|
+
}).join(', ');
|
|
4468
|
+
return sortingInfo;
|
|
4469
|
+
}
|
|
4470
|
+
|
|
4425
4471
|
renderSortingInfo() {
|
|
4426
4472
|
if (!this.options.sortingInfoSelector || !this.options.sorting) return;
|
|
4427
4473
|
|
|
@@ -4443,20 +4489,10 @@ class FTable extends FTableEventEmitter {
|
|
|
4443
4489
|
}
|
|
4444
4490
|
|
|
4445
4491
|
// Build sorted fields list with translated directions
|
|
4446
|
-
const
|
|
4447
|
-
const field = this.options.fields[s.fieldName];
|
|
4448
|
-
const title = field?.title || s.fieldName;
|
|
4449
|
-
|
|
4450
|
-
// Translate direction
|
|
4451
|
-
const directionText = s.direction === 'ASC'
|
|
4452
|
-
? (messages.ascending || 'ascending')
|
|
4453
|
-
: (messages.descending || 'descending');
|
|
4454
|
-
|
|
4455
|
-
return `${title} (${directionText})`;
|
|
4456
|
-
}).join(', ');
|
|
4492
|
+
const sortingInfo = this.getSortingInfo();
|
|
4457
4493
|
|
|
4458
4494
|
// Combine with prefix and suffix
|
|
4459
|
-
container.innerHTML = `${prefix}${
|
|
4495
|
+
container.innerHTML = `${prefix}${sortingInfo}${suffix}`;
|
|
4460
4496
|
|
|
4461
4497
|
// Add reset sorting button
|
|
4462
4498
|
if (this.state.sorting.length > 0) {
|