@vii7/div-table-widget 1.1.1 → 1.2.1
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/README.md +186 -13
- package/dist/divtable-theme-dark.min.css +1 -0
- package/dist/divtable-theme-dark.min.js +1 -0
- package/dist/divtable.min.css +1 -1
- package/dist/divtable.min.js +1 -1
- package/package.json +4 -2
- package/src/div-table-theme-dark.css +104 -0
- package/src/div-table.css +14 -0
- package/src/div-table.js +116 -248
package/src/div-table.js
CHANGED
|
@@ -113,6 +113,20 @@ class DivTable {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Strip HTML tags from a string for use in tooltips
|
|
118
|
+
* @param {string} html - String potentially containing HTML
|
|
119
|
+
* @returns {string} Plain text without HTML tags
|
|
120
|
+
*/
|
|
121
|
+
stripHtmlTags(html) {
|
|
122
|
+
if (!html) return '';
|
|
123
|
+
// Replace <br> and <br/> with space, then strip all other HTML tags
|
|
124
|
+
return String(html)
|
|
125
|
+
.replace(/<br\s*\/?>/gi, ' ')
|
|
126
|
+
.replace(/<[^>]*>/g, '')
|
|
127
|
+
.trim();
|
|
128
|
+
}
|
|
129
|
+
|
|
116
130
|
init() {
|
|
117
131
|
const container = this.options.tableWidgetElement;
|
|
118
132
|
if (!container) {
|
|
@@ -1712,12 +1726,21 @@ class DivTable {
|
|
|
1712
1726
|
fixedRow.style.height = '';
|
|
1713
1727
|
scrollRow.style.height = '';
|
|
1714
1728
|
|
|
1715
|
-
// Get natural heights
|
|
1716
|
-
const fixedHeight = fixedRow.offsetHeight;
|
|
1717
|
-
const scrollHeight = scrollRow.offsetHeight;
|
|
1729
|
+
// Get natural heights including any cell content overflow
|
|
1730
|
+
const fixedHeight = Math.max(fixedRow.offsetHeight, fixedRow.scrollHeight);
|
|
1731
|
+
const scrollHeight = Math.max(scrollRow.offsetHeight, scrollRow.scrollHeight);
|
|
1732
|
+
|
|
1733
|
+
// Also check individual cell heights
|
|
1734
|
+
let maxCellHeight = 0;
|
|
1735
|
+
fixedRow.querySelectorAll('.div-table-cell').forEach(cell => {
|
|
1736
|
+
maxCellHeight = Math.max(maxCellHeight, cell.offsetHeight, cell.scrollHeight);
|
|
1737
|
+
});
|
|
1738
|
+
scrollRow.querySelectorAll('.div-table-cell').forEach(cell => {
|
|
1739
|
+
maxCellHeight = Math.max(maxCellHeight, cell.offsetHeight, cell.scrollHeight);
|
|
1740
|
+
});
|
|
1718
1741
|
|
|
1719
1742
|
// Set both to the maximum height
|
|
1720
|
-
const maxHeight = Math.max(fixedHeight, scrollHeight);
|
|
1743
|
+
const maxHeight = Math.max(fixedHeight, scrollHeight, maxCellHeight);
|
|
1721
1744
|
if (maxHeight > 0) {
|
|
1722
1745
|
fixedRow.style.height = `${maxHeight}px`;
|
|
1723
1746
|
scrollRow.style.height = `${maxHeight}px`;
|
|
@@ -1892,8 +1915,8 @@ class DivTable {
|
|
|
1892
1915
|
const mainLabel = document.createElement('span');
|
|
1893
1916
|
mainLabel.className = 'composite-main-header';
|
|
1894
1917
|
mainLabel.innerHTML = col.label || col.field;
|
|
1918
|
+
mainLabel.title = this.stripHtmlTags(col.label || col.field);
|
|
1895
1919
|
mainLabel.style.fontWeight = '600';
|
|
1896
|
-
mainLabel.style.color = '#374151';
|
|
1897
1920
|
mainLabel.style.textAlign = 'left';
|
|
1898
1921
|
mainLabel.style.flex = '1';
|
|
1899
1922
|
mainLabelContainer.appendChild(mainLabel);
|
|
@@ -1916,7 +1939,7 @@ class DivTable {
|
|
|
1916
1939
|
groupIndicator.textContent = this.groupByField === col.field ? '☴' : '☷';
|
|
1917
1940
|
groupIndicator.style.cursor = 'pointer';
|
|
1918
1941
|
groupIndicator.style.fontSize = '1em';
|
|
1919
|
-
const columnTitle = col.label || col.field;
|
|
1942
|
+
const columnTitle = this.stripHtmlTags(col.label || col.field);
|
|
1920
1943
|
groupIndicator.title = this.groupByField === col.field ? `Grouped by ${columnTitle} (click to ungroup)` : `Click to group by ${columnTitle}`;
|
|
1921
1944
|
|
|
1922
1945
|
// Add click handler for grouping
|
|
@@ -1960,7 +1983,7 @@ class DivTable {
|
|
|
1960
1983
|
|
|
1961
1984
|
const subLabel = document.createElement('span');
|
|
1962
1985
|
subLabel.innerHTML = col.subLabel;
|
|
1963
|
-
subLabel.
|
|
1986
|
+
subLabel.title = this.stripHtmlTags(col.subLabel);
|
|
1964
1987
|
subLabel.style.textAlign = 'left';
|
|
1965
1988
|
subLabel.style.flex = '1';
|
|
1966
1989
|
subLabelContainer.appendChild(subLabel);
|
|
@@ -1980,9 +2003,9 @@ class DivTable {
|
|
|
1980
2003
|
|
|
1981
2004
|
subLabelContainer.appendChild(subSortIndicator);
|
|
1982
2005
|
|
|
1983
|
-
// Add hover effect
|
|
2006
|
+
// Add hover effect - use CSS variable for theming support
|
|
1984
2007
|
subLabelContainer.addEventListener('mouseenter', () => {
|
|
1985
|
-
subLabelContainer.style.backgroundColor = '
|
|
2008
|
+
subLabelContainer.style.backgroundColor = 'var(--dt-bg-disabled)';
|
|
1986
2009
|
});
|
|
1987
2010
|
subLabelContainer.addEventListener('mouseleave', () => {
|
|
1988
2011
|
subLabelContainer.style.backgroundColor = 'transparent';
|
|
@@ -2053,6 +2076,7 @@ class DivTable {
|
|
|
2053
2076
|
// Column label
|
|
2054
2077
|
const labelSpan = document.createElement('span');
|
|
2055
2078
|
labelSpan.innerHTML = columnLabel;
|
|
2079
|
+
labelSpan.title = this.stripHtmlTags(columnLabel);
|
|
2056
2080
|
//labelSpan.style.fontWeight = 'bold';
|
|
2057
2081
|
leftContent.appendChild(labelSpan);
|
|
2058
2082
|
|
|
@@ -2063,12 +2087,13 @@ class DivTable {
|
|
|
2063
2087
|
countSpan.style.opacity = '0.8';
|
|
2064
2088
|
countSpan.style.fontSize = '0.9em';
|
|
2065
2089
|
countSpan.style.fontWeight = 'normal';
|
|
2066
|
-
countSpan.title = `${groupCount} distinct value${groupCount === 1 ? '' : 's'} in ${columnLabel}`;
|
|
2090
|
+
countSpan.title = `${groupCount} distinct value${groupCount === 1 ? '' : 's'} in ${this.stripHtmlTags(columnLabel)}`;
|
|
2067
2091
|
leftContent.appendChild(countSpan);
|
|
2068
2092
|
} else {
|
|
2069
2093
|
// Regular column label
|
|
2070
2094
|
const labelSpan = document.createElement('span');
|
|
2071
2095
|
labelSpan.innerHTML = col.label || col.field;
|
|
2096
|
+
labelSpan.title = this.stripHtmlTags(col.label || col.field);
|
|
2072
2097
|
//labelSpan.style.fontWeight = 'bold';
|
|
2073
2098
|
leftContent.appendChild(labelSpan);
|
|
2074
2099
|
}
|
|
@@ -2089,7 +2114,7 @@ class DivTable {
|
|
|
2089
2114
|
groupIndicator.textContent = this.groupByField === col.field ? '☴' : '☷';
|
|
2090
2115
|
groupIndicator.style.cursor = 'pointer';
|
|
2091
2116
|
groupIndicator.style.fontSize = '1em';
|
|
2092
|
-
const columnTitle = col.label || col.field;
|
|
2117
|
+
const columnTitle = this.stripHtmlTags(col.label || col.field);
|
|
2093
2118
|
groupIndicator.title = this.groupByField === col.field ? `Grouped by ${columnTitle} (click to ungroup)` : `Click to group by ${columnTitle}`;
|
|
2094
2119
|
|
|
2095
2120
|
// Add click handler for grouping
|
|
@@ -2215,6 +2240,7 @@ class DivTable {
|
|
|
2215
2240
|
// Column label
|
|
2216
2241
|
const labelSpan = document.createElement('span');
|
|
2217
2242
|
labelSpan.innerHTML = columnLabel;
|
|
2243
|
+
labelSpan.title = this.stripHtmlTags(columnLabel);
|
|
2218
2244
|
leftContent.appendChild(labelSpan);
|
|
2219
2245
|
|
|
2220
2246
|
// Group count
|
|
@@ -2224,12 +2250,13 @@ class DivTable {
|
|
|
2224
2250
|
groupCountSpan.style.opacity = '0.8';
|
|
2225
2251
|
groupCountSpan.style.fontSize = '0.9em';
|
|
2226
2252
|
groupCountSpan.style.fontWeight = 'normal';
|
|
2227
|
-
groupCountSpan.title = `${groupCount} distinct value${groupCount === 1 ? '' : 's'} in ${columnLabel}`;
|
|
2253
|
+
groupCountSpan.title = `${groupCount} distinct value${groupCount === 1 ? '' : 's'} in ${this.stripHtmlTags(columnLabel)}`;
|
|
2228
2254
|
leftContent.appendChild(groupCountSpan);
|
|
2229
2255
|
} else {
|
|
2230
2256
|
// Regular label (not grouped)
|
|
2231
2257
|
const labelSpan = document.createElement('span');
|
|
2232
2258
|
labelSpan.innerHTML = col.label || col.field;
|
|
2259
|
+
labelSpan.title = this.stripHtmlTags(col.label || col.field);
|
|
2233
2260
|
leftContent.appendChild(labelSpan);
|
|
2234
2261
|
}
|
|
2235
2262
|
|
|
@@ -2251,7 +2278,7 @@ class DivTable {
|
|
|
2251
2278
|
groupIndicator.textContent = this.groupByField === col.field ? '☴' : '☷';
|
|
2252
2279
|
groupIndicator.style.cursor = 'pointer';
|
|
2253
2280
|
groupIndicator.style.fontSize = '1em';
|
|
2254
|
-
const columnTitle = col.label || col.field;
|
|
2281
|
+
const columnTitle = this.stripHtmlTags(col.label || col.field);
|
|
2255
2282
|
groupIndicator.title = this.groupByField === col.field ? `Grouped by ${columnTitle} (click to ungroup)` : `Click to group by ${columnTitle}`;
|
|
2256
2283
|
|
|
2257
2284
|
groupIndicator.addEventListener('click', (e) => {
|
|
@@ -2758,120 +2785,15 @@ class DivTable {
|
|
|
2758
2785
|
row.appendChild(checkboxCell);
|
|
2759
2786
|
}
|
|
2760
2787
|
|
|
2761
|
-
// Data columns - render using composite structure
|
|
2788
|
+
// Data columns - render using composite structure with proper alignment
|
|
2762
2789
|
compositeColumns.forEach(composite => {
|
|
2763
|
-
const cell =
|
|
2764
|
-
cell.className = 'div-table-cell';
|
|
2765
|
-
|
|
2766
|
-
if (composite.compositeName) {
|
|
2767
|
-
cell.classList.add('composite-cell');
|
|
2768
|
-
cell.style.display = 'flex';
|
|
2769
|
-
cell.style.flexDirection = 'column';
|
|
2770
|
-
cell.style.gap = '4px';
|
|
2771
|
-
|
|
2772
|
-
composite.columns.forEach((col, index) => {
|
|
2773
|
-
const subCell = document.createElement('div');
|
|
2774
|
-
subCell.className = 'composite-sub-cell';
|
|
2775
|
-
|
|
2776
|
-
if (this.groupByField && col.field === this.groupByField) {
|
|
2777
|
-
subCell.classList.add('grouped-column');
|
|
2778
|
-
subCell.textContent = '';
|
|
2779
|
-
} else {
|
|
2780
|
-
if (col.subField) {
|
|
2781
|
-
subCell.classList.add('composite-column');
|
|
2782
|
-
subCell.style.display = 'flex';
|
|
2783
|
-
subCell.style.flexDirection = 'column';
|
|
2784
|
-
subCell.style.gap = '2px';
|
|
2785
|
-
|
|
2786
|
-
const mainDiv = document.createElement('div');
|
|
2787
|
-
mainDiv.className = 'composite-main';
|
|
2788
|
-
if (typeof col.render === 'function') {
|
|
2789
|
-
mainDiv.innerHTML = col.render(item[col.field], item);
|
|
2790
|
-
} else {
|
|
2791
|
-
mainDiv.innerHTML = item[col.field] ?? '';
|
|
2792
|
-
}
|
|
2793
|
-
|
|
2794
|
-
const subDiv = document.createElement('div');
|
|
2795
|
-
subDiv.className = 'composite-sub';
|
|
2796
|
-
if (typeof col.subRender === 'function') {
|
|
2797
|
-
subDiv.innerHTML = col.subRender(item[col.subField], item);
|
|
2798
|
-
} else {
|
|
2799
|
-
subDiv.innerHTML = item[col.subField] ?? '';
|
|
2800
|
-
}
|
|
2801
|
-
|
|
2802
|
-
subCell.appendChild(mainDiv);
|
|
2803
|
-
subCell.appendChild(subDiv);
|
|
2804
|
-
} else {
|
|
2805
|
-
if (typeof col.render === 'function') {
|
|
2806
|
-
subCell.innerHTML = col.render(item[col.field], item);
|
|
2807
|
-
} else {
|
|
2808
|
-
subCell.innerHTML = item[col.field] ?? '';
|
|
2809
|
-
}
|
|
2810
|
-
}
|
|
2811
|
-
}
|
|
2812
|
-
|
|
2813
|
-
cell.appendChild(subCell);
|
|
2814
|
-
});
|
|
2815
|
-
} else {
|
|
2816
|
-
const col = composite.columns[0];
|
|
2817
|
-
|
|
2818
|
-
if (this.groupByField && col.field === this.groupByField) {
|
|
2819
|
-
cell.classList.add('grouped-column');
|
|
2820
|
-
cell.textContent = '';
|
|
2821
|
-
} else {
|
|
2822
|
-
if (col.subField) {
|
|
2823
|
-
cell.classList.add('composite-column');
|
|
2824
|
-
|
|
2825
|
-
const mainDiv = document.createElement('div');
|
|
2826
|
-
mainDiv.className = 'composite-main';
|
|
2827
|
-
if (typeof col.render === 'function') {
|
|
2828
|
-
mainDiv.innerHTML = col.render(item[col.field], item);
|
|
2829
|
-
} else {
|
|
2830
|
-
mainDiv.innerHTML = item[col.field] ?? '';
|
|
2831
|
-
}
|
|
2832
|
-
|
|
2833
|
-
const subDiv = document.createElement('div');
|
|
2834
|
-
subDiv.className = 'composite-sub';
|
|
2835
|
-
if (typeof col.subRender === 'function') {
|
|
2836
|
-
subDiv.innerHTML = col.subRender(item[col.subField], item);
|
|
2837
|
-
} else {
|
|
2838
|
-
subDiv.innerHTML = item[col.subField] ?? '';
|
|
2839
|
-
}
|
|
2840
|
-
|
|
2841
|
-
cell.appendChild(mainDiv);
|
|
2842
|
-
cell.appendChild(subDiv);
|
|
2843
|
-
} else {
|
|
2844
|
-
if (typeof col.render === 'function') {
|
|
2845
|
-
cell.innerHTML = col.render(item[col.field], item);
|
|
2846
|
-
} else {
|
|
2847
|
-
cell.innerHTML = item[col.field] ?? '';
|
|
2848
|
-
}
|
|
2849
|
-
}
|
|
2850
|
-
}
|
|
2851
|
-
}
|
|
2852
|
-
|
|
2790
|
+
const cell = this.createCellForComposite(composite, item);
|
|
2853
2791
|
row.appendChild(cell);
|
|
2854
2792
|
});
|
|
2855
2793
|
|
|
2856
2794
|
// Mark as populated
|
|
2857
2795
|
row.dataset.populated = 'true';
|
|
2858
2796
|
|
|
2859
|
-
// Measure actual height and set it explicitly to prevent bouncing on re-renders
|
|
2860
|
-
// Use requestAnimationFrame to ensure DOM has updated
|
|
2861
|
-
requestAnimationFrame(() => {
|
|
2862
|
-
const actualHeight = row.offsetHeight;
|
|
2863
|
-
if (actualHeight > 0) {
|
|
2864
|
-
// Set explicit height to prevent layout recalculation bouncing
|
|
2865
|
-
row.style.minHeight = `${actualHeight}px`;
|
|
2866
|
-
row.style.height = `${actualHeight}px`;
|
|
2867
|
-
|
|
2868
|
-
// Update estimate for future unpopulated rows
|
|
2869
|
-
if (actualHeight > this.estimatedRowHeight) {
|
|
2870
|
-
this.estimatedRowHeight = actualHeight;
|
|
2871
|
-
}
|
|
2872
|
-
}
|
|
2873
|
-
});
|
|
2874
|
-
|
|
2875
2797
|
// Update tab indexes after population
|
|
2876
2798
|
this.updateTabIndexes();
|
|
2877
2799
|
}
|
|
@@ -2981,32 +2903,28 @@ class DivTable {
|
|
|
2981
2903
|
// Use double requestAnimationFrame to ensure layout is fully complete
|
|
2982
2904
|
requestAnimationFrame(() => {
|
|
2983
2905
|
requestAnimationFrame(() => {
|
|
2984
|
-
//
|
|
2985
|
-
// Temporarily remove any height constraints to get true natural height
|
|
2986
|
-
const prevFixedHeight = fixedRow.style.height;
|
|
2987
|
-
const prevScrollHeight = scrollRow.style.height;
|
|
2988
|
-
const prevFixedMinHeight = fixedRow.style.minHeight;
|
|
2989
|
-
const prevScrollMinHeight = scrollRow.style.minHeight;
|
|
2990
|
-
|
|
2906
|
+
// Reset any fixed heights to get natural content height
|
|
2991
2907
|
fixedRow.style.height = '';
|
|
2992
2908
|
scrollRow.style.height = '';
|
|
2993
|
-
fixedRow.style.minHeight = '40px';
|
|
2994
|
-
scrollRow.style.minHeight = '40px';
|
|
2995
2909
|
|
|
2996
|
-
//
|
|
2997
|
-
|
|
2998
|
-
const
|
|
2910
|
+
// Get the maximum height from both rows, including any cell content
|
|
2911
|
+
// Use scrollHeight to capture content that might overflow
|
|
2912
|
+
const fixedHeight = Math.max(fixedRow.offsetHeight, fixedRow.scrollHeight);
|
|
2913
|
+
const scrollHeight = Math.max(scrollRow.offsetHeight, scrollRow.scrollHeight);
|
|
2999
2914
|
|
|
3000
|
-
//
|
|
3001
|
-
|
|
3002
|
-
fixedRow.
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
scrollRow.
|
|
2915
|
+
// Also check individual cell heights
|
|
2916
|
+
let maxCellHeight = 0;
|
|
2917
|
+
fixedRow.querySelectorAll('.div-table-cell').forEach(cell => {
|
|
2918
|
+
maxCellHeight = Math.max(maxCellHeight, cell.offsetHeight, cell.scrollHeight);
|
|
2919
|
+
});
|
|
2920
|
+
scrollRow.querySelectorAll('.div-table-cell').forEach(cell => {
|
|
2921
|
+
maxCellHeight = Math.max(maxCellHeight, cell.offsetHeight, cell.scrollHeight);
|
|
2922
|
+
});
|
|
3006
2923
|
|
|
3007
|
-
|
|
3008
|
-
if (maxHeight >
|
|
3009
|
-
|
|
2924
|
+
const maxHeight = Math.max(fixedHeight, scrollHeight, maxCellHeight);
|
|
2925
|
+
if (maxHeight > 0) {
|
|
2926
|
+
fixedRow.style.height = `${maxHeight}px`;
|
|
2927
|
+
scrollRow.style.height = `${maxHeight}px`;
|
|
3010
2928
|
}
|
|
3011
2929
|
});
|
|
3012
2930
|
});
|
|
@@ -3198,106 +3116,9 @@ class DivTable {
|
|
|
3198
3116
|
row.appendChild(checkboxCell);
|
|
3199
3117
|
}
|
|
3200
3118
|
|
|
3201
|
-
// Data columns - render using composite structure
|
|
3119
|
+
// Data columns - render using composite structure with proper alignment
|
|
3202
3120
|
compositeColumns.forEach(composite => {
|
|
3203
|
-
const cell =
|
|
3204
|
-
cell.className = 'div-table-cell';
|
|
3205
|
-
|
|
3206
|
-
if (composite.compositeName) {
|
|
3207
|
-
// Composite cell with multiple columns stacked vertically
|
|
3208
|
-
cell.classList.add('composite-cell');
|
|
3209
|
-
cell.style.display = 'flex';
|
|
3210
|
-
cell.style.flexDirection = 'column';
|
|
3211
|
-
cell.style.gap = '4px';
|
|
3212
|
-
|
|
3213
|
-
composite.columns.forEach((col, index) => {
|
|
3214
|
-
const subCell = document.createElement('div');
|
|
3215
|
-
subCell.className = 'composite-sub-cell';
|
|
3216
|
-
|
|
3217
|
-
// For grouped column, show empty
|
|
3218
|
-
if (this.groupByField && col.field === this.groupByField) {
|
|
3219
|
-
subCell.classList.add('grouped-column');
|
|
3220
|
-
subCell.textContent = '';
|
|
3221
|
-
} else {
|
|
3222
|
-
// Check if this column has subField (vertical stacking within the sub-cell)
|
|
3223
|
-
if (col.subField) {
|
|
3224
|
-
subCell.classList.add('composite-column');
|
|
3225
|
-
subCell.style.display = 'flex';
|
|
3226
|
-
subCell.style.flexDirection = 'column';
|
|
3227
|
-
subCell.style.gap = '2px';
|
|
3228
|
-
|
|
3229
|
-
const mainDiv = document.createElement('div');
|
|
3230
|
-
mainDiv.className = 'composite-main';
|
|
3231
|
-
if (typeof col.render === 'function') {
|
|
3232
|
-
mainDiv.innerHTML = col.render(item[col.field], item);
|
|
3233
|
-
} else {
|
|
3234
|
-
mainDiv.innerHTML = item[col.field] ?? '';
|
|
3235
|
-
}
|
|
3236
|
-
|
|
3237
|
-
const subDiv = document.createElement('div');
|
|
3238
|
-
subDiv.className = 'composite-sub';
|
|
3239
|
-
if (typeof col.subRender === 'function') {
|
|
3240
|
-
subDiv.innerHTML = col.subRender(item[col.subField], item);
|
|
3241
|
-
} else {
|
|
3242
|
-
subDiv.innerHTML = item[col.subField] ?? '';
|
|
3243
|
-
}
|
|
3244
|
-
|
|
3245
|
-
subCell.appendChild(mainDiv);
|
|
3246
|
-
subCell.appendChild(subDiv);
|
|
3247
|
-
} else {
|
|
3248
|
-
// Regular rendering
|
|
3249
|
-
if (typeof col.render === 'function') {
|
|
3250
|
-
subCell.innerHTML = col.render(item[col.field], item);
|
|
3251
|
-
} else {
|
|
3252
|
-
subCell.innerHTML = item[col.field] ?? '';
|
|
3253
|
-
}
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
|
|
3257
|
-
cell.appendChild(subCell);
|
|
3258
|
-
});
|
|
3259
|
-
} else {
|
|
3260
|
-
// Single column
|
|
3261
|
-
const col = composite.columns[0];
|
|
3262
|
-
|
|
3263
|
-
// For grouped column, show empty
|
|
3264
|
-
if (this.groupByField && col.field === this.groupByField) {
|
|
3265
|
-
cell.classList.add('grouped-column');
|
|
3266
|
-
cell.textContent = '';
|
|
3267
|
-
} else {
|
|
3268
|
-
// Check if this is a composite column with subField (vertical stacking)
|
|
3269
|
-
if (col.subField) {
|
|
3270
|
-
cell.classList.add('composite-column');
|
|
3271
|
-
|
|
3272
|
-
const mainDiv = document.createElement('div');
|
|
3273
|
-
mainDiv.className = 'composite-main';
|
|
3274
|
-
if (typeof col.render === 'function') {
|
|
3275
|
-
mainDiv.innerHTML = col.render(item[col.field], item);
|
|
3276
|
-
} else {
|
|
3277
|
-
mainDiv.innerHTML = item[col.field] ?? '';
|
|
3278
|
-
}
|
|
3279
|
-
|
|
3280
|
-
const subDiv = document.createElement('div');
|
|
3281
|
-
subDiv.className = 'composite-sub';
|
|
3282
|
-
if (typeof col.subRender === 'function') {
|
|
3283
|
-
subDiv.innerHTML = col.subRender(item[col.subField], item);
|
|
3284
|
-
} else {
|
|
3285
|
-
subDiv.innerHTML = item[col.subField] ?? '';
|
|
3286
|
-
}
|
|
3287
|
-
|
|
3288
|
-
cell.appendChild(mainDiv);
|
|
3289
|
-
cell.appendChild(subDiv);
|
|
3290
|
-
} else {
|
|
3291
|
-
// Regular column rendering
|
|
3292
|
-
if (typeof col.render === 'function') {
|
|
3293
|
-
cell.innerHTML = col.render(item[col.field], item);
|
|
3294
|
-
} else {
|
|
3295
|
-
cell.innerHTML = item[col.field] ?? '';
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
}
|
|
3299
|
-
}
|
|
3300
|
-
|
|
3121
|
+
const cell = this.createCellForComposite(composite, item);
|
|
3301
3122
|
row.appendChild(cell);
|
|
3302
3123
|
});
|
|
3303
3124
|
|
|
@@ -3586,9 +3407,6 @@ class DivTable {
|
|
|
3586
3407
|
if (composite.compositeName) {
|
|
3587
3408
|
// Composite cell with multiple columns stacked vertically
|
|
3588
3409
|
cell.classList.add('composite-cell');
|
|
3589
|
-
cell.style.display = 'flex';
|
|
3590
|
-
cell.style.flexDirection = 'column';
|
|
3591
|
-
cell.style.gap = '4px';
|
|
3592
3410
|
|
|
3593
3411
|
composite.columns.forEach((col, index) => {
|
|
3594
3412
|
const subCell = document.createElement('div');
|
|
@@ -3611,6 +3429,8 @@ class DivTable {
|
|
|
3611
3429
|
} else {
|
|
3612
3430
|
mainDiv.innerHTML = item[col.field] ?? '';
|
|
3613
3431
|
}
|
|
3432
|
+
// Set title for tooltip on main content
|
|
3433
|
+
mainDiv.title = this.stripHtmlTags(mainDiv.innerHTML);
|
|
3614
3434
|
|
|
3615
3435
|
const subDiv = document.createElement('div');
|
|
3616
3436
|
subDiv.className = 'composite-sub';
|
|
@@ -3619,6 +3439,8 @@ class DivTable {
|
|
|
3619
3439
|
} else {
|
|
3620
3440
|
subDiv.innerHTML = item[col.subField] ?? '';
|
|
3621
3441
|
}
|
|
3442
|
+
// Set title for tooltip on sub content
|
|
3443
|
+
subDiv.title = this.stripHtmlTags(subDiv.innerHTML);
|
|
3622
3444
|
|
|
3623
3445
|
subCell.appendChild(mainDiv);
|
|
3624
3446
|
subCell.appendChild(subDiv);
|
|
@@ -3628,6 +3450,8 @@ class DivTable {
|
|
|
3628
3450
|
} else {
|
|
3629
3451
|
subCell.innerHTML = item[col.field] ?? '';
|
|
3630
3452
|
}
|
|
3453
|
+
// Set title for tooltip on sub-cell
|
|
3454
|
+
subCell.title = this.stripHtmlTags(subCell.innerHTML);
|
|
3631
3455
|
}
|
|
3632
3456
|
}
|
|
3633
3457
|
|
|
@@ -3651,6 +3475,8 @@ class DivTable {
|
|
|
3651
3475
|
} else {
|
|
3652
3476
|
mainDiv.innerHTML = item[col.field] ?? '';
|
|
3653
3477
|
}
|
|
3478
|
+
// Set title for tooltip on main content
|
|
3479
|
+
mainDiv.title = this.stripHtmlTags(mainDiv.innerHTML);
|
|
3654
3480
|
|
|
3655
3481
|
const subDiv = document.createElement('div');
|
|
3656
3482
|
subDiv.className = 'composite-sub';
|
|
@@ -3659,15 +3485,23 @@ class DivTable {
|
|
|
3659
3485
|
} else {
|
|
3660
3486
|
subDiv.innerHTML = item[col.subField] ?? '';
|
|
3661
3487
|
}
|
|
3488
|
+
// Set title for tooltip on sub content
|
|
3489
|
+
subDiv.title = this.stripHtmlTags(subDiv.innerHTML);
|
|
3662
3490
|
|
|
3663
3491
|
cell.appendChild(mainDiv);
|
|
3664
3492
|
cell.appendChild(subDiv);
|
|
3665
3493
|
} else {
|
|
3494
|
+
// Wrap content in a span for proper flex alignment
|
|
3495
|
+
const contentSpan = document.createElement('span');
|
|
3496
|
+
contentSpan.className = 'cell-content';
|
|
3666
3497
|
if (typeof col.render === 'function') {
|
|
3667
|
-
|
|
3498
|
+
contentSpan.innerHTML = col.render(item[col.field], item);
|
|
3668
3499
|
} else {
|
|
3669
|
-
|
|
3500
|
+
contentSpan.innerHTML = item[col.field] ?? '';
|
|
3670
3501
|
}
|
|
3502
|
+
// Set title for tooltip
|
|
3503
|
+
contentSpan.title = this.stripHtmlTags(contentSpan.innerHTML);
|
|
3504
|
+
cell.appendChild(contentSpan);
|
|
3671
3505
|
}
|
|
3672
3506
|
}
|
|
3673
3507
|
}
|
|
@@ -5858,6 +5692,10 @@ class DivTable {
|
|
|
5858
5692
|
const formattedValue = this.formatAggregateValue(aggregateValue, col);
|
|
5859
5693
|
subCell.innerHTML = formattedValue;
|
|
5860
5694
|
subCell.classList.add('aggregate-value');
|
|
5695
|
+
// Apply column alignment
|
|
5696
|
+
if (col.align) {
|
|
5697
|
+
subCell.style.textAlign = col.align;
|
|
5698
|
+
}
|
|
5861
5699
|
}
|
|
5862
5700
|
|
|
5863
5701
|
cell.appendChild(subCell);
|
|
@@ -5866,10 +5704,21 @@ class DivTable {
|
|
|
5866
5704
|
// Single column
|
|
5867
5705
|
const col = composite.columns[0];
|
|
5868
5706
|
|
|
5707
|
+
// Apply column alignment
|
|
5708
|
+
if (col.align) {
|
|
5709
|
+
cell.style.textAlign = col.align;
|
|
5710
|
+
cell.style.justifyContent = col.align === 'right' ? 'flex-end' :
|
|
5711
|
+
col.align === 'center' ? 'center' : 'flex-start';
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5869
5714
|
if (col.aggregate) {
|
|
5870
5715
|
const aggregateValue = this.calculateAggregate(col, aggregationData);
|
|
5871
5716
|
const formattedValue = this.formatAggregateValue(aggregateValue, col);
|
|
5872
|
-
|
|
5717
|
+
// Wrap in span for proper flex alignment
|
|
5718
|
+
const contentSpan = document.createElement('span');
|
|
5719
|
+
contentSpan.className = 'cell-content';
|
|
5720
|
+
contentSpan.innerHTML = formattedValue;
|
|
5721
|
+
cell.appendChild(contentSpan);
|
|
5873
5722
|
cell.classList.add('aggregate-value');
|
|
5874
5723
|
}
|
|
5875
5724
|
}
|
|
@@ -5947,6 +5796,10 @@ class DivTable {
|
|
|
5947
5796
|
const formattedValue = this.formatAggregateValue(aggregateValue, col);
|
|
5948
5797
|
subCell.innerHTML = formattedValue;
|
|
5949
5798
|
subCell.classList.add('aggregate-value');
|
|
5799
|
+
// Apply column alignment
|
|
5800
|
+
if (col.align) {
|
|
5801
|
+
subCell.style.textAlign = col.align;
|
|
5802
|
+
}
|
|
5950
5803
|
}
|
|
5951
5804
|
|
|
5952
5805
|
cell.appendChild(subCell);
|
|
@@ -5954,10 +5807,21 @@ class DivTable {
|
|
|
5954
5807
|
} else {
|
|
5955
5808
|
const col = composite.columns[0];
|
|
5956
5809
|
|
|
5810
|
+
// Apply column alignment
|
|
5811
|
+
if (col.align) {
|
|
5812
|
+
cell.style.textAlign = col.align;
|
|
5813
|
+
cell.style.justifyContent = col.align === 'right' ? 'flex-end' :
|
|
5814
|
+
col.align === 'center' ? 'center' : 'flex-start';
|
|
5815
|
+
}
|
|
5816
|
+
|
|
5957
5817
|
if (col.aggregate) {
|
|
5958
5818
|
const aggregateValue = this.calculateAggregate(col, groupData);
|
|
5959
5819
|
const formattedValue = this.formatAggregateValue(aggregateValue, col);
|
|
5960
|
-
|
|
5820
|
+
// Wrap in span for proper flex alignment
|
|
5821
|
+
const contentSpan = document.createElement('span');
|
|
5822
|
+
contentSpan.className = 'cell-content';
|
|
5823
|
+
contentSpan.innerHTML = formattedValue;
|
|
5824
|
+
cell.appendChild(contentSpan);
|
|
5961
5825
|
cell.classList.add('aggregate-value');
|
|
5962
5826
|
}
|
|
5963
5827
|
}
|
|
@@ -6135,7 +5999,11 @@ class DivTable {
|
|
|
6135
5999
|
if (col.aggregate) {
|
|
6136
6000
|
const aggregateValue = this.calculateAggregate(col, data);
|
|
6137
6001
|
const formattedValue = this.formatAggregateValue(aggregateValue, col);
|
|
6138
|
-
|
|
6002
|
+
// Wrap in span for proper flex alignment
|
|
6003
|
+
const contentSpan = document.createElement('span');
|
|
6004
|
+
contentSpan.className = 'cell-content';
|
|
6005
|
+
contentSpan.innerHTML = formattedValue;
|
|
6006
|
+
cell.appendChild(contentSpan);
|
|
6139
6007
|
cell.classList.add('aggregate-value');
|
|
6140
6008
|
}
|
|
6141
6009
|
}
|