summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--templates/stations.html397
1 files changed, 396 insertions, 1 deletions
diff --git a/templates/stations.html b/templates/stations.html
index b26aa94..36b9b98 100644
--- a/templates/stations.html
+++ b/templates/stations.html
@@ -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 %}