« get me outta code hell

Merge branch 'additional-names' into preview - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/static/client3.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-11-24 14:56:10 -0400
committer(quasar) nebula <qznebula@protonmail.com>2023-11-24 14:56:10 -0400
commitca30b07b9e116f6d42d6ea6a2623e1500c289383 (patch)
tree64a65bbff14b09c914743c15f0e17d26bd27b87c /src/static/client3.js
parent9e00e7770e5c3987b6a6a1437d79a38ff57115b9 (diff)
parentbad238355e19c4fef5e5f3b41df88fa9b1b84aaa (diff)
Merge branch 'additional-names' into preview
Diffstat (limited to 'src/static/client3.js')
-rw-r--r--src/static/client3.js107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/static/client3.js b/src/static/client3.js
index 9db9fc6..d0973e4 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.