Add large table search filter
This commit is contained in:
@@ -78,8 +78,19 @@
|
|||||||
<p class="sg-preview-label">Component: Large Table</p>
|
<p class="sg-preview-label">Component: Large Table</p>
|
||||||
|
|
||||||
<article class="sg-card sg-large-table" data-component="large-table" role="table" aria-label="Beispiel Large Table">
|
<article class="sg-card sg-large-table" data-component="large-table" role="table" aria-label="Beispiel Large Table">
|
||||||
<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue" data-component-part="large-table-header">
|
<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-large-table__title-segment" data-component-part="large-table-header">
|
||||||
<div class="sg-strong">Large Table</div>
|
<div class="sg-strong">Large Table</div>
|
||||||
|
<div class="sg-large-table__search" data-component="search-field">
|
||||||
|
<label class="sg-large-table__search-label" for="large-table-search">Suchfeld</label>
|
||||||
|
<input
|
||||||
|
class="sg-large-table__search-input"
|
||||||
|
id="large-table-search"
|
||||||
|
type="search"
|
||||||
|
placeholder="Tabelle durchsuchen"
|
||||||
|
aria-label="Tabelle durchsuchen"
|
||||||
|
data-large-table-search
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</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-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">
|
||||||
@@ -209,9 +220,11 @@
|
|||||||
const headerButtons = headerCells.map((cell) => cell.querySelector('.sg-large-table__sort-button'));
|
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 rows = Array.from(table.querySelectorAll('[data-component-part="large-table-row"]'));
|
||||||
const headerRow = table.querySelector('[data-component-part="large-table-header-row"]');
|
const headerRow = table.querySelector('[data-component-part="large-table-header-row"]');
|
||||||
|
const searchInput = table.querySelector('[data-large-table-search]');
|
||||||
const state = {
|
const state = {
|
||||||
columnIndex: 0,
|
columnIndex: 0,
|
||||||
direction: 'ascending',
|
direction: 'ascending',
|
||||||
|
query: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
function setHeaderState(activeIndex, direction) {
|
function setHeaderState(activeIndex, direction) {
|
||||||
@@ -251,21 +264,33 @@
|
|||||||
return direction === 'ascending' ? comparison : -comparison;
|
return direction === 'ascending' ? comparison : -comparison;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortRows(columnIndex, direction) {
|
function rowMatchesQuery(row, query) {
|
||||||
|
if (!query) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(row.querySelectorAll('[role="cell"]')).some((cell) => {
|
||||||
|
const value = cell.textContent || '';
|
||||||
|
return value.toLowerCase().includes(query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderRows() {
|
||||||
const sortedRows = rows.slice().sort((leftRow, rightRow) => {
|
const sortedRows = rows.slice().sort((leftRow, rightRow) => {
|
||||||
const leftCell = leftRow.querySelectorAll('[role="cell"]')[columnIndex];
|
const leftCell = leftRow.querySelectorAll('[role="cell"]')[state.columnIndex];
|
||||||
const rightCell = rightRow.querySelectorAll('[role="cell"]')[columnIndex];
|
const rightCell = rightRow.querySelectorAll('[role="cell"]')[state.columnIndex];
|
||||||
const leftValue = leftCell ? leftCell.textContent : '';
|
const leftValue = leftCell ? leftCell.textContent : '';
|
||||||
const rightValue = rightCell ? rightCell.textContent : '';
|
const rightValue = rightCell ? rightCell.textContent : '';
|
||||||
|
|
||||||
return compareValues(leftValue, rightValue, direction);
|
return compareValues(leftValue, rightValue, state.direction);
|
||||||
});
|
});
|
||||||
|
|
||||||
sortedRows.forEach((row) => {
|
sortedRows.forEach((row) => {
|
||||||
table.appendChild(row);
|
table.appendChild(row);
|
||||||
|
row.hidden = !rowMatchesQuery(row, state.query);
|
||||||
});
|
});
|
||||||
|
|
||||||
setHeaderState(columnIndex, direction);
|
setHeaderState(state.columnIndex, state.direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
headerButtons.forEach((button, index) => {
|
headerButtons.forEach((button, index) => {
|
||||||
@@ -280,14 +305,21 @@
|
|||||||
|
|
||||||
state.columnIndex = index;
|
state.columnIndex = index;
|
||||||
state.direction = direction;
|
state.direction = direction;
|
||||||
sortRows(index, direction);
|
renderRows();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.addEventListener('input', () => {
|
||||||
|
state.query = searchInput.value.trim().toLowerCase();
|
||||||
|
renderRows();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (headerRow) {
|
if (headerRow) {
|
||||||
setHeaderState(state.columnIndex, state.direction);
|
setHeaderState(state.columnIndex, state.direction);
|
||||||
}
|
}
|
||||||
sortRows(state.columnIndex, state.direction);
|
renderRows();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,49 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sg-large-table__title-segment {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: var(--spacing-large);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sg-large-table__search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: var(--spacing-small);
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sg-large-table__search-label {
|
||||||
|
color: var(--text-card-header);
|
||||||
|
font-family: var(--font-family-base);
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
line-height: var(--line-height-base);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sg-large-table__search-input {
|
||||||
|
width: 14rem;
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0.35rem var(--spacing-small);
|
||||||
|
border: var(--border-none);
|
||||||
|
border-radius: var(--radius-card);
|
||||||
|
background: var(--color-white);
|
||||||
|
color: var(--text-control-default);
|
||||||
|
font-family: var(--font-family-base);
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
line-height: var(--line-height-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sg-large-table__search-input:focus-visible {
|
||||||
|
outline: 2px solid var(--color-white);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.sg-large-table__row {
|
.sg-large-table__row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
|||||||
Reference in New Issue
Block a user