Merge pull request 'Add table sort indicators & layout tweaks' (#18) from gravel/sessioncommunities.online:table-sort-indicators into main

Reviewed-on: SomeGuy/sessioncommunities.online#18

You're right, #20 is probably the way to go.
PR accepted.
dev
SomeGuy 2 years ago
commit 78ee1e89eb

@ -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)
}
});

@ -248,17 +248,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 <noscript> styles otherwise.
function markSortableColumns() {
const table = dom.tbl_communities();
for (const th of table.querySelectorAll('th')) {
if (th.id.includes("qr_code")) continue;
th.classList.add('sortable');
const header_cells = table.querySelectorAll('th');
for (let colno = 0; colno < header_cells.length; colno++) {
if (!columnIsSortable(colno)) continue;
header_cells[colno].classList.add('sortable');
}
}

@ -32,7 +32,48 @@ header {
flex-grow: 1;
}
#tbl_communities { width:100%; }
#tbl_communities {
/* Browser defaults. */
--cell-padding-h: 1px;
--cell-padding-v: 1px;
width:100%;
}
#tbl_communities th {
white-space: nowrap;
}
#tbl_communities :is(th, td) {
padding: var(--cell-padding-v) var(--cell-padding-h);
}
#tbl_communities th.sortable {
position: relative;
padding-right: calc( 1.5em + var(--cell-padding-h) );
}
#tbl_communities th.sortable::after {
position: absolute;
right: 0.25em;
top: 50%;
transform: translateY(-50%);
/* content: "\25C7"; */ /* White diamond */
/* content: "\2195"; */ /* Up-down arrow */
/* content: "\25A1"; */ /* White square */
/* content: "\25B8"; */ /* Small right pointing triangle */
content: "\2B25"; /* Black medium diamond */
color: grey;
}
#tbl_communities[data-sort-asc=true] th[data-sort=true]::after {
content: "\25B2"; /* Black up pointing triangle */
color: initial;
}
#tbl_communities[data-sort-asc=false] th[data-sort=true]::after {
content: "\25BC"; /* Black up pointing triangle */
color: initial;
}
#toggle-show-room-ids:not(:checked)
~ #tbl_communities :is(#th_identifier, .td_identifier) {
@ -43,6 +84,10 @@ header {
font-family: monospace;
}
.td_language {
text-align: center;
font-size: 1.25em;
}
.td_language:empty::after {
content: "\2753";
}
@ -84,7 +129,7 @@ header {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
justify-content: space-around;
}
.copy_button { font-size: inherit }
@ -232,3 +277,4 @@ label[for=toggle-show-room-ids]::after {
to {bottom: 0; opacity: 0;}
}

@ -3,14 +3,15 @@
// Once handlers are attached in JS, this check ceases to be useful.
function column_sortable($id) {
return $id != "qr";
// Join URL contents are not guaranteed to have visible text.
return $id != "qr" && $id != "preview" && $id != "join_url";
}
function sort_onclick($colno) {
global $TABLE_COLUMNS;
$column = $TABLE_COLUMNS[$colno];
if (!column_sortable($column['id'])) return "";
return " onclick='sortTable($colno)'";
return " onclick='sortTable($colno)' title='Click to sort this column'";
}
$TABLE_COLUMNS = [

Loading…
Cancel
Save