« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/static
diff options
context:
space:
mode:
Diffstat (limited to 'src/static')
-rw-r--r--src/static/client3.js (renamed from src/static/client2.js)275
-rw-r--r--src/static/site5.css10
2 files changed, 158 insertions, 127 deletions
diff --git a/src/static/client2.js b/src/static/client3.js
index 0ec052bd..8372a268 100644
--- a/src/static/client2.js
+++ b/src/static/client3.js
@@ -7,16 +7,7 @@
 
 import {getColors} from '../util/colors.js';
 import {empty, stitchArrays} from '../util/sugar.js';
-
-import {
-  filterMultipleArrays,
-  getArtistNumContributions,
-} from '../util/wiki-data.js';
-
-let albumData, artistData;
-let officialAlbumData, fandomAlbumData, beyondAlbumData;
-
-let ready = false;
+import {filterMultipleArrays} from '../util/wiki-data.js';
 
 const clientInfo = window.hsmusicClientInfo = Object.create(null);
 
@@ -76,15 +67,6 @@ function cssProp(el, key) {
   return getComputedStyle(el).getPropertyValue(key).trim();
 }
 
-function getRefDirectory(ref) {
-  return ref.split(':')[1];
-}
-
-function getAlbum(el) {
-  const directory = cssProp(el, '--album-directory');
-  return albumData.find((album) => album.directory === directory);
-}
-
 // TODO: These should pro8a8ly access some shared urlSpec path. We'd need to
 // separ8te the tooling around that into common-shared code too.
 const getLinkHref = (type, directory) => rebase(`${type}/${directory}`);
@@ -108,6 +90,13 @@ const scriptedLinkInfo = clientInfo.scriptedLinkInfo = {
   nextLink: null,
   previousLink: null,
   randomLink: null,
+
+  state: {
+    albumDirectories: null,
+    albumTrackDirectories: null,
+    artistDirectories: null,
+    artistNumContributions: null,
+  },
 };
 
 function getScriptedLinkReferences() {
@@ -129,109 +118,130 @@ function getScriptedLinkReferences() {
 
 function addRandomLinkListeners() {
   for (const a of scriptedLinkInfo.randomLinks ?? []) {
-    a.addEventListener('click', evt => {
-      if (!ready) {
-        evt.preventDefault();
-        return;
-      }
+    a.addEventListener('click', domEvent => {
+      handleRandomLinkClicked(a, domEvent);
+    });
+  }
+}
 
-      const tracks = albumData =>
-        albumData
-          .map(album => album.tracks)
-          .reduce((acc, tracks) => acc.concat(tracks), []);
+function handleRandomLinkClicked(a, domEvent) {
+  const href = determineRandomLinkHref(a);
 
-      setTimeout(() => {
-        a.href = rebase('js-disabled');
-      });
+  if (!href) {
+    domEvent.preventDefault();
+    return;
+  }
 
-      switch (a.dataset.random) {
-        case 'album':
-          a.href = openAlbum(pick(albumData).directory);
-          break;
+  setTimeout(() => {
+    a.href = '#'
+  });
 
-        case 'track':
-          a.href = openTrack(getRefDirectory(pick(tracks(albumData))));
-          break;
+  a.href = href;
+}
 
-        case 'album-in-group-dl': {
-          const albumLinks =
-            Array.from(a
-              .closest('dt')
-              .nextElementSibling
-              .querySelectorAll('li a'))
+function determineRandomLinkHref(a) {
+  const {state} = scriptedLinkInfo;
 
-          const albumDirectories =
-            albumLinks.map(a =>
-              getComputedStyle(a).getPropertyValue('--album-directory'));
+  const trackDirectoriesFromAlbumDirectories = albumDirectories =>
+    albumDirectories
+      .map(directory => state.albumDirectories.indexOf(directory))
+      .map(index => state.albumTrackDirectories[index])
+      .reduce((acc, trackDirectories) => acc.concat(trackDirectories, []));
 
-          a.href = openAlbum(pick(albumDirectories));
-          break;
-        }
+  switch (a.dataset.random) {
+    case 'album': {
+      const {albumDirectories} = state;
+      if (!albumDirectories) return null;
+
+      return openAlbum(pick(albumDirectories));
+    }
 
-        case 'track-in-group-dl': {
-          const albumLinks =
-            Array.from(a
-              .closest('dt')
-              .nextElementSibling
-              .querySelectorAll('li a'))
+    case 'track': {
+      const {albumDirectories} = state;
+      if (!albumDirectories) return null;
 
-          const albumDirectories =
-            albumLinks.map(a =>
-              getComputedStyle(a).getPropertyValue('--album-directory'));
+      const trackDirectories =
+        trackDirectoriesFromAlbumDirectories(
+          albumDirectories);
 
-          const filteredAlbumData =
-            albumData.filter(album =>
-              albumDirectories.includes(album.directory));
+      return openTrack(pick(trackDirectories));
+    }
 
-          a.href = openTrack(getRefDirectory(pick(tracks(filteredAlbumData))));
-          break;
-        }
+    case 'album-in-group-dl': {
+      const albumLinks =
+        Array.from(a
+          .closest('dt')
+          .nextElementSibling
+          .querySelectorAll('li a'))
 
-        /* Legacy links, for old versions             *
-         * of generateListRandomPageLinksGroupSection */
+      const listAlbumDirectories =
+        albumLinks
+          .map(a => cssProp(a, '--album-directory'));
 
-        case 'album-in-official':
-          a.href = openAlbum(pick(officialAlbumData).directory);
-          break;
+      return openAlbum(pick(listAlbumDirectories));
+    }
 
-        case 'album-in-fandom':
-          a.href = openAlbum(pick(fandomAlbumData).directory);
-          break;
+    case 'track-in-group-dl': {
+      const {albumDirectories} = state;
+      if (!albumDirectories) return null;
 
-        case 'album-in-beyond':
-          a.href = openAlbum(pick(beyondAlbumData).directory);
-          break;
+      const albumLinks =
+        Array.from(a
+          .closest('dt')
+          .nextElementSibling
+          .querySelectorAll('li a'))
 
-        /* End legacy links */
+      const listAlbumDirectories =
+        albumLinks
+          .map(a => cssProp(a, '--album-directory'));
 
-        case 'track-in-album':
-          a.href = openTrack(getRefDirectory(pick(getAlbum(a).tracks)));
-          break;
+      const trackDirectories =
+        trackDirectoriesFromAlbumDirectories(
+          listAlbumDirectories);
 
-        case 'track-in-official':
-          a.href = openTrack(getRefDirectory(pick(tracks(officialAlbumData))));
-          break;
+      return openTrack(pick(trackDirectories));
+    }
 
-        case 'track-in-fandom':
-          a.href = openTrack(getRefDirectory(pick(tracks(fandomAlbumData))));
-          break;
+    case 'track-in-sidebar': {
+      // Note that the container for track links may be <ol> or <ul>, and
+      // they can't be identified by href, since links from one track to
+      // another don't include "track" in the href.
+      const trackLinks =
+        Array.from(document
+          .querySelector('.track-list-sidebar-box')
+          .querySelectorAll('li a'));
 
-        case 'track-in-beyond':
-          a.href = openTrack(getRefDirectory(pick(tracks(beyondAlbumData))));
-          break;
+      return pick(trackLinks).href;
+    }
 
-        case 'artist':
-          a.href = openArtist(pick(artistData).directory);
-          break;
+    case 'track-in-album': {
+      const {albumDirectories, albumTrackDirectories} = state;
+      if (!albumDirectories || !albumTrackDirectories) return null;
 
-        case 'artist-more-than-one-contrib':
-          a.href =
-            openArtist(
-              pick(artistData.filter((artist) => getArtistNumContributions(artist) > 1))
-                .directory);
-          break;
-      }
-    });
+      const albumDirectory = cssProp(a, '--album-directory');
+      const albumIndex = albumDirectories.indexOf(albumDirectory);
+      const trackDirectories = albumTrackDirectories[albumIndex];
+
+      return openTrack(pick(trackDirectories));
+    }
+
+    case 'artist': {
+      const {artistDirectories} = state;
+      if (!artistDirectories) return null;
+
+      return openArtist(pick(artistDirectories));
+    }
+
+    case 'artist-more-than-one-contrib': {
+      const {artistDirectories, artistNumContributions} = state;
+      if (!artistDirectories || !artistNumContributions) return null;
+
+      const filteredArtistDirectories =
+        artistDirectories
+          .filter((_artist, index) => artistNumContributions[index] > 1);
+
+      return openArtist(pick(filteredArtistDirectories));
+    }
   }
 }
 
@@ -255,9 +265,7 @@ function addNavigationKeyPressListeners() {
       } else if (event.charCode === 'P'.charCodeAt(0)) {
         scriptedLinkInfo.previousNavLink?.click();
       } else if (event.charCode === 'R'.charCodeAt(0)) {
-        if (ready) {
-          scriptedLinkInfo.randomNavLink?.click();
-        }
+        scriptedLinkInfo.randomNavLink?.click();
       }
     }
   });
@@ -282,31 +290,44 @@ clientSteps.addPageListeners.push(addNavigationKeyPressListeners);
 clientSteps.addPageListeners.push(addRevealLinkClickListeners);
 clientSteps.mutatePageContent.push(mutateNavigationLinkContent);
 
-const elements1 = document.getElementsByClassName('js-hide-once-data');
-const elements2 = document.getElementsByClassName('js-show-once-data');
-
-for (const element of elements1) element.style.display = 'block';
-
-fetch(rebase('data.json', 'rebaseShared'))
-  .then((data) => data.json())
-  .then((data) => {
-    albumData = data.albumData;
-    artistData = data.artistData;
-
-    const albumsInGroup = directory =>
-      albumData
-        .filter(album =>
-          album.groups.includes(`group:${directory}`));
-
-    officialAlbumData = albumsInGroup('official');
-    fandomAlbumData = albumsInGroup('fandom');
-    beyondAlbumData = albumsInGroup('beyond');
-
-    for (const element of elements1) element.style.display = 'none';
-    for (const element of elements2) element.style.display = 'block';
+if (
+  document.documentElement.dataset.urlKey === 'localized.listing' &&
+  document.documentElement.dataset.urlValue0 === 'random'
+) {
+  const dataLoadingLine = document.getElementById('data-loading-line');
+  const dataLoadedLine = document.getElementById('data-loaded-line');
+  const dataErrorLine = document.getElementById('data-error-line');
+
+  dataLoadingLine.style.display = 'block';
+
+  fetch(rebase('random-link-data.json', 'rebaseShared'))
+    .then(data => data.json())
+    .then(data => {
+      const {state} = scriptedLinkInfo;
+
+      Object.assign(state, {
+        albumDirectories: data.albumDirectories,
+        albumTrackDirectories: data.albumTrackDirectories,
+        artistDirectories: data.artistDirectories,
+        artistNumContributions: data.artistNumContributions,
+      });
 
-    ready = true;
-  });
+      dataLoadingLine.style.display = 'none';
+      dataLoadedLine.style.display = 'block';
+    }, () => {
+      dataLoadingLine.style.display = 'none';
+      dataErrorLine.style.display = 'block';
+    })
+    .then(() => {
+      const {randomLinks} = scriptedLinkInfo;
+      for (const a of randomLinks) {
+        const href = determineRandomLinkHref(a);
+        if (!href) {
+          a.removeAttribute('href');
+        }
+      }
+    });
+}
 
 // Data & info card ---------------------------------------
 
diff --git a/src/static/site5.css b/src/static/site5.css
index 1ffe5044..ba44ec37 100644
--- a/src/static/site5.css
+++ b/src/static/site5.css
@@ -803,6 +803,16 @@ html[data-url-key="localized.albumCommentary"] li.no-commentary {
   opacity: 0.7;
 }
 
+html[data-url-key="localized.listing"][data-url-value0="random"] #data-loading-line,
+html[data-url-key="localized.listing"][data-url-value0="random"] #data-loaded-line,
+html[data-url-key="localized.listing"][data-url-value0="random"] #data-error-line {
+  display: none;
+}
+
+html[data-url-key="localized.listing"][data-url-value0="random"] #content a:not([href]) {
+  opacity: 0.7;
+}
+
 /* Images */
 
 .image-container {