]> BookStack Code Mirror - website/blobdiff - themes/bookstack/static/js/script.js
Final post release time
[website] / themes / bookstack / static / js / script.js
index 8fe5d0fb4438c2c4c6499ab36cae76fcb79db7e7..6b7e5a7a15e812011e02547221a50ef9d66c02f0 100644 (file)
@@ -57,14 +57,12 @@ const searchInput = document.getElementById('site-search-input');
 const searchDialog = searchForm.querySelector('dialog');
 
 async function runSearch() {
-  const searchTerm = searchInput.value.toLowerCase();
+  const searchTerm = searchInput.value;
 
   let pages = [];
   try {
-    pages = await window.webidx.search({
-      dbfile:'/search.db',
-      query: searchTerm,
-    });
+    const resp = await fetch(`/search.php?query=${encodeURIComponent(searchTerm)}`);
+    pages = await resp.json();
   } catch (error) {
     searchDialog.innerHTML = '<strong class="search-category-title">Failed to load search results</strong>';
     console.error(error);
@@ -72,9 +70,10 @@ async function runSearch() {
   }
 
   // Sort pages to prioritise those with word in title
+  const lowerSearchTerm = searchTerm.toLowerCase();
   pages.sort((a, b) => {
-    const aScore = (a.url.includes(searchTerm) || a.title.toLowerCase().includes(searchTerm)) ? 1 : 0;
-    const bScore = (b.url.includes(searchTerm) || b.title.toLowerCase().includes(searchTerm)) ? 1 : 0;
+    const aScore = (a.url.includes(lowerSearchTerm) || a.title.toLowerCase().includes(lowerSearchTerm)) ? 1 : 0;
+    const bScore = (b.url.includes(lowerSearchTerm) || b.title.toLowerCase().includes(lowerSearchTerm)) ? 1 : 0;
     return bScore - aScore;
   });
 
@@ -88,13 +87,15 @@ async function runSearch() {
   const categoryNames = Object.keys(categorised);
 
   for (const page of pages) {
+    let pageCategory = null;
     for (const categoryName of categoryNames) {
       const category = categorised[categoryName];
-      if (page.url.includes(category.filter)) {
-        category.pages.push(page);
+      if (page.url.startsWith(category.filter)) {
+        pageCategory = category;
         break;
       }
     }
+    (pageCategory || categorised.other).pages.push(page);
   }
 
   const categoryResults = categoryNames.map(name => {
@@ -114,8 +115,8 @@ async function runSearch() {
   const resultList = categoryResults.length ? categoryResults : [emptyResult];
   const results = el('div', {}, resultList);
 
-  for (const child of searchDialog.children) {
-    child.remove();
+  while (searchDialog.firstChild) {
+    searchDialog.removeChild(searchDialog.firstChild);
   }
   
   searchDialog.append(results);
@@ -128,33 +129,59 @@ function showSearchDialog() {
   }
   searchDialog.show();
   searchInput.focus();
-  
+
   const clickListener = e => {
-    if(!e.target.closest('dialog')) {
+    if (!e.target.closest('dialog')) {
       closeListener();
     }
   };
 
   const escListener = e => {
     if (e.key === 'Escape') {
-        closeListener();
+      closeListener();
+    }
+  };
+
+  const arrowListener = e => {
+    if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') {
+      return;
+    }
+    e.preventDefault();
+
+    const links = Array.from(searchDialog.querySelectorAll('a'));
+    const focusables = [searchInput, ...links];
+    if (focusables.length < 2) { // Only search input
+      return;
+    }
+
+    const active = document.activeElement;
+    let currentIndex = focusables.indexOf(active);
+
+    if (e.key === 'ArrowDown') {
+      currentIndex = (currentIndex + 1) % focusables.length;
+    } else { // ArrowUp
+      currentIndex = (currentIndex - 1 + focusables.length) % focusables.length;
     }
+
+    focusables[currentIndex].focus();
   };
 
   const mouseLeaveListener = e => {
     closeListener();
-  }
+  };
 
   const closeListener = () => {
     searchDialog.close();
     document.removeEventListener('click', clickListener);
     document.removeEventListener('keydown', escListener);
     searchForm.removeEventListener('mouseleave', mouseLeaveListener);
+    searchForm.removeEventListener('keydown', arrowListener);
   };
 
   document.addEventListener('click', clickListener);
   document.addEventListener('keydown', escListener);
   searchForm.addEventListener('mouseleave', mouseLeaveListener);
+  searchForm.addEventListener('keydown', arrowListener);
 }
 
 function showSearchLoading() {
@@ -176,4 +203,17 @@ searchInput.addEventListener('input', event => {
     showSearchLoading();
     runSearch();
   }
-})
\ No newline at end of file
+});
+
+
+// Email display
+const emailDisplayLinks = document.querySelectorAll('a.email-display');
+const eb64 = 'ZW1haWxAYm9v' + 'a3N0YWNrYXBwLmNvbQ==';
+for (const link of emailDisplayLinks) {
+  const email = atob(eb64);
+  link.addEventListener('click', e => {
+    e.preventDefault();
+    e.target.textContent = email;
+    e.target.href = 'mailto:' + email;
+  });
+}
\ No newline at end of file