mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2025-01-18 17:02:31 +00:00
Table sorting.
This commit is contained in:
parent
51cf09ece7
commit
29e16b66b7
@ -20,7 +20,9 @@ and the SRTM altitude are in <b>bold</b> if the discrepancy is more than 60m ver
|
||||
|
||||
<p>Unless otherwise specified data is expressed in UTM in WGS84 datum. Coordinates are expresed in meters.</p>
|
||||
|
||||
<table cellpadding="6" cellspacing="8">
|
||||
<p>Click on column headings to sort.</p>
|
||||
|
||||
<table cellpadding="6" cellspacing="8" class="table-sort">
|
||||
<tr><th>Survex Station</th><th>x [m]</th><th>y [m]</th><th>lat. [deg]</th><th>long. [deg]</th><th>alt [m]</th><th>SRTM<br> alt</th><th>SRTM [m]<br> ref</th><th>Used on <br />this Entrance</th><th>Cave</th></tr>
|
||||
{% for s in stations %}
|
||||
<tr>
|
||||
@ -110,6 +112,399 @@ Coordinate systems in Austria are explained in:<br>
|
||||
<a href="/stations">Troggle UTM and lat./lomg. and altitude report</a><br>
|
||||
<a href="/entrances">Troggle entrances</a><br>
|
||||
|
||||
<!--
|
||||
This script is added for ease of use.
|
||||
You can safely delete it.
|
||||
|
||||
Radost Waszkiewicz (2023)
|
||||
-->
|
||||
<script>
|
||||
/*
|
||||
table-sort-js
|
||||
Author: Lee Wannacott
|
||||
Licence: MIT License Copyright (c) 2021 Lee Wannacott
|
||||
*/
|
||||
|
||||
function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
|
||||
function getHTMLTables() {
|
||||
if (testingTableSortJS === true) {
|
||||
const getTagTable = domDocumentWindow.getElementsByTagName("table");
|
||||
return [getTagTable];
|
||||
} else {
|
||||
const getTagTable = document.getElementsByTagName("table");
|
||||
return [getTagTable];
|
||||
}
|
||||
}
|
||||
|
||||
const [getTagTable] = getHTMLTables();
|
||||
const columnIndexAndTableRow = {};
|
||||
const fileSizeColumnTextAndRow = {};
|
||||
for (let table of getTagTable) {
|
||||
if (table.classList.contains("table-sort")) {
|
||||
makeTableSortable(table);
|
||||
}
|
||||
}
|
||||
|
||||
function makeTableSortable(sortableTable) {
|
||||
let createTableHead;
|
||||
let tableBody;
|
||||
if (sortableTable.getElementsByTagName("thead").length === 0) {
|
||||
if (testingTableSortJS === true) {
|
||||
createTableHead = domDocumentWindow.createElement("thead");
|
||||
} else {
|
||||
createTableHead = document.createElement("thead");
|
||||
}
|
||||
createTableHead.appendChild(sortableTable.rows[0]);
|
||||
sortableTable.insertBefore(createTableHead, sortableTable.firstChild);
|
||||
if (sortableTable.querySelectorAll("tbody").length > 1) {
|
||||
tableBody = sortableTable.querySelectorAll("tbody")[1];
|
||||
} else {
|
||||
tableBody = sortableTable.querySelector("tbody");
|
||||
}
|
||||
} else {
|
||||
tableBody = sortableTable.querySelector("tbody");
|
||||
}
|
||||
|
||||
const tableHead = sortableTable.querySelector("thead");
|
||||
const tableHeadHeaders = tableHead.querySelectorAll("th");
|
||||
|
||||
for (let [columnIndex, th] of tableHeadHeaders.entries()) {
|
||||
if (!th.classList.contains("disable-sort")) {
|
||||
th.style.cursor = "pointer";
|
||||
makeEachColumnSortable(th, columnIndex, tableBody, sortableTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeEachColumnSortable(th, columnIndex, tableBody, sortableTable) {
|
||||
const desc = th.classList.contains("order-by-desc");
|
||||
let tableArrows = sortableTable.classList.contains("table-arrows");
|
||||
const [arrowUp, arrowDown] = [" ▲", " ▼"];
|
||||
const fillValue = "!X!Y!Z!";
|
||||
|
||||
if (desc && tableArrows) {
|
||||
th.insertAdjacentText("beforeend", arrowDown);
|
||||
} else if (tableArrows) {
|
||||
th.insertAdjacentText("beforeend", arrowUp);
|
||||
}
|
||||
|
||||
function sortDataAttributes(tableRows, columnData) {
|
||||
for (let [i, tr] of tableRows.entries()) {
|
||||
const dataAttributeTd = tr.querySelectorAll("td").item(columnIndex)
|
||||
.dataset.sort;
|
||||
columnData.push(`${dataAttributeTd}#${i}`);
|
||||
columnIndexAndTableRow[columnData[i]] = tr.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
function sortFileSize(tableRows, columnData) {
|
||||
const numberWithUnitType =
|
||||
/[.0-9]+(\s?B|\s?KB|\s?KiB|\s?MB|\s?MiB|\s?GB|\s?GiB|T\s?B|\s?TiB)/i;
|
||||
const unitType =
|
||||
/(\s?B|\s?KB|\s?KiB|\s?MB|\s?MiB|\s?GB|G\s?iB|\s?TB|\s?TiB)/i;
|
||||
const fileSizes = {
|
||||
Kibibyte: 1024,
|
||||
Mebibyte: 1.049e6,
|
||||
Gibibyte: 1.074e9,
|
||||
Tebibyte: 1.1e12,
|
||||
Pebibyte: 1.126e15,
|
||||
Kilobyte: 1000,
|
||||
Megabyte: 1e6,
|
||||
Gigabyte: 1e9,
|
||||
Terabyte: 1e12,
|
||||
};
|
||||
function removeUnitTypeConvertToBytes(fileSizeTd, _replace, i) {
|
||||
fileSizeTd = fileSizeTd.replace(unitType, "");
|
||||
fileSizeTd = fileSizeTd.replace(
|
||||
fileSizeTd,
|
||||
fileSizeTd * fileSizes[_replace]
|
||||
);
|
||||
if (i) {
|
||||
columnData.push(`${fileSizeTd}#${i}`);
|
||||
}
|
||||
return fileSizeTd;
|
||||
}
|
||||
for (let [i, tr] of tableRows.entries()) {
|
||||
let fileSizeTd = tr
|
||||
.querySelectorAll("td")
|
||||
.item(columnIndex).textContent;
|
||||
if (fileSizeTd.match(numberWithUnitType)) {
|
||||
if (fileSizeTd.match(/\s?KB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Kilobyte", i);
|
||||
} else if (fileSizeTd.match(/\s?KiB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Kibibyte", i);
|
||||
} else if (fileSizeTd.match(/\s?MB/i)) {
|
||||
// TODO: figure out why refactoring this line breaks test.
|
||||
fileSizeTd = removeUnitTypeConvertToBytes(fileSizeTd, "Megabyte");
|
||||
columnData.push(`${fileSizeTd}#${i}`);
|
||||
} else if (fileSizeTd.match(/\s?MiB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Mebibyte", i);
|
||||
} else if (fileSizeTd.match(/\s?GB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Gigabyte", i);
|
||||
} else if (fileSizeTd.match(/\s?GiB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Gibibyte", i);
|
||||
} else if (fileSizeTd.match(/\s?TB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Terabyte", i);
|
||||
} else if (fileSizeTd.match(/\s?TiB/i)) {
|
||||
removeUnitTypeConvertToBytes(fileSizeTd, "Tebibyte", i);
|
||||
} else if (fileSizeTd.match(/\s?B/i)) {
|
||||
fileSizeTd = fileSizeTd.replace(unitType, "");
|
||||
columnData.push(`${fileSizeTd}#${i}`);
|
||||
}
|
||||
} else {
|
||||
columnData.push(`${fillValue}#${i}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let [timesClickedColumn, columnIndexesClicked] = [0, []];
|
||||
|
||||
function rememberSort(timesClickedColumn, columnIndexesClicked) {
|
||||
// if user clicked different column from first column reset times clicked.
|
||||
columnIndexesClicked.push(columnIndex);
|
||||
if (timesClickedColumn === 1 && columnIndexesClicked.length > 1) {
|
||||
const lastColumnClicked =
|
||||
columnIndexesClicked[columnIndexesClicked.length - 1];
|
||||
const secondLastColumnClicked =
|
||||
columnIndexesClicked[columnIndexesClicked.length - 2];
|
||||
if (lastColumnClicked !== secondLastColumnClicked) {
|
||||
timesClickedColumn = 0;
|
||||
columnIndexesClicked.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getColSpanData(sortableTable, colSpanData, colSpanSum) {
|
||||
sortableTable.querySelectorAll("th").forEach((th, index) => {
|
||||
colSpanData[index] = th.colSpan;
|
||||
if (index === 0) colSpanSum[index] = th.colSpan;
|
||||
else colSpanSum[index] = colSpanSum[index - 1] + th.colSpan;
|
||||
});
|
||||
}
|
||||
|
||||
function getTableData(tableProperties) {
|
||||
const {
|
||||
tableRows,
|
||||
columnData,
|
||||
isFileSize,
|
||||
isDataAttribute,
|
||||
colSpanData,
|
||||
colSpanSum,
|
||||
} = tableProperties;
|
||||
for (let [i, tr] of tableRows.entries()) {
|
||||
let tdTextContent = tr
|
||||
.querySelectorAll("td")
|
||||
.item(
|
||||
colSpanData[columnIndex] === 1
|
||||
? colSpanSum[columnIndex] - 1
|
||||
: colSpanSum[columnIndex] - colSpanData[columnIndex]
|
||||
).textContent;
|
||||
if (tdTextContent.length === 0) {
|
||||
tdTextContent = "";
|
||||
}
|
||||
if (tdTextContent.trim() !== "") {
|
||||
if (isFileSize) {
|
||||
fileSizeColumnTextAndRow[columnData[i]] = tr.innerHTML;
|
||||
}
|
||||
if (!isFileSize && !isDataAttribute) {
|
||||
columnData.push(`${tdTextContent}#${i}`);
|
||||
columnIndexAndTableRow[`${tdTextContent}#${i}`] = tr.innerHTML;
|
||||
}
|
||||
} else {
|
||||
// Fill in blank table cells dict key with filler value.
|
||||
columnData.push(`${fillValue}#${i}`);
|
||||
columnIndexAndTableRow[`${fillValue}#${i}`] = tr.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
const isPunctSort = th.classList.contains("punct-sort");
|
||||
const isAlphaSort = th.classList.contains("alpha-sort");
|
||||
function sortAscending(a, b) {
|
||||
if (a.includes(`${fillValue}#`)) {
|
||||
return 1;
|
||||
} else if (b.includes(`${fillValue}#`)) {
|
||||
return -1;
|
||||
} else {
|
||||
return a.localeCompare(
|
||||
b,
|
||||
navigator.languages[0] || navigator.language,
|
||||
{ numeric: !isAlphaSort, ignorePunctuation: !isPunctSort }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function sortDescending(a, b) {
|
||||
return sortAscending(b, a);
|
||||
}
|
||||
|
||||
function clearArrows(arrowUp = "▲", arrowDown = "▼") {
|
||||
th.innerHTML = th.innerHTML.replace(arrowUp, "");
|
||||
th.innerHTML = th.innerHTML.replace(arrowDown, "");
|
||||
}
|
||||
|
||||
if (columnData[0] === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
function changeTableArrow(arrowDirection) {
|
||||
if (tableArrows) {
|
||||
clearArrows(arrowUp, arrowDown);
|
||||
th.insertAdjacentText("beforeend", arrowDirection);
|
||||
}
|
||||
}
|
||||
|
||||
function sortColumn(sortDirection) {
|
||||
columnData.sort(sortDirection, {
|
||||
numeric: !isAlphaSort,
|
||||
ignorePunctuation: !isPunctSort,
|
||||
});
|
||||
}
|
||||
|
||||
if (timesClickedColumn === 1) {
|
||||
if (desc) {
|
||||
changeTableArrow(arrowDown);
|
||||
sortColumn(sortDescending);
|
||||
} else {
|
||||
changeTableArrow(arrowUp);
|
||||
sortColumn(sortAscending);
|
||||
}
|
||||
} else if (timesClickedColumn === 2) {
|
||||
timesClickedColumn = 0;
|
||||
if (desc) {
|
||||
changeTableArrow(arrowUp);
|
||||
sortColumn(sortAscending);
|
||||
} else {
|
||||
changeTableArrow(arrowDown);
|
||||
sortColumn(sortDescending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateTable(tableProperties) {
|
||||
const { tableRows, columnData, isFileSize } = tableProperties;
|
||||
for (let [i, tr] of tableRows.entries()) {
|
||||
if (isFileSize) {
|
||||
tr.innerHTML = fileSizeColumnTextAndRow[columnData[i]];
|
||||
let fileSizeInBytesHTML = tr
|
||||
.querySelectorAll("td")
|
||||
.item(columnIndex).innerHTML;
|
||||
const fileSizeInBytesText = tr
|
||||
.querySelectorAll("td")
|
||||
.item(columnIndex).textContent;
|
||||
const fileSizes = {
|
||||
Kibibyte: 1024,
|
||||
Mebibyte: 1.049e6,
|
||||
Gibibyte: 1.074e9,
|
||||
Tebibyte: 1.1e12,
|
||||
Pebibyte: 1.126e15,
|
||||
};
|
||||
// Remove the unique identifyer for duplicate values(#number).
|
||||
columnData[i] = columnData[i].replace(/#[0-9]*/, "");
|
||||
const fileSize = columnData[i];
|
||||
if (fileSize < fileSizes.Kibibyte) {
|
||||
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
||||
fileSizeInBytesText,
|
||||
`${parseFloat(fileSize).toFixed(2)} B`
|
||||
);
|
||||
} else if (
|
||||
fileSize >= fileSizes.Kibibyte &&
|
||||
fileSize < fileSizes.Mebibyte
|
||||
) {
|
||||
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
||||
fileSizeInBytesText,
|
||||
`${(fileSize / fileSizes.Kibibyte).toFixed(2)} KiB`
|
||||
);
|
||||
} else if (
|
||||
fileSize >= fileSizes.Mebibyte &&
|
||||
fileSize < fileSizes.Gibibyte
|
||||
) {
|
||||
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
||||
fileSizeInBytesText,
|
||||
`${(fileSize / fileSizes.Mebibyte).toFixed(2)} MiB`
|
||||
);
|
||||
} else if (
|
||||
fileSize >= fileSizes.Gibibyte &&
|
||||
fileSize < fileSizes.Tebibyte
|
||||
) {
|
||||
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
||||
fileSizeInBytesText,
|
||||
`${(fileSize / fileSizes.Gibibyte).toFixed(2)} GiB`
|
||||
);
|
||||
} else if (
|
||||
fileSize >= fileSizes.Tebibyte &&
|
||||
fileSize < fileSizes.Pebibyte
|
||||
) {
|
||||
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
||||
fileSizeInBytesText,
|
||||
`${(fileSize / fileSizes.Tebibyte).toFixed(2)} TiB`
|
||||
);
|
||||
} else {
|
||||
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
||||
fileSizeInBytesText,
|
||||
"NaN"
|
||||
);
|
||||
}
|
||||
tr.querySelectorAll("td").item(columnIndex).innerHTML =
|
||||
fileSizeInBytesHTML;
|
||||
} else if (!isFileSize) {
|
||||
tr.innerHTML = columnIndexAndTableRow[columnData[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
th.addEventListener("click", function () {
|
||||
const [columnData, colSpanData, colSpanSum] = [[], {}, {}];
|
||||
|
||||
const visibleTableRows = Array.prototype.filter.call(
|
||||
tableBody.querySelectorAll("tr"),
|
||||
(tr) => {
|
||||
return tr.style.display !== "none";
|
||||
}
|
||||
);
|
||||
|
||||
const isDataAttribute = th.classList.contains("data-sort");
|
||||
if (isDataAttribute) {
|
||||
sortDataAttributes(visibleTableRows, columnData);
|
||||
}
|
||||
|
||||
const isFileSize = th.classList.contains("file-size-sort");
|
||||
if (isFileSize) {
|
||||
sortFileSize(visibleTableRows, columnData);
|
||||
}
|
||||
|
||||
const isRememberSort = sortableTable.classList.contains("remember-sort");
|
||||
if (!isRememberSort) {
|
||||
rememberSort(timesClickedColumn, columnIndexesClicked);
|
||||
}
|
||||
|
||||
timesClickedColumn += 1;
|
||||
|
||||
getColSpanData(sortableTable, colSpanData, colSpanSum);
|
||||
const tableProperties = {
|
||||
tableRows: visibleTableRows,
|
||||
columnData,
|
||||
isFileSize,
|
||||
isDataAttribute,
|
||||
colSpanData,
|
||||
colSpanSum,
|
||||
};
|
||||
getTableData(tableProperties);
|
||||
updateTable(tableProperties);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
document.readyState === "complete" ||
|
||||
document.readyState === "interactive"
|
||||
) {
|
||||
tableSortJs();
|
||||
} else if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", tableSortJs, false);
|
||||
}
|
||||
if (typeof module == "object") {
|
||||
module.exports = tableSortJs;
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
Loading…
Reference in New Issue
Block a user