Last active
July 7, 2023 10:04
-
-
Save DvdGiessen/6256ab5cbdb17e58593a1d74a9b009e9 to your computer and use it in GitHub Desktop.
JS function to make tables sortable and filterable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sortableFilterable(tableElement) { | |
if (tableElement.tHead && tableElement.tHead.rows.length > 0) { | |
const headers = tableElement.tHead.rows.item(0).cells; | |
for (const header of headers) { | |
if (typeof header.dataset.sortType !== 'undefined' && ['auto', 'string', 'integer'].indexOf(header.dataset.sortType) >= 0) { | |
header.addEventListener('click', () => { | |
// Classes | |
const reverseSort = header.classList.contains('sorted') && !header.classList.contains('sorted-reverse'); | |
for (const h of headers) { | |
h.classList.remove('sorted', 'sorted-reverse'); | |
} | |
header.classList.add('sorted'); | |
if (reverseSort) { | |
header.classList.add('sorted-reverse'); | |
} | |
// Find offset | |
let cellIndex = 0; | |
for (const h of headers) { | |
if (h === header) break; | |
cellIndex += h.colspan || 1; | |
} | |
// Sort each tbody | |
for (const tbody of tableElement.tBodies) { | |
const rows = Array.prototype.slice.call(tbody.rows); | |
rows.sort((a, b) => { | |
if (reverseSort) { | |
const c = a; | |
a = b; | |
b = c; | |
} | |
if (a.cells.length <= cellIndex || b.cells.length <= cellIndex) { | |
return 0; | |
} | |
const aCell = a.cells.item(cellIndex); | |
const bCell = b.cells.item(cellIndex); | |
const aValue = typeof aCell.dataset.sortValue !== 'undefined' ? aCell.dataset.sortValue : aCell.innerText; | |
const bValue = typeof bCell.dataset.sortValue !== 'undefined' ? bCell.dataset.sortValue : bCell.innerText; | |
let type = typeof header.dataset.sortType !== 'undefined' ? header.dataset.sortType : 'auto'; | |
if (type === 'auto') { | |
if(!isNaN(aValue) && !isNaN(bValue)) { | |
type = 'integer'; | |
} else { | |
type = 'string'; | |
} | |
} | |
switch (type) { | |
case 'string': | |
return aValue.localeCompare(bValue, undefined, {sensitivity: 'base', numeric: true}); | |
case 'integer': | |
return ((+aValue) - (+bValue)) || 0; | |
default: | |
return 0; | |
} | |
}); | |
// Reorder the DOM elements | |
for (const row of rows) { | |
tbody.appendChild(row); | |
} | |
} | |
}); | |
header.style.cursor = 'pointer'; | |
} | |
} | |
} | |
const filterInput = document.createElement('input'); | |
filterInput.type = 'search'; | |
filterInput.addEventListener('input', () => { | |
const terms = filterInput.value.toLowerCase().split(' '); | |
for (const tbody of tableElement.tBodies) { | |
for (const row of tbody.rows) { | |
const rowContent = row.innerHTML.replace(/<[^>]+>/g, ' ').toLowerCase(); | |
let shouldHide = true; | |
for (const term of terms) { | |
if (rowContent.indexOf(term) >= 0) { | |
shouldHide = false; | |
break; | |
} | |
} | |
row.style.display = shouldHide ? 'none' : null; | |
} | |
} | |
}); | |
tableElement.parentElement.insertBefore(filterInput, tableElement); | |
return filterInput; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment