From 9c946df709fbeca15bc6e76435cbe30269a2bd3a Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 10 Jun 2026 07:02:20 -0300 Subject: client, content, css: simple group contributions table filter --- src/static/css/features.css | 37 +++++++ src/static/js/client-util.js | 8 +- src/static/js/client/group-contributions-table.js | 123 ++++++++++++++++++++++ src/static/js/client/index.js | 2 + 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/static/js/client/group-contributions-table.js (limited to 'src/static') diff --git a/src/static/css/features.css b/src/static/css/features.css index 2d54fe7a..f0bd1425 100644 --- a/src/static/css/features.css +++ b/src/static/css/features.css @@ -1260,12 +1260,49 @@ padding-right: 1.5ch; } + th:nth-child(1) { text-align: left; } td.group { padding-left: 3ch; } td.count { text-align: center; } td.duration { text-align: right; } } } +@layer interaction { + .group-contributions-table { + .group a { + position: relative; + text-decoration: underline; + text-decoration-style: dotted; + } + } + + .group-contributions-table:has(.group a.selected) { + tr:has(.group a:not(.selected)) { + td { opacity: 0.65; } + td.group { opacity: 0.8; } + } + + .group a.selected { + text-decoration-style: solid; + } + + .group a.selected::before { + content: ""; + + position: absolute; + display: inline-block; + top: 50%; transform: translateY(-50%); + left: -1.75ch; + + width: 0.4em; + height: 0.4em; + border-radius: 100000cm; + + background: var(--primary-color); + } + } +} + /* Image and media containers */ @layer layout { diff --git a/src/static/js/client-util.js b/src/static/js/client-util.js index de54945c..8ad31b90 100644 --- a/src/static/js/client-util.js +++ b/src/static/js/client-util.js @@ -16,9 +16,15 @@ export function rebase(href, rebaseKey = 'rebaseLocalized') { export function cssProp(el, ...args) { if (typeof args[0] === 'string' && args.length === 1) { - return getComputedStyle(el).getPropertyValue(args[0]).trim(); + if (el) { + return getComputedStyle(el).getPropertyValue(args[0]).trim(); + } else { + return ''; + } } + if (!el) return; + if (typeof args[0] === 'string' && args.length === 2) { if (args[1] === null) { el.style.removeProperty(args[0]); diff --git a/src/static/js/client/group-contributions-table.js b/src/static/js/client/group-contributions-table.js new file mode 100644 index 00000000..3b79f84d --- /dev/null +++ b/src/static/js/client/group-contributions-table.js @@ -0,0 +1,123 @@ +import {cssProp} from '../client-util.js'; +import {stitchArrays} from '../../shared-util/sugar.js'; + +export const info = { + id: 'groupContributionsInfo', + + tables: null, + lists: null, + + groupLinks: null, + groupLinkDirectories: null, + + chunkDTs: null, + chunkDDs: null, + chunkGroupDirectories: null, +}; + +export function getPageReferences() { + if (document.documentElement.dataset.urlKey !== 'localized.artist') { + return; + } + + info.tables = + Array.from(document.querySelectorAll('.group-contributions-table')); + + info.lists = + info.tables + .map(table => table.closest('dl')); + + info.groupLinks = + info.tables + .map(table => Array.from(table.querySelectorAll('td.group a'))); + + info.groupLinkDirectories = + info.groupLinks + .map(links => links + .map(link => link.dataset.directory)); + + info.chunkDTs = + info.lists + .map(list => Array.from(list.querySelectorAll('dt'))); + + info.chunkDDs = + info.chunkDTs + .map(dts => dts + .map(dt => dt.nextElementSibling) + .map(el => el.tagName === 'DD' ? el : null)); + + info.chunkGroupDirectories = + info.chunkDTs + .map(dts => dts + .map(dt => dt.dataset.groups) + .map(string => string ? string.split(' ') : [])); +} + +export function addPageListeners() { + if (!info.tables) return; + + stitchArrays({ + table: info.tables, + groupLinks: info.groupLinks, + }).forEach(({table, groupLinks}) => { + groupLinks.forEach(groupLink => { + groupLink.addEventListener('click', domEvent => { + domEvent.preventDefault(); + handleGroupLinkClicked(table, groupLink); + }); + }); + }); +} + +function handleGroupLinkClicked(table, groupLink) { + const i = info.tables.indexOf(table); + + groupLink.classList.toggle('selected'); + + // For now, just disable having more than one link selected at a time. + for (const link of info.groupLinks[i]) { + if (link !== groupLink) { + link.classList.remove('selected'); + } + } + + updateVisibleChunks(table); +} + +function updateVisibleChunks(table) { + const i = info.tables.indexOf(table); + + const selectedGroupDirectories = + stitchArrays({ + link: info.groupLinks[i], + directory: info.groupLinkDirectories[i], + }).filter(({link}) => link.classList.contains('selected')) + .map(({directory}) => directory); + + stitchArrays({ + chunkDT: info.chunkDTs[i], + chunkDD: info.chunkDDs[i], + chunkGroupDirectories: info.chunkGroupDirectories[i], + }).forEach(({ + chunkDT, + chunkDD, + chunkGroupDirectories, + }) => { + if (selectedGroupDirectories.length >= 1) { + const included = + chunkGroupDirectories + .some(d => selectedGroupDirectories.includes(d)); + + if (included) { + cssProp(chunkDT, 'display', null); + cssProp(chunkDD, 'display', null); + } else { + cssProp(chunkDT, 'display', 'none'); + cssProp(chunkDD, 'display', 'none'); + } + } else { + cssProp(chunkDT, 'display', null); + cssProp(chunkDD, 'display', null); + } + }); +} diff --git a/src/static/js/client/index.js b/src/static/js/client/index.js index a17f7dab..a438d6d8 100644 --- a/src/static/js/client/index.js +++ b/src/static/js/client/index.js @@ -8,6 +8,7 @@ import * as datetimestampTooltipModule from './datetimestamp-tooltip.js'; import * as draggedLinkModule from './dragged-link.js'; import * as expandableGridSectionModule from './expandable-grid-section.js'; import * as galleryStyleSelectorModule from './gallery-style-selector.js'; +import * as groupContributionsTableModule from './group-contributions-table.js'; import * as hashLinkModule from './hash-link.js'; import * as hoverableTooltipModule from './hoverable-tooltip.js'; import * as imageOverlayModule from './image-overlay.js'; @@ -33,6 +34,7 @@ export const modules = [ draggedLinkModule, expandableGridSectionModule, galleryStyleSelectorModule, + groupContributionsTableModule, hashLinkModule, hoverableTooltipModule, imageOverlayModule, -- cgit 1.3.0-6-gf8a5