2
0
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:
Expo on server 2023-11-08 13:05:57 +00:00
parent 51cf09ece7
commit 29e16b66b7

View File

@ -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 %}