diff --git a/assets/js/offline-search.js b/assets/js/offline-search.js index 80db769a..d6bec0bf 100644 --- a/assets/js/offline-search.js +++ b/assets/js/offline-search.js @@ -1,208 +1,212 @@ // Adapted from code by Matt Walters https://www.mattwalters.net/posts/2018-03-28-hugo-and-lunr/ (function ($) { - 'use strict'; - - $(document).ready(function () { - const $searchInput = $('.td-search input'); - const $searchResults = $('.td-offline-search-results'); + "use strict"; + + $(document).ready(function () { + const $searchInput = $(".td-search input"); + const $searchResults = $(".td-offline-search-results"); + // + // Register handler + // + + $searchInput.on("change", (event) => { + render($(event.target)); + + // Hide keyboard on mobile browser + $searchInput.blur(); + }); + + // Prevent reloading page by enter key on sidebar search. + $searchInput.closest("form").on("submit", () => { + return false; + }); + + // + // Lunr + // + + let idx = null; // Lunr index + const resultDetails = new Map(); // Will hold the data for the search results (titles and summaries) + + // Set up for an Ajax call to request the JSON data file that is created by Hugo's build process + $.ajax($searchInput.data("offline-search-index-json-src")).then((data) => { + idx = lunr(function () { + this.ref("ref"); + + // If you added more searchable fields to the search index, list them here. + // Here you can specify searchable fields to the search index - e.g. individual toxonomies for you project + // With "boost" you can add weighting for specific (default weighting without boost: 1) + this.field("title", { boost: 5 }); + this.field("categories", { boost: 3 }); + this.field("tags", { boost: 3 }); + // this.field('projects', { boost: 3 }); // example for an individual toxonomy called projects + this.field("description", { boost: 2 }); + this.field("body"); + + data.forEach((doc) => { + this.add(doc); + + resultDetails.set(doc.ref, { + title: doc.title, + excerpt: doc.excerpt, + }); + }); + }); + + $searchInput.trigger("change"); + }); + + const render = ($targetSearchInput) => { // - // Register handler + // Dispose existing popover // - - $searchInput.on('change', (event) => { - render($(event.target)); - - // Hide keyboard on mobile browser - $searchInput.blur(); - }); - - // Prevent reloading page by enter key on sidebar search. - $searchInput.closest('form').on('submit', () => { - return false; - }); - + + { + let popover = bootstrap.Popover.getInstance($targetSearchInput[0]); + if (popover !== null) { + popover.dispose(); + } + } + // - // Lunr + // Search // - - let idx = null; // Lunr index - const resultDetails = new Map(); // Will hold the data for the search results (titles and summaries) - - // Set up for an Ajax call to request the JSON data file that is created by Hugo's build process - $.ajax($searchInput.data('offline-search-index-json-src')).then((data) => { - idx = lunr(function () { - this.ref('ref'); - - // If you added more searchable fields to the search index, list them here. - // Here you can specify searchable fields to the search index - e.g. individual toxonomies for you project - // With "boost" you can add weighting for specific (default weighting without boost: 1) - this.field('title', { boost: 5 }); - this.field('categories', { boost: 3 }); - this.field('tags', { boost: 3 }); - // this.field('projects', { boost: 3 }); // example for an individual toxonomy called projects - this.field('description', { boost: 2 }); - this.field('body'); - - data.forEach((doc) => { - this.add(doc); - - resultDetails.set(doc.ref, { - title: doc.title, - excerpt: doc.excerpt, + + if (idx === null) { + return; + } + + const searchQuery = $targetSearchInput.val(); + if (searchQuery === "") { + return; + } + + const results = idx + .query((q) => { + const tokens = lunr.tokenizer(searchQuery.toLowerCase()); + tokens.forEach((token) => { + const queryString = token.toString(); + q.term(queryString, { + boost: 100, }); - }); - }); - - $searchInput.trigger('change'); - }); - - const render = ($targetSearchInput) => { - // - // Dispose existing popover - // - - { - let popover = bootstrap.Popover.getInstance($targetSearchInput[0]); - if (popover !== null) { - popover.dispose(); - } - } - - // - // Search - // - - if (idx === null) { - return; - } - - const searchQuery = $targetSearchInput.val(); - if (searchQuery === '') { - return; - } - - const results = idx - .query((q) => { - const tokens = lunr.tokenizer(searchQuery.toLowerCase()); - tokens.forEach((token) => { - const queryString = token.toString(); - q.term(queryString, { - boost: 100, - }); - q.term(queryString, { - wildcard: - lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING, - boost: 10, - }); - q.term(queryString, { - editDistance: 2, - }); + q.term(queryString, { + wildcard: + lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING, + boost: 10, + }); + q.term(queryString, { + editDistance: 2, }); + }); + }) + .slice(0, $targetSearchInput.data("offline-search-max-results")); + + // + // Make result html + // + + const $html = $("
").text(`No results found for query "${searchQuery}"`) ); - - const $searchResultBody = $('
').text(`No results found for query "${searchQuery}"`) + } else { + results.forEach((r) => { + const doc = resultDetails.get(r.ref); + const href = + $searchInput.data("offline-search-base-href") + + r.ref.replace(/^\//, ""); + + const $entry = $("
').text(doc.excerpt));
-
- $searchResultBody.append($entry);
- });
- }
-
- $targetSearchInput.one('shown.bs.popover', () => {
- $('.td-offline-search-results__close-button').on('click', () => {
- $targetSearchInput.val('');
- $targetSearchInput.trigger('change');
- });
- });
-
- const popover = new bootstrap.Popover($targetSearchInput, {
- content: $html[0],
- html: true,
- customClass: 'td-offline-search-results',
- placement: 'bottom',
+
+ $entry.append(
+ $("")
+ .addClass("d-block")
+ .css({
+ fontSize: "1.2rem",
+ })
+ .attr("href", href)
+ .text(doc.title)
+ );
+
+ $entry.append($(" ").text(doc.excerpt));
+
+ $searchResultBody.append($entry);
});
- popover.show();
- };
+ }
- //Bring focus to search bar
- $(document).on('keydown', function (event) {
- if (event.key === '/') {
- $searchInput.focus();
- }
+ $targetSearchInput.one("shown.bs.popover", () => {
+ $(".td-offline-search-results__close-button").on("click", () => {
+ $targetSearchInput.val("");
+ $targetSearchInput.trigger("change");
+ });
});
- $(document).on('click', function (event) {
- if (!$(event.target).closest('.td-search').length) {
- // Clicked outside the search panel
- $searchInput.val('');
- $searchInput.trigger('change');
- }
+ const popover = new bootstrap.Popover($targetSearchInput, {
+ content: $html[0],
+ html: true,
+ customClass: "td-offline-search-results",
+ placement: "bottom",
});
+ popover.show();
+ };
- //close the search panel when the ESC key is pressed
- $(document).on('keydown', function (event) {
- if (event.key === 'Escape') {
- $searchInput.val('');
- $searchInput.trigger('change');
- }
- });
+ //Bring focus to search bar
+ $(document).on("keydown", function (event) {
+ if (event.key === "/") {
+ $searchInput.focus();
+ }
+ });
+ $(document).on("click", function (event) {
+ if (!$(event.target).closest(".td-search").length) {
+ // Clicked outside the search panel
+ $searchInput.val("");
+ $searchInput.trigger("change");
+ }
+ });
+
+ //close the search panel when the ESC key is pressed
+ $(document).on("keydown", function (event) {
+ if (event.key === "Escape") {
+ $searchInput.val("");
+ $searchInput.trigger("change");
+ }
+ });
+ $searchInput.on("keydown", (event) => {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ render($searchInput);
+ }
});
- })(jQuery);
-
\ No newline at end of file
+ });
+})(jQuery);
diff --git a/layouts/partials/hotkey.html b/layouts/partials/hotkey.html
index 6561782d..c1e1ca9d 100644
--- a/layouts/partials/hotkey.html
+++ b/layouts/partials/hotkey.html
@@ -13,11 +13,16 @@
href="https://unpkg.com/keyboard-css@1.2.4/dist/css/main.min.css"
/>