« 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/css/site.css226
-rw-r--r--src/static/js/client/additional-names-box.js6
-rw-r--r--src/static/js/client/css-compatibility-assistant.js26
-rw-r--r--src/static/js/client/hoverable-tooltip.js23
-rw-r--r--src/static/js/client/image-overlay.js5
-rw-r--r--src/static/js/client/sticky-heading.js15
-rw-r--r--src/static/js/rectangles.js42
7 files changed, 261 insertions, 82 deletions
diff --git a/src/static/css/site.css b/src/static/css/site.css
index d3ab28a7..0a7e36ae 100644
--- a/src/static/css/site.css
+++ b/src/static/css/site.css
@@ -583,6 +583,15 @@ summary.underline-white > span:hover a:not(:hover) {
   border-bottom-left-radius: 0;
 }
 
+.track-list-sidebar-box summary {
+  padding-left: 20px !important;
+  text-indent: -15px !important;
+}
+
+.track-list-sidebar-box .track-section-range {
+  white-space: nowrap;
+}
+
 .wiki-search-sidebar-box {
   padding: 1px 0 0 0;
 
@@ -922,7 +931,11 @@ a .normal-content {
 
   background-color: var(--primary-color);
 
-  mask-image: url(/static-4p1/misc/image.svg);
+  /* mask-image is set in content JavaScript,
+   * because we can't identify the correct nor
+   * absolute path to the file from CSS.
+   */
+
   mask-repeat: no-repeat;
   mask-position: calc(100% - 2px);
   vertical-align: text-bottom;
@@ -950,29 +963,46 @@ a .normal-content {
   font-weight: 800;
 }
 
-.nav-links-hierarchical .nav-link:not(:first-child)::before {
+.nav-links-hierarchical .nav-link + .nav-link::before,
+.nav-links-hierarchical .nav-link + .blockwrap .nav-link::before {
   content: "\0020/\0020";
 }
 
-.series-nav-link {
+.series-nav-links {
   display: inline-block;
 }
 
-.series-nav-link:not(:first-child)::before {
+.series-nav-links:not(:first-child)::before {
   content: "\00a0»\00a0";
   font-weight: normal;
 }
 
-.series-nav-link:not(:last-child)::after {
+.series-nav-links:not(:last-child)::after {
   content: ",\00a0";
 }
 
-.series-nav-link + .series-nav-link::before {
+.series-nav-links + .series-nav-links::before {
   content: "";
 }
 
+.dot-switcher > span:not(:first-child) {
+  display: inline-block;
+  white-space: nowrap;
+}
+
+/* Yeah, all this stuff only applies to elements of the dot switcher
+ * besides the first, which will necessarily have a bullet point at left.
+ */
+.dot-switcher *:where(.dot-switcher > span:not(:first-child) > *) {
+  display: inline-block;
+  white-space: wrap;
+  text-align: left;
+  vertical-align: top;
+}
+
 .dot-switcher > span:not(:first-child)::before {
   content: "\0020\00b7\0020";
+  white-space: pre;
   font-weight: 800;
 }
 
@@ -999,7 +1029,7 @@ a .normal-content {
   display: block;
 }
 
-#secondary-nav.album-secondary-nav.with-previous-next {
+#secondary-nav.album-secondary-nav {
   display: flex;
   justify-content: space-around;
   padding-left: 7.5% !important;
@@ -1017,7 +1047,8 @@ a .normal-content {
   margin-right: 5px;
 }
 
-#secondary-nav.album-secondary-nav .dot-switcher {
+#secondary-nav.album-secondary-nav .group-nav-links .dot-switcher,
+#secondary-nav.album-secondary-nav .series-nav-links .dot-switcher {
   white-space: nowrap;
 }
 
@@ -1069,7 +1100,17 @@ a .normal-content {
   text-decoration: none !important;
 }
 
+.text-with-tooltip.wiki-edits > .hoverable {
+  white-space: nowrap;
+}
+
+.isolate-tooltip-z-indexing > * {
+  position: relative;
+  z-index: -1;
+}
+
 .tooltip {
+  font-size: 1rem;
   position: absolute;
   z-index: 3;
   left: -10px;
@@ -1077,7 +1118,12 @@ a .normal-content {
   display: none;
 }
 
-li:not(:first-child:last-child) .tooltip,
+.cover-artwork .tooltip,
+#sidebar .tooltip {
+  font-size: 0.9rem;
+}
+
+li:not(:first-child:last-child) .tooltip:where(:not(.cover-artwork .tooltip)),
 .offset-tooltips > :not(:first-child:last-child) .tooltip {
   left: 14px;
 }
@@ -1119,18 +1165,23 @@ li:not(:first-child:last-child) .tooltip,
 .thing-name-tooltip,
 .wiki-edits-tooltip {
   padding: 3px 4px 2px 2px;
-  left: -6px !important;
+  left: -6px;
 }
 
-.wiki-edits-tooltip {
+.thing-name-tooltip .tooltip-content,
+.wiki-edits-tooltip .tooltip-content {
   font-size: 0.85em;
 }
 
-/* Terrifying?
- * https://stackoverflow.com/a/64424759/4633828
- */
-.thing-name-tooltip { margin-right: -120px; }
-.wiki-edits-tooltip { margin-right: -200px; }
+.thing-name-tooltip .tooltip-content {
+  width: max-content;
+  max-width: 120px;
+}
+
+.wiki-edits-tooltip .tooltip-content {
+  width: max-content;
+  max-width: 200px;
+}
 
 .contribution-tooltip .tooltip-content {
   padding: 6px 2px 2px 2px;
@@ -1366,12 +1417,9 @@ hr.cute,
   border-style: none none dotted none;
 }
 
-#cover-art-container {
+.cover-artwork {
   font-size: 0.8em;
   border: 2px solid var(--primary-color);
-  box-shadow:
-    0 2px 14px -6px var(--primary-color),
-    0 0 12px 12px #00000080;
 
   border-radius: 0 0 4px 4px;
   background: var(--bg-black-color);
@@ -1380,37 +1428,53 @@ hr.cute,
           backdrop-filter: blur(3px);
 }
 
-#cover-art-container:has(.image-details),
-#cover-art-container.has-image-details {
+.cover-artwork:has(.image-details),
+.cover-artwork.has-image-details {
   border-radius: 0 0 6px 6px;
 }
 
-#cover-art-container:not(:has(.image-details)),
-#cover-art-container:not(.has-image-details) {
+.cover-artwork:not(:has(.image-details)),
+.cover-artwork:not(.has-image-details) {
   /* Hacky: `overflow: hidden` hides tag tooltips, so it can't be applied
    * if we've got tags/details visible. But it's okay, because we only
    * need to apply it if it *doesn't* - that's when the rounded border
-   * of #cover-art-container needs to cut off its child image-container
+   * of the .cover-artwork needs to cut off its child .image-container
    * (which has a background that otherwise causes sharp corners).
    */
   overflow: hidden;
 }
 
-#cover-art-container .image-container {
-  /* Border is handled on the cover-art-container. */
+#artwork-column .cover-artwork {
+  box-shadow:
+    0 2px 14px -6px var(--primary-color),
+    0 0 12px 12px #00000080;
+}
+
+#artwork-column .cover-artwork:not(:first-child) {
+  margin-top: 20px;
+  margin-left: 30px;
+  margin-right: 5px;
+}
+
+#artwork-column .cover-artwork:last-child:not(:first-child) {
+  margin-bottom: 25px;
+}
+
+.cover-artwork .image-container {
+  /* Border is handled on the .cover-artwork. */
   border: none;
-  border-radius: 0;
+  border-radius: 0 !important;
 }
 
-#cover-art-container .image-details {
+.cover-artwork .image-details {
   border-top-color: var(--deep-color);
 }
 
-#cover-art-container .image-details + .image-details {
+.cover-artwork .image-details + .image-details {
   border-top-color: var(--primary-color);
 }
 
-#cover-art-container .image {
+.cover-artwork .image {
   display: block;
   width: 100%;
   height: 100%;
@@ -1453,6 +1517,10 @@ hr.cute,
   margin-bottom: 2px;
 }
 
+ul.image-details.art-tag-details {
+  padding-bottom: 0;
+}
+
 ul.image-details.art-tag-details li {
   display: inline-block;
 }
@@ -1461,23 +1529,40 @@ ul.image-details.art-tag-details li:not(:last-child)::after {
   content: " \00b7 ";
 }
 
-.image-details.non-unique-details {
-  font-style: oblique;
-}
-
 p.image-details.illustrator-details {
   text-align: center;
   font-style: oblique;
 }
 
+p.image-details.origin-details {
+  margin-bottom: 2px;
+}
+
+.album-art-info {
+  font-size: 0.8em;
+  border: 2px solid var(--deep-color);
+
+  margin: 10px min(15px, 1vw) 15px;
+
+  background: var(--bg-black-color);
+  padding: 6px;
+  border-radius: 5px;
+
+  -webkit-backdrop-filter: blur(3px);
+          backdrop-filter: blur(3px);
+}
+
+.album-art-info p {
+  margin: 0;
+}
+
+/*
 p.content-heading:has(+ .commentary-entry-heading.dated) {
   clear: right;
 }
+*/
 
 .commentary-entry-heading {
-  display: flex;
-  flex-direction: row;
-
   margin-left: 15px;
   padding-left: 5px;
   max-width: 625px;
@@ -1487,7 +1572,7 @@ p.content-heading:has(+ .commentary-entry-heading.dated) {
 }
 
 .commentary-entry-heading-text {
-  flex-grow: 1;
+  display: block;
   padding-left: 1.25ch;
   text-indent: -1.25ch;
 }
@@ -1496,20 +1581,6 @@ p.content-heading:has(+ .commentary-entry-heading.dated) {
   font-style: oblique;
 }
 
-.commentary-entry-heading .commentary-date {
-  flex-shrink: 0;
-
-  margin-left: 0.75ch;
-  align-self: flex-end;
-
-  padding-left: 0.5ch;
-  padding-right: 0.25ch;
-}
-
-.commentary-entry-heading .hoverable {
-  box-shadow: 1px 2px 6px 5px #04040460;
-}
-
 .commentary-entry-body summary {
   list-style-position: outside;
 }
@@ -1518,6 +1589,19 @@ p.content-heading:has(+ .commentary-entry-heading.dated) {
   color: var(--primary-color);
 }
 
+.commentary-date {
+  float: right;
+  margin-top: -0.8em;
+  margin-left: 0.75ch;
+  padding-left: 0.5ch;
+  padding-right: 0.4em;
+  font-size: 0.9em;
+}
+
+.commentary-date .hoverable {
+  box-shadow: 1px 2px 6px 5px #04040460;
+}
+
 .commentary-art {
   float: right;
   width: 30%;
@@ -1532,6 +1616,20 @@ p.content-heading:has(+ .commentary-entry-heading.dated) {
   box-shadow: 0 0 4px 5px rgba(0, 0, 0, 0.25) !important;
 }
 
+.lyrics-switcher {
+  padding-left: 20px;
+}
+
+.lyrics-switcher > span:not(:first-child)::before {
+  content: "\0020\00b7\0020";
+  font-weight: 800;
+}
+
+.lyrics-entry {
+  padding-left: 40px;
+  max-width: 600px;
+}
+
 .js-hide,
 .js-show-once-data,
 .js-hide-once-data {
@@ -1668,6 +1766,10 @@ ul.quick-info li:not(:last-child)::after {
   margin-top: 25px;
 }
 
+.gallery-set-switcher {
+  text-align: center;
+}
+
 .quick-description:not(.has-external-links-only) {
   --clamped-padding-ratio: max(var(--responsive-padding-ratio), 0.06);
   margin-left: auto;
@@ -1752,7 +1854,7 @@ li .by a {
   display: inline-block;
 }
 
-p code {
+p code, li code {
   font-size: 0.95em;
   font-family: "courier new", monospace;
   font-weight: 800;
@@ -2919,11 +3021,11 @@ h3.content-heading {
   top: 0;
 }
 
-.content-sticky-heading-anchor:not(:matches(.content-sticky-heading-root[inert]) *) {
+.content-sticky-heading-anchor:not(:where(.content-sticky-heading-root[inert]) *) {
   position: relative;
 }
 
-.content-sticky-heading-container:not(:matches(.content-sticky-heading-root[inert]) *) {
+.content-sticky-heading-container:not(:where(.content-sticky-heading-root[inert]) *) {
   position: absolute;
 }
 
@@ -3049,7 +3151,7 @@ main.long-content .content-sticky-heading-container .content-sticky-subheading-r
   transition: transform 0.35s, opacity 0.30s;
 }
 
-.content-sticky-heading-cover .image-container {
+.content-sticky-heading-cover .cover-artwork {
   border-width: 1px;
   border-radius: 1.25px;
   box-shadow: none;
@@ -3380,7 +3482,7 @@ main.long-content .content-sticky-heading-container .content-sticky-subheading-r
   /* Cover art floats to the right. It's positioned in HTML beneath the
    * heading, so pull it up a little to "float" on top.
    */
-  #cover-art-container {
+  #artwork-column {
     float: right;
     width: 40%;
     max-width: 400px;
@@ -3393,18 +3495,18 @@ main.long-content .content-sticky-heading-container .content-sticky-subheading-r
   /* ...Except on top-indexes, where cover art is displayed prominently
    * between the heading and subheading.
    */
-  #content.top-index #cover-art-container {
+  #content.top-index #artwork-column {
     float: none;
     margin: 2em auto 2.5em auto;
     max-width: 375px;
   }
 
-  html[data-url-key="localized.home"] #page-container.showing-sidebar-left .grid-listing > .grid-item:not(:nth-child(n+10)) {
+  html[data-url-key="localized.home"] #page-container.showing-sidebar-left .grid-listing > .grid-item:not(:nth-child(n+7)) {
     flex-basis: 23%;
     margin: 15px;
   }
 
-  html[data-url-key="localized.home"] #page-container.showing-sidebar-left .grid-listing > .grid-item:nth-child(n+10) {
+  html[data-url-key="localized.home"] #page-container.showing-sidebar-left .grid-listing > .grid-item:nth-child(n+7) {
     flex-basis: 18%;
     margin: 10px;
   }
@@ -3500,7 +3602,7 @@ main.long-content .content-sticky-heading-container .content-sticky-subheading-r
     --responsive-padding-ratio: 0.02;
   }
 
-  #cover-art-container {
+  #artwork-column {
     margin: 25px 0 5px 0;
     width: 100%;
     max-width: unset;
diff --git a/src/static/js/client/additional-names-box.js b/src/static/js/client/additional-names-box.js
index 7c1baef6..195ba25d 100644
--- a/src/static/js/client/additional-names-box.js
+++ b/src/static/js/client/additional-names-box.js
@@ -33,7 +33,7 @@ export function getPageReferences() {
       '.content-sticky-heading-container' +
       ' ' +
       'a[href="#additional-names-box"]' +
-      ':not(:matches([inert] *))');
+      ':not(:where([inert] *))');
 
   info.contentContainer =
     document.querySelector('#content');
@@ -119,9 +119,9 @@ function handleAdditionalNamesBoxLinkClicked(domEvent) {
       ? top > 0.7 * window.innerHeight
    : height && !boxFitsInFrame
       ? top > 0.4 * window.innerHeight
-      ? top > 0.5 * window.innerHeight) ||
+      : top > 0.5 * window.innerHeight) ||
 
-    (bottom && bottomFitsInFrame
+    (bottom && boxFitsInFrame
       ? bottom > window.innerHeight - 20
       : false);
 
diff --git a/src/static/js/client/css-compatibility-assistant.js b/src/static/js/client/css-compatibility-assistant.js
index 6e7b15b5..aa637cc4 100644
--- a/src/static/js/client/css-compatibility-assistant.js
+++ b/src/static/js/client/css-compatibility-assistant.js
@@ -1,22 +1,30 @@
 /* eslint-env browser */
 
+import {stitchArrays} from '../../shared-util/sugar.js';
+
 export const info = {
   id: 'cssCompatibilityAssistantInfo',
 
-  coverArtContainer: null,
-  coverArtImageDetails: null,
+  coverArtworks: null,
+  coverArtworkImageDetails: null,
 };
 
 export function getPageReferences() {
-  info.coverArtContainer =
-    document.getElementById('cover-art-container');
+  info.coverArtworks =
+    Array.from(document.querySelectorAll('.cover-artwork'));
 
-  info.coverArtImageDetails =
-    info.coverArtContainer?.querySelector('.image-details');
+  info.coverArtworkImageDetails =
+    info.coverArtworks
+      .map(artwork => artwork.querySelector('.image-details'));
 }
 
 export function mutatePageContent() {
-  if (info.coverArtImageDetails) {
-    info.coverArtContainer.classList.add('has-image-details');
-  }
+  stitchArrays({
+    coverArtwork: info.coverArtworks,
+    imageDetails: info.coverArtworkImageDetails,
+  }).forEach(({coverArtwork, imageDetails}) => {
+      if (imageDetails) {
+        coverArtwork.classList.add('has-image-details');
+      }
+    });
 }
diff --git a/src/static/js/client/hoverable-tooltip.js b/src/static/js/client/hoverable-tooltip.js
index 484f2ab0..9569de3e 100644
--- a/src/static/js/client/hoverable-tooltip.js
+++ b/src/static/js/client/hoverable-tooltip.js
@@ -576,6 +576,17 @@ export function showTooltipFromHoverable(hoverable) {
 
   hoverable.classList.add('has-visible-tooltip');
 
+  const isolator =
+    hoverable.closest('.isolate-tooltip-z-indexing > *');
+
+  if (isolator) {
+    for (const child of isolator.parentElement.children) {
+      cssProp(child, 'z-index', null);
+    }
+
+    cssProp(isolator, 'z-index', '1');
+  }
+
   positionTooltipFromHoverableWithBrains(hoverable);
 
   cssProp(tooltip, 'display', 'block');
@@ -667,12 +678,12 @@ export function positionTooltipFromHoverableWithBrains(hoverable) {
 
     for (let i = 0; i < numBaselineRects; i++) {
       for (const [dir1, dir2] of [
+        ['down', 'right'],
+        ['down', 'left'],
         ['right', 'down'],
         ['left', 'down'],
         ['right', 'up'],
         ['left', 'up'],
-        ['down', 'right'],
-        ['down', 'left'],
         ['up', 'right'],
         ['up', 'left'],
       ]) {
@@ -995,6 +1006,14 @@ export function getTooltipBaselineOpportunityAreas(tooltip) {
   return results;
 }
 
+export function mutatePageContent() {
+  for (const isolatorRoot of document.querySelectorAll('.isolate-tooltip-z-indexing')) {
+    if (isolatorRoot.firstElementChild) {
+      cssProp(isolatorRoot.firstElementChild, 'z-index', '1');
+    }
+  }
+}
+
 export function addPageListeners() {
   const {state} = info;
 
diff --git a/src/static/js/client/image-overlay.js b/src/static/js/client/image-overlay.js
index da192178..e9e2708d 100644
--- a/src/static/js/client/image-overlay.js
+++ b/src/static/js/client/image-overlay.js
@@ -96,7 +96,10 @@ function handleContainerClicked(evt) {
   // If you clicked anything near the action bar, don't hide the
   // image overlay.
   const rect = info.actionContainer.getBoundingClientRect();
-  if (evt.clientY >= rect.top - 40 && evt.clientY <= rect.bottom + 40) {
+  if (
+    evt.clientY >= rect.top - 40 && evt.clientY <= rect.bottom + 40 &&
+    evt.clientX >= rect.left + 20 && evt.clientX <= rect.right - 20
+  ) {
     return;
   }
 
diff --git a/src/static/js/client/sticky-heading.js b/src/static/js/client/sticky-heading.js
index fba05b84..b65574d0 100644
--- a/src/static/js/client/sticky-heading.js
+++ b/src/static/js/client/sticky-heading.js
@@ -23,6 +23,7 @@ export const info = {
 
   contentContainers: null,
   contentHeadings: null,
+  contentCoverColumns: null,
   contentCovers: null,
   contentCoversReveal: null,
 
@@ -82,9 +83,13 @@ export function getPageReferences() {
     info.stickyContainers
       .map(el => el.closest('.content-sticky-heading-root').parentElement);
 
-  info.contentCovers =
+  info.contentCoverColumns =
     info.contentContainers
-      .map(el => el.querySelector('#cover-art-container'));
+      .map(el => el.querySelector('#artwork-column'));
+
+  info.contentCovers =
+    info.contentCoverColumns
+      .map(el => el ? el.querySelector('.cover-artwork') : null);
 
   info.contentCoversReveal =
     info.contentCovers
@@ -212,10 +217,10 @@ function updateCollapseStatus(index) {
 function updateStickyCoverVisibility(index) {
   const stickyCoverContainer = info.stickyCoverContainers[index];
   const stickyContainer = info.stickyContainers[index];
-  const contentCover = info.contentCovers[index];
+  const contentCoverColumn = info.contentCoverColumns[index];
 
-  if (contentCover && stickyCoverContainer) {
-    if (contentCover.getBoundingClientRect().bottom < 4) {
+  if (contentCoverColumn && stickyCoverContainer) {
+    if (contentCoverColumn.getBoundingClientRect().bottom < 4) {
       stickyCoverContainer.classList.add('visible');
       stickyContainer.classList.add('cover-visible');
     } else {
diff --git a/src/static/js/rectangles.js b/src/static/js/rectangles.js
index cdab2cb8..b00ed98e 100644
--- a/src/static/js/rectangles.js
+++ b/src/static/js/rectangles.js
@@ -510,4 +510,46 @@ export class WikiRect extends DOMRect {
       height: this.height,
     });
   }
+
+  // Other utilities
+
+  #display = null;
+
+  display() {
+    if (!this.#display) {
+      this.#display = document.createElement('div');
+      document.body.appendChild(this.#display);
+    }
+
+    Object.assign(this.#display.style, {
+      position: 'fixed',
+      background: '#000c',
+      border: '3px solid var(--primary-color)',
+      borderRadius: '4px',
+      top: this.top + 'px',
+      left: this.left + 'px',
+      width: this.width + 'px',
+      height: this.height + 'px',
+      pointerEvents: 'none',
+    });
+
+    let i = 0;
+    const int = setInterval(() => {
+      i++;
+      if (i >= 3) clearInterval(int);
+      if (!this.#display) return;
+
+      this.#display.style.display = 'none';
+      setTimeout(() => {
+        this.#display.style.display = '';
+      }, 200);
+    }, 600);
+  }
+
+  hide() {
+    if (this.#display) {
+      this.#display.remove();
+      this.#display = null;
+    }
+  }
 }