diff --git a/output/js/constants.js b/output/js/constants.js index 8fe3d67..23bc0d1 100644 --- a/output/js/constants.js +++ b/output/js/constants.js @@ -14,7 +14,7 @@ export const dom = { export const COLUMN = { IDENTIFIER: 0, LANGUAGE: 1, NAME: 2, DESCRIPTION: 3, USERS: 4, PREVIEW: 5, - QR_CODE: 6, JOIN_URL: 7 + QR_CODE: 6, SERVER_ICON: 7, JOIN_URL: 8 }; // Reverse enum. @@ -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,20 +41,33 @@ export function columnAscendingByDefault(column) { return column != COLUMN.USERS; } -export function columnIsSortable(column) { return column != COLUMN.QR_CODE; } - -export function columnNeedsCasefold(column) { - return [ - COLUMN.IDENTIFIER, - COLUMN.NAME, - COLUMN.DESCRIPTION +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 columnIsNumeric(column) { - return [ - COLUMN.USERS - ].includes(column); +/** + * @type {Record any>} + */ +const TRANSFORMATION = { + numeric: (el) => parseInt(el.innerText), + casefold: (el) => el.innerText.toLowerCase().trim(), + tokenData: (el) => el.getAttribute("data-token") +} + +/** + * @type {Dictionary any>} + */ +export const COLUMN_TRANSFORMATION = { + [COLUMN.USERS]: TRANSFORMATION.numeric, + [COLUMN.IDENTIFIER]: TRANSFORMATION.casefold, + [COLUMN.NAME]: TRANSFORMATION.casefold, + [COLUMN.DESCRIPTION]: TRANSFORMATION.casefold, + [COLUMN.SERVER_ICON]: TRANSFORMATION.tokenData } /** @@ -64,22 +77,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 8865a5a..0a0eb54 100644 --- a/output/main.js +++ b/output/main.js @@ -16,8 +16,7 @@ // Import magic numbers and data import { dom, COLUMN, COLUMN_LITERAL, COMPARISON, ATTRIBUTES, - columnAscendingByDefault, columnIsSortable, columnNeedsCasefold, - columnIsNumeric, element + columnAscendingByDefault, columnIsSortable, COLUMN_TRANSFORMATION, element } from './js/constants.js'; // Hidden communities for transparency. @@ -192,21 +191,12 @@ function makeRowComparer(column, ascending) { } // Callback to obtain sortable content from cell text. - let contentToSortable = (text) => text.trim(); - - if (columnNeedsCasefold(column)) { - // Make certain columns sort regardless of casing. - contentToSortable = (text) => text.toLowerCase().trim(); - } - else if (columnIsNumeric(column)) { - // Make certain columns sort on parsed numeric value instead of text. - contentToSortable = (text) => parseInt(text); - } + const columnToSortable = COLUMN_TRANSFORMATION[column] ?? ((el) => el.innerText.trim()); // Construct comparer using derived property to determine sort order. const rowComparer = compareProp( ascending ? compareAscending : compareDescending, - row => contentToSortable(row.children[column].innerText) + row => columnToSortable(row.children[column]) ); return rowComparer; @@ -248,17 +238,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