« 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.js107
-rw-r--r--src/static/site5.css66
2 files changed, 173 insertions, 0 deletions
diff --git a/src/static/client3.js b/src/static/client3.js
index 9db9fc6c..d0973e46 100644
--- a/src/static/client3.js
+++ b/src/static/client3.js
@@ -1033,6 +1033,7 @@ const hashLinkInfo = clientInfo.hashLinkInfo = {
   },
 
   event: {
+    beforeHashLinkScrolls: [],
     whenHashLinkClicked: [],
   },
 };
@@ -1095,6 +1096,21 @@ function addHashLinkListeners() {
         return;
       }
 
+      // Don't do anything if the target element isn't actually visible!
+      if (target.offsetParent === null) {
+        return;
+      }
+
+      // Allow event handlers to prevent scrolling.
+      for (const handler of event.beforeHashLinkScrolls) {
+        if (handler({
+          link: hashLink,
+          target,
+        }) === false) {
+          return;
+        }
+      }
+
       // Hide skipper box right away, so the layout is updated on time for the
       // math operations coming up next.
       const skipper = document.getElementById('skippers');
@@ -1134,6 +1150,7 @@ function addHashLinkListeners() {
       for (const handler of event.whenHashLinkClicked) {
         handler({
           link: hashLink,
+          target,
         });
       }
     });
@@ -1704,6 +1721,96 @@ function loadImage(imageUrl, onprogress) {
   });
 }
 
+// "Additional names" box ---------------------------------
+
+const additionalNamesBoxInfo = clientInfo.additionalNamesBox = {
+  box: null,
+  links: null,
+  mainContentContainer: null,
+
+  state: {
+    visible: false,
+  },
+};
+
+function getAdditionalNamesBoxReferences() {
+  const info = additionalNamesBoxInfo;
+
+  info.box =
+    document.getElementById('additional-names-box');
+
+  info.links =
+    document.querySelectorAll('a[href="#additional-names-box"]');
+
+  info.mainContentContainer =
+    document.querySelector('#content .main-content-container');
+}
+
+function addAdditionalNamesBoxInternalListeners() {
+  const info = additionalNamesBoxInfo;
+
+  hashLinkInfo.event.beforeHashLinkScrolls.push(({target}) => {
+    if (target === info.box) {
+      return false;
+    }
+  });
+}
+
+function addAdditionalNamesBoxListeners() {
+  const info = additionalNamesBoxInfo;
+
+  for (const link of info.links) {
+    link.addEventListener('click', domEvent => {
+      handleAdditionalNamesBoxLinkClicked(domEvent);
+    });
+  }
+}
+
+function handleAdditionalNamesBoxLinkClicked(domEvent) {
+  const info = additionalNamesBoxInfo;
+  const {state} = info;
+
+  domEvent.preventDefault();
+
+  if (!info.box || !info.mainContentContainer) return;
+
+  const margin =
+    +(cssProp(info.box, 'scroll-margin-top').replace('px', ''));
+
+  const {top} =
+    (state.visible
+      ? info.box.getBoundingClientRect()
+      : info.mainContentContainer.getBoundingClientRect());
+
+  if (top + 20 < margin || top > 0.4 * window.innerHeight) {
+    if (!state.visible) {
+      toggleAdditionalNamesBox();
+    }
+
+    window.scrollTo({
+      top: window.scrollY + top - margin,
+      behavior: 'smooth',
+    });
+  } else {
+    toggleAdditionalNamesBox();
+  }
+}
+
+function toggleAdditionalNamesBox() {
+  const info = additionalNamesBoxInfo;
+  const {state} = info;
+
+  state.visible = !state.visible;
+  info.box.style.display =
+    (state.visible
+      ? 'block'
+      : 'none');
+}
+
+clientSteps.getPageReferences.push(getAdditionalNamesBoxReferences);
+clientSteps.addInternalListeners.push(addAdditionalNamesBoxInternalListeners);
+clientSteps.addPageListeners.push(addAdditionalNamesBoxListeners);
+
 // Group contributions table ------------------------------
 
 // TODO: Update to clientSteps style.
diff --git a/src/static/site5.css b/src/static/site5.css
index 5a769545..bf2eea11 100644
--- a/src/static/site5.css
+++ b/src/static/site5.css
@@ -872,6 +872,68 @@ html[data-url-key="localized.listing"][data-url-value0="random"] #content a:not(
   opacity: 0.7;
 }
 
+/* Additional names (heading and box) */
+
+h1 a[href="#additional-names-box"] {
+  color: inherit;
+  text-decoration: underline;
+  text-decoration-style: dotted;
+}
+
+h1 a[href="#additional-names-box"]:hover {
+  text-decoration-style: solid;
+}
+
+#additional-names-box {
+  --custom-scroll-offset: calc(0.5em - 2px);
+
+  margin: 1em 0 1em -10px;
+  padding: 15px 20px 10px 20px;
+  width: max-content;
+  max-width: min(60vw, 600px);
+
+  border: 1px dotted var(--primary-color);
+  border-radius: 6px;
+
+  background:
+    linear-gradient(var(--bg-color), var(--bg-color)),
+    linear-gradient(#000000bb, #000000bb),
+    var(--primary-color);
+
+  box-shadow: 0 -2px 6px -1px var(--dim-color) inset;
+
+  display: none;
+}
+
+#additional-names-box > :first-child { margin-top: 0; }
+#additional-names-box > :last-child { margin-bottom: 0; }
+
+#additional-names-box p {
+  padding-left: 10px;
+  padding-right: 10px;
+  margin-bottom: 0;
+  font-style: oblique;
+}
+
+#additional-names-box ul {
+  padding-left: 10px;
+  margin-top: 0.5em;
+}
+
+#additional-names-box li .additional-name {
+  margin-right: 0.25em;
+}
+
+#additional-names-box li .additional-name .content-image {
+  margin-bottom: 0.25em;
+  margin-top: 0.5em;
+}
+
+#additional-names-box li .annotation {
+  opacity: 0.8;
+  display: inline-block;
+}
+
 /* Images */
 
 .image-container {
@@ -1830,6 +1892,10 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content
     max-width: unset;
   }
 
+  #additional-names-box {
+    max-width: unset;
+  }
+
   /* Show sticky heading above cover art */
 
   .content-sticky-heading-container {