From d3878aa55352a921db75aeb26d21591d939f6558 Mon Sep 17 00:00:00 2001 From: gravel Date: Fri, 27 Jan 2023 15:11:51 +0100 Subject: [PATCH] Add table sort indicators --- output/js/constants.js | 39 ++++++++++++--------- output/main.js | 29 +++++++++------- output/styles2.css | 50 +++++++++++++++++++++++++-- sites/+components/tbl_communities.php | 5 +-- 4 files changed, 91 insertions(+), 32 deletions(-) diff --git a/output/js/constants.js b/output/js/constants.js index 3002622..071f42d 100644 --- a/output/js/constants.js +++ b/output/js/constants.js @@ -33,7 +33,7 @@ export const ATTRIBUTES = { ACTIVE: 'data-sort', ASCENDING: 'data-sort-asc', COLUMN: 'data-sorted-by', - COLUMN_LITERAL: 'sorted-by' + // COLUMN_LITERAL: 'sorted-by' } }; @@ -41,7 +41,14 @@ export function columnAscendingByDefault(column) { return column != COLUMN.USERS; } -export function columnIsSortable(column) { return column != COLUMN.QR_CODE; } +export function columnIsSortable(column) { + return ![ + COLUMN.QR_CODE, + COLUMN.PREVIEW, + // Join URL contents are not guaranteed to have visible text. + COLUMN.JOIN_URL + ].includes(column); +} export function columnNeedsCasefold(column) { return [ @@ -64,22 +71,22 @@ export function columnIsNumeric(column) { * @returns {HTMLElement} */ function createElement(tag, ...args) { - const element = document.createElement(tag); - if (args.length === 0) return element; - const propsCandidate = args[0]; - if (typeof propsCandidate !== "string" && !(propsCandidate instanceof Element)) { - // args[0] is not child element or text node - // must be props object - Object.assign(element, propsCandidate); - args.shift(); - } - element.append(...args); - return element; + const element = document.createElement(tag); + if (args.length === 0) return element; + const propsCandidate = args[0]; + if (typeof propsCandidate !== "string" && !(propsCandidate instanceof Element)) { + // args[0] is not child element or text node + // must be props object + Object.assign(element, propsCandidate); + args.shift(); + } + element.append(...args); + return element; } export const element = new Proxy({}, { - get(_, key) { - return (...args) => createElement(key, ...args) - } + get(_, key) { + return (...args) => createElement(key, ...args) + } }); diff --git a/output/main.js b/output/main.js index 0bc0bdb..2aba288 100644 --- a/output/main.js +++ b/output/main.js @@ -51,11 +51,11 @@ const filteredCommunities = { // This can be achieved with `text-overflow: ellipsis` instead // and generated entirely server-side. const transformJoinURL = (join_link) => { - return element.button({ - textContent: "Copy", - className: "copy_button", - onclick: () => copyToClipboard(join_link) - }); + return element.button({ + textContent: "Copy", + className: "copy_button", + onclick: () => copyToClipboard(join_link) + }); } function onLoad(timestamp) { @@ -101,7 +101,7 @@ function hideBadCommunities() { * Removes an element by its ID and returns the number of elements removed. */ function hideElementByID(id) { - const element = document.getElementById(id); + const element = document.getElementById(id); element?.remove(); return element ? 1 : 0; } @@ -245,17 +245,22 @@ function setSortState(table, { ascending, column }) { } table.setAttribute(ATTRIBUTES.SORTING.ASCENDING, ascending); table.setAttribute(ATTRIBUTES.SORTING.COLUMN, column); - // This can be used to style column headers in a consistent way, i.e. - // #tbl_communities[data-sort-asc=true][sorted-by=name]::after #th_name, ... - table.setAttribute(ATTRIBUTES.SORTING.COLUMN_LITERAL, COLUMN_LITERAL[column]); + + // No way around this for brief CSS. + const headers = table.querySelectorAll("th"); + headers.forEach((th, colno) => { + th.removeAttribute(ATTRIBUTES.SORTING.ACTIVE); + }); + headers[column].setAttribute(ATTRIBUTES.SORTING.ACTIVE, true); } // This is best done in JS, as it would require