Add sortable large table headers
This commit is contained in:
@@ -83,11 +83,36 @@
|
||||
</div>
|
||||
|
||||
<div class="sg-card-segment sg-card-segment--body sg-card-segment--white sg-large-table__row sg-large-table__row--header" role="row" data-component-part="large-table-header-row">
|
||||
<div class="sg-large-table__cell" role="columnheader">Spalte 1</div>
|
||||
<div class="sg-large-table__cell" role="columnheader">Spalte 2</div>
|
||||
<div class="sg-large-table__cell" role="columnheader">Spalte 3</div>
|
||||
<div class="sg-large-table__cell" role="columnheader">Spalte 4</div>
|
||||
<div class="sg-large-table__cell" role="columnheader">Spalte 5</div>
|
||||
<div class="sg-large-table__cell sg-large-table__cell--header" role="columnheader" aria-sort="none" data-sort-key="0">
|
||||
<button class="sg-large-table__sort-button" type="button" aria-label="Spalte 1 sortieren">
|
||||
<span class="sg-large-table__sort-label">Spalte 1</span>
|
||||
<span class="sg-large-table__sort-icon" aria-hidden="true">↕</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sg-large-table__cell sg-large-table__cell--header" role="columnheader" aria-sort="none" data-sort-key="1">
|
||||
<button class="sg-large-table__sort-button" type="button" aria-label="Spalte 2 sortieren">
|
||||
<span class="sg-large-table__sort-label">Spalte 2</span>
|
||||
<span class="sg-large-table__sort-icon" aria-hidden="true">↕</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sg-large-table__cell sg-large-table__cell--header" role="columnheader" aria-sort="none" data-sort-key="2">
|
||||
<button class="sg-large-table__sort-button" type="button" aria-label="Spalte 3 sortieren">
|
||||
<span class="sg-large-table__sort-label">Spalte 3</span>
|
||||
<span class="sg-large-table__sort-icon" aria-hidden="true">↕</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sg-large-table__cell sg-large-table__cell--header" role="columnheader" aria-sort="none" data-sort-key="3">
|
||||
<button class="sg-large-table__sort-button" type="button" aria-label="Spalte 4 sortieren">
|
||||
<span class="sg-large-table__sort-label">Spalte 4</span>
|
||||
<span class="sg-large-table__sort-icon" aria-hidden="true">↕</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sg-large-table__cell sg-large-table__cell--header" role="columnheader" aria-sort="none" data-sort-key="4">
|
||||
<button class="sg-large-table__sort-button" type="button" aria-label="Spalte 5 sortieren">
|
||||
<span class="sg-large-table__sort-label">Spalte 5</span>
|
||||
<span class="sg-large-table__sort-icon" aria-hidden="true">↕</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sg-card-segment sg-card-segment--body sg-card-segment--white sg-large-table__row" role="row" data-component-part="large-table-row">
|
||||
@@ -173,5 +198,98 @@
|
||||
|
||||
</section>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const table = document.querySelector('[data-component="large-table"]');
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
const headerCells = Array.from(table.querySelectorAll('[role="columnheader"][data-sort-key]'));
|
||||
const headerButtons = headerCells.map((cell) => cell.querySelector('.sg-large-table__sort-button'));
|
||||
const rows = Array.from(table.querySelectorAll('[data-component-part="large-table-row"]'));
|
||||
const headerRow = table.querySelector('[data-component-part="large-table-header-row"]');
|
||||
const state = {
|
||||
columnIndex: 0,
|
||||
direction: 'ascending',
|
||||
};
|
||||
|
||||
function setHeaderState(activeIndex, direction) {
|
||||
headerCells.forEach((cell, index) => {
|
||||
const icon = cell.querySelector('.sg-large-table__sort-icon');
|
||||
const isActive = index === activeIndex;
|
||||
|
||||
cell.setAttribute('aria-sort', isActive ? direction : 'none');
|
||||
if (icon) {
|
||||
icon.textContent = isActive ? (direction === 'ascending' ? '↑' : '↓') : '↕';
|
||||
}
|
||||
});
|
||||
|
||||
headerButtons.forEach((button, index) => {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
const label = `Spalte ${index + 1}`;
|
||||
button.setAttribute(
|
||||
'aria-label',
|
||||
index === activeIndex
|
||||
? `${label} ${direction === 'ascending' ? 'aufsteigend' : 'absteigend'} sortiert`
|
||||
: `${label} sortieren`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function compareValues(left, right, direction) {
|
||||
const normalizedLeft = left.trim();
|
||||
const normalizedRight = right.trim();
|
||||
const comparison = normalizedLeft.localeCompare(normalizedRight, 'de', {
|
||||
numeric: true,
|
||||
sensitivity: 'base',
|
||||
});
|
||||
|
||||
return direction === 'ascending' ? comparison : -comparison;
|
||||
}
|
||||
|
||||
function sortRows(columnIndex, direction) {
|
||||
const sortedRows = rows.slice().sort((leftRow, rightRow) => {
|
||||
const leftCell = leftRow.querySelectorAll('[role="cell"]')[columnIndex];
|
||||
const rightCell = rightRow.querySelectorAll('[role="cell"]')[columnIndex];
|
||||
const leftValue = leftCell ? leftCell.textContent : '';
|
||||
const rightValue = rightCell ? rightCell.textContent : '';
|
||||
|
||||
return compareValues(leftValue, rightValue, direction);
|
||||
});
|
||||
|
||||
sortedRows.forEach((row) => {
|
||||
table.appendChild(row);
|
||||
});
|
||||
|
||||
setHeaderState(columnIndex, direction);
|
||||
}
|
||||
|
||||
headerButtons.forEach((button, index) => {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
const direction = state.columnIndex === index && state.direction === 'ascending'
|
||||
? 'descending'
|
||||
: 'ascending';
|
||||
|
||||
state.columnIndex = index;
|
||||
state.direction = direction;
|
||||
sortRows(index, direction);
|
||||
});
|
||||
});
|
||||
|
||||
if (headerRow) {
|
||||
setHeaderState(state.columnIndex, state.direction);
|
||||
}
|
||||
sortRows(state.columnIndex, state.direction);
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user