« 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/js
diff options
context:
space:
mode:
Diffstat (limited to 'src/static/js')
-rw-r--r--src/static/js/client.js81
1 files changed, 74 insertions, 7 deletions
diff --git a/src/static/js/client.js b/src/static/js/client.js
index 2bc8bf47..74240b0d 100644
--- a/src/static/js/client.js
+++ b/src/static/js/client.js
@@ -3711,6 +3711,9 @@ const sidebarSearchInfo = initInfo('sidebarSearchInfo', {
   state: {
     sidebarColumnShownForSearch: null,
 
+    tidiedSidebar: null,
+    collapsedDetailsForTidiness: null,
+
     workerStatus: null,
     searchStage: null,
 
@@ -3960,6 +3963,7 @@ function addSidebarSearchListeners() {
     domEvent.preventDefault();
     clearSidebarSearch();
     possiblyHideSearchSidebarColumn();
+    restoreSidebarSearchColumn();
   });
 }
 
@@ -4224,6 +4228,8 @@ function showSidebarSearchResults(results) {
   if (!empty(flatResults)) {
     cssProp(info.endSearchRule, 'display', 'block');
     cssProp(info.endSearchLine, 'display', 'block');
+
+    tidySidebarSearchColumn();
   }
 }
 
@@ -4428,19 +4434,80 @@ function possiblyHideSearchSidebarColumn() {
     return;
   }
 
-  if (state.sidebarColumnShownForSearch) {
-    info.searchSidebarColumn.classList.add('initially-hidden');
+  if (!state.sidebarColumnShownForSearch) {
+    return;
+  }
 
-    if (info.searchSidebarColumn.id === 'sidebar-left') {
-      info.pageContainer.classList.remove('showing-sidebar-left');
-    } else if (info.searchSidebarColumn.id === 'sidebar-right') {
-      info.pageContainer.classList.remove('showing-sidebar-right');
-    }
+  info.searchSidebarColumn.classList.add('initially-hidden');
+
+  if (info.searchSidebarColumn.id === 'sidebar-left') {
+    info.pageContainer.classList.remove('showing-sidebar-left');
+  } else if (info.searchSidebarColumn.id === 'sidebar-right') {
+    info.pageContainer.classList.remove('showing-sidebar-right');
   }
 
   state.sidebarColumnShownForSearch = null;
 }
 
+// This should be called after results are shown, since it checks the
+// elements added to understand the current search state.
+function tidySidebarSearchColumn() {
+  const info = sidebarSearchInfo;
+  const {state} = info;
+
+  // Don't *re-tidy* the sidebar if we've already tidied it to display
+  // some results. This flag will get cleared if the search is dismissed
+  // altogether (and the pre-tidy state is restored).
+  if (state.tidiedSidebar) {
+    return;
+  }
+
+  const here = location.href.replace(/\/$/, '');
+  const currentPageIsResult =
+    Array.from(info.results.querySelectorAll('a'))
+      .some(link => {
+        const there = link.href.replace(/\/$/, '');
+        return here === there;
+      });
+
+  // Don't tidy the sidebar if you've navigated to some other page than
+  // what's in the current result list.
+  if (!currentPageIsResult) {
+    return;
+  }
+
+  state.tidiedSidebar = true;
+  state.collapsedDetailsForTidiness = [];
+
+  for (const box of info.searchSidebarColumn.querySelectorAll('.sidebar')) {
+    if (box === info.searchBox) {
+      continue;
+    }
+
+    for (const details of box.getElementsByTagName('details')) {
+      if (details.open) {
+        details.removeAttribute('open');
+        state.collapsedDetailsForTidiness.push(details);
+      }
+    }
+  }
+}
+
+function restoreSidebarSearchColumn() {
+  const {state} = sidebarSearchInfo;
+
+  if (!state.tidiedSidebar) {
+    return;
+  }
+
+  for (const details of state.collapsedDetailsForTidiness) {
+    details.setAttribute('open', '');
+  }
+
+  state.collapsedDetailsForTidiness = [];
+  state.tidiedSidebar = null;
+}
+
 clientSteps.getPageReferences.push(getSidebarSearchReferences);
 clientSteps.addInternalListeners.push(addSidebarSearchInternalListeners);
 clientSteps.mutatePageContent.push(mutateSidebarSearchContent);