From 9382997b0095c3611bfd9d06e593b162175f1f39 Mon Sep 17 00:00:00 2001 From: welpo Date: Sun, 7 Jan 2024 20:10:10 +0100 Subject: [PATCH] fix same- page result navigation --- static/js/searchElasticlunr.js | 38 +++++++++++++++++++----------- static/js/searchElasticlunr.min.js | 2 +- templates/partials/header.html | 2 +- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/static/js/searchElasticlunr.js b/static/js/searchElasticlunr.js index 926071a26..0cf9281ca 100644 --- a/static/js/searchElasticlunr.js +++ b/static/js/searchElasticlunr.js @@ -2945,7 +2945,7 @@ window.onload = function () { // Display the results. let resultIdCounter = 0; // Counter to generate unique IDs. searchResults.forEach(function (result) { - if (result.doc.body !== '') { + if (result.doc.title || result.doc.path || result.doc.id) { const resultDiv = document.createElement('div'); resultDiv.setAttribute('role', 'option'); resultDiv.id = 'result-' + resultIdCounter++; @@ -2953,24 +2953,32 @@ window.onload = function () { const linkElement = resultDiv.querySelector('a'); const titleElement = resultDiv.querySelector('span:first-child'); const snippetElement = resultDiv.querySelector('span:nth-child(2)'); - // Return a link with text fragment, scrolling and highlighting the search term. - const encodedSearchTerm = encodeURIComponent(searchTerm); - linkElement.href = `${result.ref}#:~:text=${encodedSearchTerm}`; - titleElement.textContent = result.doc.title; + + // Determine the text for the title. + titleElement.textContent = + result.doc.title || result.doc.path || result.doc.id; + + // Determine if the body or description is available for the snippet. + let snippetText = result.doc.body + ? generateSnippet(result.doc.body, searchTerm.split(/\s+/)) + : result.doc.description + ? result.doc.description + : ''; + snippetElement.innerHTML = snippetText; + + // Create the hyperlink. + let href = result.ref; if (result.doc.body) { - snippetElement.innerHTML = generateSnippet( - result.doc.body, - searchTerm.split(/\s+/) - ); - } else { - // Handle the case where body is undefined or empty - console.error('Document body is undefined for result:', result); - snippetElement.innerHTML = ''; // Or set some default message + // Include text fragment if body is available. + const encodedSearchTerm = encodeURIComponent(searchTerm); + href += `#:~:text=${encodedSearchTerm}`; } + linkElement.href = href; results.appendChild(resultDiv); } }); + searchInput.setAttribute( 'aria-expanded', resultIdCounter > 0 ? 'true' : 'false' @@ -3093,11 +3101,13 @@ window.onload = function () { } if (event.key === 'Enter' && activeDiv) { + event.preventDefault(); + event.stopImmediatePropagation(); const anchorTag = activeDiv.querySelector('a'); if (anchorTag) { - event.preventDefault(); window.location.href = anchorTag.getAttribute('href'); } + closeModal(); // Necessary when linking to the current page. } }); }; diff --git a/static/js/searchElasticlunr.min.js b/static/js/searchElasticlunr.min.js index 3b8a13653..be49f4d31 100644 --- a/static/js/searchElasticlunr.min.js +++ b/static/js/searchElasticlunr.min.js @@ -1 +1 @@ -!function(){function g(e){var t=new g.Index;return t.pipeline.add(g.trimmer,g.stopWordFilter,g.stemmer),e&&e.call(t,t),t}var t;g.version="0.9.5",(lunr=g).utils={},g.utils.warn=(t=this,function(e){t.console&&console.warn&&console.warn(e)}),g.utils.toString=function(e){return null==e?"":e.toString()},(g.EventEmitter=function(){this.events={}}).prototype.addListener=function(){var e=Array.prototype.slice.call(arguments);const t=e.pop();if("function"!=typeof t)throw new TypeError("last argument must be a function");e.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},g.EventEmitter.prototype.removeListener=function(e,t){this.hasHandler(e)&&-1!==(t=this.events[e].indexOf(t))&&(this.events[e].splice(t,1),0===this.events[e].length)&&delete this.events[e]},g.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){const t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},g.EventEmitter.prototype.hasHandler=function(e){return e in this.events},(g.tokenizer=function(n){if(!arguments.length||null==n)return[];if(Array.isArray(n)){let e=n.filter(function(e){return null!=e}),t=(e=e.map(function(e){return g.utils.toString(e).toLowerCase()}),[]);return e.forEach(function(e){e=e.split(g.tokenizer.seperator),t=t.concat(e)},this),t}return n.toString().trim().toLowerCase().split(g.tokenizer.seperator)}).defaultSeperator=/[\s-]+/,g.tokenizer.seperator=g.tokenizer.defaultSeperator,g.tokenizer.setSeperator=function(e){null!=e&&"object"==typeof e&&(g.tokenizer.seperator=e)},g.tokenizer.resetSeperator=function(){g.tokenizer.seperator=g.tokenizer.defaultSeperator},g.tokenizer.getSeperator=function(){return g.tokenizer.seperator},(g.Pipeline=function(){this._queue=[]}).registeredFunctions={},g.Pipeline.registerFunction=function(e,t){t in g.Pipeline.registeredFunctions&&g.utils.warn("Overwriting existing registered function: "+t),e.label=t,g.Pipeline.registeredFunctions[t]=e},g.Pipeline.getRegisteredFunction=function(e){return e in g.Pipeline.registeredFunctions!=1?null:g.Pipeline.registeredFunctions[e]},g.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||g.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},g.Pipeline.load=function(e){const n=new g.Pipeline;return e.forEach(function(e){var t=g.Pipeline.getRegisteredFunction(e);if(!t)throw new Error("Cannot load un-registered function: "+e);n.add(t)}),n},g.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){g.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},g.Pipeline.prototype.after=function(e,t){if(g.Pipeline.warnIfFunctionNotRegistered(t),-1===(e=this._queue.indexOf(e)))throw new Error("Cannot find existingFn");this._queue.splice(e+1,0,t)},g.Pipeline.prototype.before=function(e,t){if(g.Pipeline.warnIfFunctionNotRegistered(t),-1===(e=this._queue.indexOf(e)))throw new Error("Cannot find existingFn");this._queue.splice(e,0,t)},g.Pipeline.prototype.remove=function(e){-1!==(e=this._queue.indexOf(e))&&this._queue.splice(e,1)},g.Pipeline.prototype.run=function(o){var e=[],t=o.length,i=this._queue.length;for(let n=0;ne&&(n=i),o=n-t,i=t+Math.floor(o/2),r=this.elements[i]}return r===e?i:-1},lunr.SortedSet.prototype.locationFor=function(e){let t=0,n=this.elements.length,o=n-t,i=t+Math.floor(o/2),r=this.elements[i];for(;1e&&(n=i),o=n-t,i=t+Math.floor(o/2),r=this.elements[i];return r>e?i:ri-1||o>r-1);)s[n]===l[o]?(t.add(s[n]),n++,o++):s[n]l[o]&&o++;return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){let t,n,o;n=this.length>=e.length?(t=this,e):(t=e,this),o=t.clone();for(let e=0,t=n.toArray();e{let t=n.getAttribute(e);t&&(t=t.replace("$SHORTCUT",m),n.setAttribute(e,t))})}s.addEventListener("keydown",function(e){"Enter"!==e.key&&" "!==e.key||s.click()});let e,i=(f.addEventListener("click",o),f.addEventListener("touchend",o),document.addEventListener("keydown",function(e){"Escape"===e.key&&u()}),g.addEventListener("click",function(){t(),h.focus()}),g.addEventListener("keydown",function(e){"Enter"!==e.key&&" "!==e.key||(t(),h.focus(),e.preventDefault())}),s.addEventListener("mouseover",r),s.addEventListener("click",l),s.addEventListener("touchstart",l),null);function l(){e=document.activeElement,r(),f.style.display="block",h.focus()}function u(){f.style.display="none",t(),e&&document.body.contains(e)&&e.focus()}function a(e){var t;"true"!==e.getAttribute("aria-selected")&&([t=null]=[e],d.querySelectorAll("#results > div").forEach(e=>{e!==t&&e.setAttribute("aria-selected","false")}),e.setAttribute("aria-selected","true")),h.setAttribute("aria-activedescendant",e.id)}function t(){h.value="",d.innerHTML="",p.textContent="0",y.style.display="none",h.removeAttribute("aria-activedescendant")}function o(e){e.target===f&&u(),e.stopPropagation()}function r(){if(!i)if(window.searchIndex)i=Promise.resolve(elasticlunr.Index.load(window.searchIndex));else{var t=document.documentElement.getAttribute("lang").substring(0,2);let e=document.querySelector("meta[name='base']").getAttribute("content");e.endsWith("/")&&(e=e.slice(0,-1)),i=fetch(e+"/search_index."+t+".json").then(e=>e.json()).then(e=>elasticlunr.Index.load(e))}}function w(e){return e=parseInt(e,16).toString(2),[0,1,2,3,4][Math.ceil(e.length/8)]}function c(){a(this)}h.addEventListener("input",async function(){const s=this.value.trim();var e,t,n=await i,o=(d.innerHTML="",y.style.display=0",n=t.querySelector("a"),o=t.querySelector("span:first-child"),i=t.querySelector("span:nth-child(2)"),r=encodeURIComponent(s),n.href=e.ref+"#:~:text="+r,o.textContent=e.doc.title,i.innerHTML=function(e,t){var n=t.map(function(e){return elasticlunr.stemmer(e.toLowerCase())});let o=0;var i=[];for(const m of e.toLowerCase().split(". ")){let t=!0;for(const v of m.split(/[\s\n]/)){if(0"),p[2]+p[0].length);!h.test(p[0])&&12<=p[0].length?(f=function(t){let n="",o=!1,i=0,r=0,s=0;for(let e=0;e"),d=g}c.push("…");var y=t=c.join("");return 150]+>/g,"").length?t.substring(0,150)+"…":y}(e.doc.body,s.split(/\s+/)),d.appendChild(t))}),h.setAttribute("aria-expanded",0 div").forEach(e=>{e.removeEventListener("touchstart",c),e.addEventListener("touchstart",c)})},!0),document.addEventListener("keydown",function(t){var e=navigator.userAgent.toLowerCase().includes("mac")?t.metaKey:t.ctrlKey;if("k"===t.key&&e)t.preventDefault(),("block"===f.style.display?u:l)();else if(e=document.activeElement,"Tab"!==t.key||e!==h&&e!==g){if(0!==(r=d.querySelectorAll("#results > div")).length){var n,o,i=Array.from(r),r=d.querySelector('[aria-selected="true"]'),s=i.indexOf(r);if(["ArrowUp","ArrowDown","Home","End","PageUp","PageDown"].includes(t.key)){t.preventDefault();let e=s;switch(t.key){case"ArrowUp":e=Math.max(s-1,0);break;case"ArrowDown":e=Math.min(s+1,i.length-1);break;case"Home":e=0;break;case"End":e=i.length-1;break;case"PageUp":e=Math.max(s-3,0);break;case"PageDown":e=Math.min(s+3,i.length-1)}e!==s&&(a((o=i)[n=e]),o[n].scrollIntoView({block:"nearest",inline:"start"}))}"Enter"===t.key&&r&&(o=r.querySelector("a"))&&(t.preventDefault(),window.location.href=o.getAttribute("href"))}}else t.preventDefault(),(e===h?g:h).focus()})}}; +!function(){function p(e){var t=new p.Index;return t.pipeline.add(p.trimmer,p.stopWordFilter,p.stemmer),e&&e.call(t,t),t}var t;p.version="0.9.5",(lunr=p).utils={},p.utils.warn=(t=this,function(e){t.console&&console.warn&&console.warn(e)}),p.utils.toString=function(e){return null==e?"":e.toString()},p.EventEmitter=function(){this.events={}},p.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments);const t=e.pop();if("function"!=typeof t)throw new TypeError("last argument must be a function");e.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},p.EventEmitter.prototype.removeListener=function(e,t){this.hasHandler(e)&&-1!==(t=this.events[e].indexOf(t))&&(this.events[e].splice(t,1),0===this.events[e].length)&&delete this.events[e]},p.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){const t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},p.EventEmitter.prototype.hasHandler=function(e){return e in this.events},p.tokenizer=function(n){if(!arguments.length||null==n)return[];if(Array.isArray(n)){let e=n.filter(function(e){return null!=e}),t=(e=e.map(function(e){return p.utils.toString(e).toLowerCase()}),[]);return e.forEach(function(e){e=e.split(p.tokenizer.seperator),t=t.concat(e)},this),t}return n.toString().trim().toLowerCase().split(p.tokenizer.seperator)},p.tokenizer.defaultSeperator=/[\s-]+/,p.tokenizer.seperator=p.tokenizer.defaultSeperator,p.tokenizer.setSeperator=function(e){null!=e&&"object"==typeof e&&(p.tokenizer.seperator=e)},p.tokenizer.resetSeperator=function(){p.tokenizer.seperator=p.tokenizer.defaultSeperator},p.tokenizer.getSeperator=function(){return p.tokenizer.seperator},p.Pipeline=function(){this._queue=[]},p.Pipeline.registeredFunctions={},p.Pipeline.registerFunction=function(e,t){t in p.Pipeline.registeredFunctions&&p.utils.warn("Overwriting existing registered function: "+t),e.label=t,p.Pipeline.registeredFunctions[t]=e},p.Pipeline.getRegisteredFunction=function(e){return e in p.Pipeline.registeredFunctions!=1?null:p.Pipeline.registeredFunctions[e]},p.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||p.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},p.Pipeline.load=function(e){const n=new p.Pipeline;return e.forEach(function(e){var t=p.Pipeline.getRegisteredFunction(e);if(!t)throw new Error("Cannot load un-registered function: "+e);n.add(t)}),n},p.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){p.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},p.Pipeline.prototype.after=function(e,t){if(p.Pipeline.warnIfFunctionNotRegistered(t),-1===(e=this._queue.indexOf(e)))throw new Error("Cannot find existingFn");this._queue.splice(e+1,0,t)},p.Pipeline.prototype.before=function(e,t){if(p.Pipeline.warnIfFunctionNotRegistered(t),-1===(e=this._queue.indexOf(e)))throw new Error("Cannot find existingFn");this._queue.splice(e,0,t)},p.Pipeline.prototype.remove=function(e){-1!==(e=this._queue.indexOf(e))&&this._queue.splice(e,1)},p.Pipeline.prototype.run=function(o){var e=[],t=o.length,i=this._queue.length;for(let n=0;ne&&(n=i),o=n-t,i=t+Math.floor(o/2),r=this.elements[i]}return r===e?i:-1},lunr.SortedSet.prototype.locationFor=function(e){let t=0,n=this.elements.length,o=n-t,i=t+Math.floor(o/2),r=this.elements[i];for(;1e&&(n=i),o=n-t,i=t+Math.floor(o/2),r=this.elements[i];return r>e?i:ri-1||o>r-1);)s[n]===l[o]?(t.add(s[n]),n++,o++):s[n]l[o]&&o++;return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){let t,n,o;n=this.length>=e.length?(t=this,e):(t=e,this),o=t.clone();for(let e=0,t=n.toArray();e{let t=n.getAttribute(e);t&&(t=t.replace("$SHORTCUT",v),n.setAttribute(e,t))})}s.addEventListener("keydown",function(e){"Enter"!==e.key&&" "!==e.key||s.click()});let e,i=(f.addEventListener("click",o),f.addEventListener("touchend",o),document.addEventListener("keydown",function(e){"Escape"===e.key&&u()}),g.addEventListener("click",function(){t(),h.focus()}),g.addEventListener("keydown",function(e){"Enter"!==e.key&&" "!==e.key||(t(),h.focus(),e.preventDefault())}),s.addEventListener("mouseover",r),s.addEventListener("click",l),s.addEventListener("touchstart",l),null);function l(){e=document.activeElement,r(),f.style.display="block",h.focus()}function u(){f.style.display="none",t(),e&&document.body.contains(e)&&e.focus()}function a(e){var t;"true"!==e.getAttribute("aria-selected")&&([t=null]=[e],d.querySelectorAll("#results > div").forEach(e=>{e!==t&&e.setAttribute("aria-selected","false")}),e.setAttribute("aria-selected","true")),h.setAttribute("aria-activedescendant",e.id)}function t(){h.value="",d.innerHTML="",p.textContent="0",y.style.display="none",h.removeAttribute("aria-activedescendant")}function o(e){e.target===f&&u(),e.stopPropagation()}function r(){if(!i)if(window.searchIndex)i=Promise.resolve(elasticlunr.Index.load(window.searchIndex));else{var t=document.documentElement.getAttribute("lang").substring(0,2);let e=document.querySelector("meta[name='base']").getAttribute("content");e.endsWith("/")&&(e=e.slice(0,-1)),i=fetch(e+"/search_index."+t+".json").then(e=>e.json()).then(e=>elasticlunr.Index.load(e))}}function m(e){return e=parseInt(e,16).toString(2),[0,1,2,3,4][Math.ceil(e.length/8)]}function c(){a(this)}h.addEventListener("input",async function(){const s=this.value.trim();var e,t,n,o=await i;d.innerHTML="",y.style.display=0",n.querySelector("a")),i=n.querySelector("span:first-child"),r=n.querySelector("span:nth-child(2)");i.textContent=t.doc.title||t.doc.path||t.doc.id,i=t.doc.body?function(n,e){var o=e.map(function(e){return elasticlunr.stemmer(e.toLowerCase())});let i=0;var r=[];for(const e of n.toLowerCase().split(". ")){let t=!0;for(const s of e.split(/[\s\n]/)){if(0"),p[2]+p[0].length);!h.test(p[0])&&12<=p[0].length?(f=function(t){let n="",o=!1,i=0,r=0,s=0;for(let e=0;e"),d=g}c.push("…");var y=e=c.join("");return 150]+>/g,"").length?e.substring(0,150)+"…":y}(t.doc.body,s.split(/\s+/)):t.doc.description||"",r.innerHTML=i;let e=t.ref;t.doc.body&&(e+="#:~:text="+(r=encodeURIComponent(s))),o.href=e,d.appendChild(n)}}),h.setAttribute("aria-expanded",0 div").forEach(e=>{e.removeEventListener("touchstart",c),e.addEventListener("touchstart",c)})},!0),document.addEventListener("keydown",function(t){var e=navigator.userAgent.toLowerCase().includes("mac")?t.metaKey:t.ctrlKey;if("k"===t.key&&e)t.preventDefault(),("block"===f.style.display?u:l)();else if(e=document.activeElement,"Tab"!==t.key||e!==h&&e!==g){if(0!==(r=d.querySelectorAll("#results > div")).length){var n,o,i=Array.from(r),r=d.querySelector('[aria-selected="true"]'),s=i.indexOf(r);if(["ArrowUp","ArrowDown","Home","End","PageUp","PageDown"].includes(t.key)){t.preventDefault();let e=s;switch(t.key){case"ArrowUp":e=Math.max(s-1,0);break;case"ArrowDown":e=Math.min(s+1,i.length-1);break;case"Home":e=0;break;case"End":e=i.length-1;break;case"PageUp":e=Math.max(s-3,0);break;case"PageDown":e=Math.min(s+3,i.length-1)}e!==s&&(a((o=i)[n=e]),o[n].scrollIntoView({block:"nearest",inline:"start"}))}"Enter"===t.key&&r&&(t.preventDefault(),t.stopImmediatePropagation(),(o=r.querySelector("a"))&&(window.location.href=o.getAttribute("href")),u())}}else t.preventDefault(),(e===h?g:h).focus()})}}; diff --git a/templates/partials/header.html b/templates/partials/header.html index c003b4ffb..4473889c8 100644 --- a/templates/partials/header.html +++ b/templates/partials/header.html @@ -172,7 +172,7 @@ {%- endif -%} - + {# Support correct stemming and stop word filtering in non-English search #} {%- if lang != "en" -%}