feat[partials/ js/] Stripped search functionality
I don't care about search on second thought.
This commit is contained in:
parent
06eba57815
commit
af33766176
@ -16,6 +16,7 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ block "footer" . }}
|
{{ block "footer" . }}
|
||||||
|
<script src="/js/dark.js" defer="" ></script>
|
||||||
<!-- More shared code, perhaps a footer but that can be overridden if need be in -->
|
<!-- More shared code, perhaps a footer but that can be overridden if need be in -->
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</body>
|
</body>
|
||||||
|
@ -4,4 +4,5 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Go <a href="{{ .Site.BaseURL }}/index.xml">here</a> for an RSS feed.</p>
|
<p>Go <a href="{{ .Site.BaseURL }}/index.xml">here</a> for an RSS feed.</p>
|
||||||
</footer>
|
<script src="/js/dark.js" defer="" ></script>
|
||||||
|
</footer>
|
||||||
|
@ -11,8 +11,4 @@
|
|||||||
<link rel="icon" type="image/png" href="/assets/img/favicon.ico" />
|
<link rel="icon" type="image/png" href="/assets/img/favicon.ico" />
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
|
||||||
integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
|
integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
|
||||||
<script src="/js/dark.js" defer=""></script>
|
|
||||||
|
|
||||||
{{ partialCached "search" . }}
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<!-- layouts/partials/search.html -->
|
<!-- layouts/partials/search.html -->
|
||||||
<form id="search__form" class="noscript" method="GET" action="https://duckduckgo.com/" data-language-prefix="{{ site.LanguagePrefix }}">
|
<form id="search__form" class="noscript" method="GET" action="https://duckduckgo.com/" data-language-prefix="{{ site.LanguagePrefix }}">
|
||||||
<div class="search__bar">
|
<div class="search__bar">
|
||||||
<input id="search__input" class="muted" name="q" tabindex="0" autocomplete="off" {{ with site.BaseURL }}value="Ctrl-/ to search"{{ end }} placeholder="{{ i18n "search" }}">
|
<input type="text" id="search__input" class="muted" name="q" tabindex="0" autocomplete="off" {{ with site.BaseURL }}value="Ctrl-Shift-L "{{ end }} placeholder="{{ i18n "search" }}">
|
||||||
<!-- label id="search__button" for="search__input" class="icon" type="button"><span>⌕</span></label>-->
|
<label id="search__button" for="search__input" class="icon" type="button"><span>⌕</span></label>
|
||||||
</div>
|
</div>
|
||||||
<div id="search__results" class="articles-list"></div>
|
<div id="search__results" class="articles-list"></div>
|
||||||
</form>
|
</form>
|
||||||
@ -12,8 +12,7 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
#search__form {
|
#search__form {
|
||||||
float: right;
|
|
||||||
padding: 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#search__input {
|
#search__input {
|
||||||
|
@ -3,16 +3,9 @@
|
|||||||
// Date: 2020-03-20
|
// Date: 2020-03-20
|
||||||
// When: Time-stamp: "2020-03-23 09:36:20 gwern"
|
// When: Time-stamp: "2020-03-23 09:36:20 gwern"
|
||||||
// license: PD
|
// license: PD
|
||||||
|
// Author: Judah Sotomayor
|
||||||
/* Experimental 'dark mode': Mac OS (Safari) lets users specify via an OS widget 'dark'/'light' to make everything appear */
|
// Date: 2023-10-15
|
||||||
/* bright-white or darker (eg for darker at evening to avoid straining eyes & disrupting circadian rhyhms); this then is */
|
// When: <2023-10-15 Sun 14:26>
|
||||||
/* exposed by Safari as a CSS variable which can be selected on. This is also currently supported by Firefox weakly as an */
|
|
||||||
/* about:config variable. Hypothetically, iOS in the future might use its camera or the clock to set 'dark mode' */
|
|
||||||
/* automatically. https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme */
|
|
||||||
/* https://webkit.org/blog/8718/new-webkit-features-in-safari-12-1/ */
|
|
||||||
/* https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
|
||||||
|
|
||||||
/* Because many users do not have access to a browser/OS which explicitly supports dark mode, cannot modify the browser/OS setting without undesired side-effects, wish to opt in only for specific websites, or simply forget that they turned on dark mode & dislike it, we make dark mode controllable by providing a widget at the top of the page. */
|
|
||||||
|
|
||||||
/* For gwern.net, the default white-black */
|
/* For gwern.net, the default white-black */
|
||||||
/* scheme is 'light', and it can be flipped to a 'dark' scheme fairly easily by inverting it; the main visual problem is */
|
/* scheme is 'light', and it can be flipped to a 'dark' scheme fairly easily by inverting it; the main visual problem is */
|
||||||
@ -28,7 +21,7 @@
|
|||||||
returns the created element.
|
returns the created element.
|
||||||
*/
|
*/
|
||||||
function addUIElement(element_html) {
|
function addUIElement(element_html) {
|
||||||
var ui_elements_container = document.querySelector("#ui-elements-container");
|
var ui_elements_container = document.getElementById('ui-elements-container');
|
||||||
if (!ui_elements_container) {
|
if (!ui_elements_container) {
|
||||||
ui_elements_container = document.createElement("div");
|
ui_elements_container = document.createElement("div");
|
||||||
ui_elements_container.id = "ui-elements-container";
|
ui_elements_container.id = "ui-elements-container";
|
||||||
@ -271,11 +264,8 @@ function injectModeSelector() {
|
|||||||
|
|
||||||
document.querySelector("head").insertAdjacentHTML("beforeend", `<style id='mode-selector-styles'>
|
document.querySelector("head").insertAdjacentHTML("beforeend", `<style id='mode-selector-styles'>
|
||||||
#mode-selector {
|
#mode-selector {
|
||||||
position: absolute;
|
position: relative;
|
||||||
right: 3px;
|
|
||||||
top: 4px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #fff;
|
|
||||||
padding: 0.125em 0.25em;
|
padding: 0.125em 0.25em;
|
||||||
border: 3px solid transparent;
|
border: 3px solid transparent;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
@ -288,7 +278,6 @@ function injectModeSelector() {
|
|||||||
#mode-selector:hover {
|
#mode-selector:hover {
|
||||||
transition: none;
|
transition: none;
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
border: 3px double #aaa;
|
|
||||||
}
|
}
|
||||||
#mode-selector button {
|
#mode-selector button {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
@ -327,7 +316,7 @@ function injectModeSelector() {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
border-bottom: 1px dotted currentColor;
|
border-bottom: 1px dotted currentColor;
|
||||||
width: calc(100% - 12px);
|
width: 25%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
</style>`);
|
</style>`);
|
||||||
|
@ -1,244 +0,0 @@
|
|||||||
// static/scripts/askolonion/askolonion.js
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
askolonion — Super fast, client side search for Hugo.io with Fusejs.io
|
|
||||||
based on https://gist.github.com/cmod/5410eae147e4318164258742dd053993
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
|
|
||||||
if (typeof variable !== 'undefined') {
|
|
||||||
console.log('askolonion.js already loaded');
|
|
||||||
} else {
|
|
||||||
askolonion = function(){
|
|
||||||
var search__form = document.getElementById('search__form'); // search form
|
|
||||||
var search__input = document.getElementById('search__input'); // input box for search
|
|
||||||
var search__button = document.getElementById('search__button'); // form submit button
|
|
||||||
var search__results = document.getElementById('search__results'); // targets the <ul>
|
|
||||||
var fuse; // holds our search engine
|
|
||||||
var search__focus = false; // check to true to make visible by default
|
|
||||||
var results_available = false; // did we get any search results?
|
|
||||||
var first_run = true; // allow us to delay loading json data unless search activated
|
|
||||||
var first = search__results.firstChild; // first child of search list
|
|
||||||
var last = search__results.lastChild; // last child of search list
|
|
||||||
|
|
||||||
|
|
||||||
search__form.classList.remove('noscript'); // JavaScript is active
|
|
||||||
search__form.setAttribute('data-focus', search__focus);
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
The main keyboard event listener running the show
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
// console.log(event); // DEBUG
|
|
||||||
// Ctrl + / to show or hide Search
|
|
||||||
// if (event.which === 191) { // Key: /
|
|
||||||
if (event.ctrlKey && event.which === 191) { // Key: Ctrl + /
|
|
||||||
search_toggle_focus(e); // toggle visibility of search box
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
The main keyboard event listener running the show
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__form.addEventListener('keydown', function(e) {
|
|
||||||
// Allow ESC (27) to close search box
|
|
||||||
if (e.keyCode == 27) {
|
|
||||||
search__focus = true; // make sure toggle removes focus
|
|
||||||
search_toggle_focus(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOWN (40) arrow
|
|
||||||
if (e.keyCode == 40) {
|
|
||||||
if (results_available) {
|
|
||||||
e.preventDefault(); // stop window from scrolling
|
|
||||||
if ( document.activeElement == search__input) { first.focus(); } // if the currently focused element is the main input --> focus the first <li>
|
|
||||||
else if ( document.activeElement == last ) { first.focus(); } // if we're at the bottom, loop to the start
|
|
||||||
// else if ( document.activeElement == last ) { last.focus(); } // if we're at the bottom, stay there
|
|
||||||
else { document.activeElement.parentElement.nextSibling.firstElementChild.focus(); } // otherwise select the next search result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UP (38) arrow
|
|
||||||
if (e.keyCode == 38) {
|
|
||||||
if (results_available) {
|
|
||||||
e.preventDefault(); // stop window from scrolling
|
|
||||||
if ( document.activeElement == search__input) { search__input.focus(); } // If we're in the input box, do nothing
|
|
||||||
else if ( document.activeElement == first) { search__input.focus(); } // If we're at the first item, go to input box
|
|
||||||
else { document.activeElement.parentElement.previousSibling.firstElementChild.focus(); } // Otherwise, select the search result above the current active one
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Enter (13) to move to the first result
|
|
||||||
if (e.keyCode == 13) {
|
|
||||||
e.preventDefault(); // stop form from being submitted
|
|
||||||
if (results_available && document.activeElement == search__input) {
|
|
||||||
first.focus();
|
|
||||||
} else {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Backspace (8) to switch back to the search input
|
|
||||||
if (e.keyCode == 8) {
|
|
||||||
if (document.activeElement != search__input) {
|
|
||||||
e.preventDefault(); // stop browser from going back in history
|
|
||||||
search__input.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Load our json data and builds fuse.js search index
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__form.addEventListener('focusin', function(e) {
|
|
||||||
search_init(); // try to load the search index
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Make button toggle focus
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__button.addEventListener('mousedown', function(e) {
|
|
||||||
search_toggle_focus(e);
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Remove focus on blur
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__form.addEventListener('focusout', function(e) {
|
|
||||||
if (e.relatedTarget === null) {
|
|
||||||
search_toggle_focus(e);
|
|
||||||
}
|
|
||||||
else if (e.relatedTarget.type === 'submit') {
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Toggle focus UI of form
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function search_toggle_focus(e) {
|
|
||||||
// order of operations is very important to keep focus where it should stay
|
|
||||||
if (!search__focus) {
|
|
||||||
// search__button.value = '⨯';
|
|
||||||
search__form.setAttribute('data-focus', true);
|
|
||||||
search__input.focus(); // move focus to search box
|
|
||||||
search__focus = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// search__button.value = '⌕';
|
|
||||||
search__form.setAttribute('data-focus', false);
|
|
||||||
document.activeElement.blur(); // remove focus from search box
|
|
||||||
search__focus = false;
|
|
||||||
}
|
|
||||||
// console.log(search__focus,e); // DEBUG
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Fetch some json without jquery
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function fetch_JSON(path, callback) {
|
|
||||||
var httpRequest = new XMLHttpRequest();
|
|
||||||
httpRequest.onreadystatechange = function() {
|
|
||||||
if (httpRequest.readyState === 4) {
|
|
||||||
if (httpRequest.status === 200) {
|
|
||||||
var data = JSON.parse(httpRequest.responseText);
|
|
||||||
if (callback) callback(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
httpRequest.open('GET', path);
|
|
||||||
httpRequest.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Load script
|
|
||||||
based on https://stackoverflow.com/a/55451823
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function load_script(url) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
let script = document.createElement("script");
|
|
||||||
script.onerror = reject;
|
|
||||||
script.onload = resolve;
|
|
||||||
if (document.currentScript) {
|
|
||||||
document.currentScript.parentNode.insertBefore(script, document.currentScript);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
document.head.appendChild(script)
|
|
||||||
}
|
|
||||||
script.src = url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Load our search index, only executed once
|
|
||||||
on first call of search box (Ctrl + /)
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function search_init() {
|
|
||||||
if (first_run) {
|
|
||||||
load_script(window.location.origin + '/scripts/askolonion/fuse.basic.min.js').then(() => {
|
|
||||||
search__input.value = ""; // reset default value
|
|
||||||
first_run = false; // let's never do this again
|
|
||||||
fetch_JSON(search__form.getAttribute('data-language-prefix') + '/index.json', function(data){
|
|
||||||
var options = { // fuse.js options; check fuse.js website for details
|
|
||||||
shouldSort: true,
|
|
||||||
location: 0,
|
|
||||||
distance: 100,
|
|
||||||
threshold: 0.4,
|
|
||||||
minMatchCharLength: 2,
|
|
||||||
keys: [
|
|
||||||
'permalink',
|
|
||||||
'title',
|
|
||||||
'date',
|
|
||||||
'summary',
|
|
||||||
'section',
|
|
||||||
'categories',
|
|
||||||
'tags'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
fuse = new Fuse(data, options); // build the index from the json file
|
|
||||||
|
|
||||||
search__input.addEventListener('keyup', function(e) { // execute search as each character is typed
|
|
||||||
search_exec(this.value);
|
|
||||||
});
|
|
||||||
// console.log("index.json loaded"); // DEBUG
|
|
||||||
});
|
|
||||||
}).catch((error) => { console.log('askolonion failed to load: ' + error); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Using the index we loaded on Ctrl + /, run
|
|
||||||
a search query (for "term") every time a letter is typed
|
|
||||||
in the search box
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function search_exec(term) {
|
|
||||||
let results = fuse.search(term); // the actual query being run using fuse.js
|
|
||||||
let search_items = ''; // our results bucket
|
|
||||||
|
|
||||||
if (results.length === 0) { // no results based on what was typed into the input box
|
|
||||||
results_available = false;
|
|
||||||
search_items = '';
|
|
||||||
} else { // build our html
|
|
||||||
for (let item in results.slice(0,50)) { // only show first 5 results
|
|
||||||
search_items = search_items +
|
|
||||||
`<article><a href="${results[item].item.permalink}" tabindex="0">
|
|
||||||
<time class="time">${results[item].item.date}</time>
|
|
||||||
<h3 class="title">${results[item].item.title}</h3>
|
|
||||||
<p class="summary">${results[item].item.summary}</p>
|
|
||||||
<span class="section">${results[item].item.section}</span>
|
|
||||||
<span class="categories">${results[item].item.categories.join(', ')}</span>
|
|
||||||
<span class="tags">${results[item].item.tags.join(', ')}</span>
|
|
||||||
</article>`;
|
|
||||||
}
|
|
||||||
results_available = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
search__results.innerHTML = search_items;
|
|
||||||
if (results.length > 0) {
|
|
||||||
first = search__results.firstChild.firstElementChild; // first result container — used for checking against keyboard up/down location
|
|
||||||
last = search__results.lastChild.firstElementChild; // last result container — used for checking against keyboard up/down location
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
}
|
|
9
static/scripts/askolonion/fuse.basic.min.js
vendored
9
static/scripts/askolonion/fuse.basic.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -1,244 +0,0 @@
|
|||||||
// static/scripts/askolonion/askolonion.js
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
askolonion — Super fast, client side search for Hugo.io with Fusejs.io
|
|
||||||
based on https://gist.github.com/cmod/5410eae147e4318164258742dd053993
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
|
|
||||||
if (typeof variable !== 'undefined') {
|
|
||||||
console.log('askolonion.js already loaded');
|
|
||||||
} else {
|
|
||||||
askolonion = function(){
|
|
||||||
var search__form = document.getElementById('search__form'); // search form
|
|
||||||
var search__input = document.getElementById('search__input'); // input box for search
|
|
||||||
var search__button = document.getElementById('search__button'); // form submit button
|
|
||||||
var search__results = document.getElementById('search__results'); // targets the <ul>
|
|
||||||
var fuse; // holds our search engine
|
|
||||||
var search__focus = false; // check to true to make visible by default
|
|
||||||
var results_available = false; // did we get any search results?
|
|
||||||
var first_run = true; // allow us to delay loading json data unless search activated
|
|
||||||
var first = search__results.firstChild; // first child of search list
|
|
||||||
var last = search__results.lastChild; // last child of search list
|
|
||||||
|
|
||||||
|
|
||||||
search__form.classList.remove('noscript'); // JavaScript is active
|
|
||||||
search__form.setAttribute('data-focus', search__focus);
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
The main keyboard event listener running the show
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
// console.log(event); // DEBUG
|
|
||||||
// Ctrl + / to show or hide Search
|
|
||||||
// if (event.which === 191) { // Key: /
|
|
||||||
if (event.ctrlKey && event.which === 191) { // Key: Ctrl + /
|
|
||||||
search_toggle_focus(e); // toggle visibility of search box
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
The main keyboard event listener running the show
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__form.addEventListener('keydown', function(e) {
|
|
||||||
// Allow ESC (27) to close search box
|
|
||||||
if (e.keyCode == 27) {
|
|
||||||
search__focus = true; // make sure toggle removes focus
|
|
||||||
search_toggle_focus(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOWN (40) arrow
|
|
||||||
if (e.keyCode == 40) {
|
|
||||||
if (results_available) {
|
|
||||||
e.preventDefault(); // stop window from scrolling
|
|
||||||
if ( document.activeElement == search__input) { first.focus(); } // if the currently focused element is the main input --> focus the first <li>
|
|
||||||
else if ( document.activeElement == last ) { first.focus(); } // if we're at the bottom, loop to the start
|
|
||||||
// else if ( document.activeElement == last ) { last.focus(); } // if we're at the bottom, stay there
|
|
||||||
else { document.activeElement.parentElement.nextSibling.firstElementChild.focus(); } // otherwise select the next search result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UP (38) arrow
|
|
||||||
if (e.keyCode == 38) {
|
|
||||||
if (results_available) {
|
|
||||||
e.preventDefault(); // stop window from scrolling
|
|
||||||
if ( document.activeElement == search__input) { search__input.focus(); } // If we're in the input box, do nothing
|
|
||||||
else if ( document.activeElement == first) { search__input.focus(); } // If we're at the first item, go to input box
|
|
||||||
else { document.activeElement.parentElement.previousSibling.firstElementChild.focus(); } // Otherwise, select the search result above the current active one
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Enter (13) to move to the first result
|
|
||||||
if (e.keyCode == 13) {
|
|
||||||
e.preventDefault(); // stop form from being submitted
|
|
||||||
if (results_available && document.activeElement == search__input) {
|
|
||||||
first.focus();
|
|
||||||
} else {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Backspace (8) to switch back to the search input
|
|
||||||
if (e.keyCode == 8) {
|
|
||||||
if (document.activeElement != search__input) {
|
|
||||||
e.preventDefault(); // stop browser from going back in history
|
|
||||||
search__input.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Load our json data and builds fuse.js search index
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__form.addEventListener('focusin', function(e) {
|
|
||||||
search_init(); // try to load the search index
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Make button toggle focus
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__button.addEventListener('mousedown', function(e) {
|
|
||||||
search_toggle_focus(e);
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Remove focus on blur
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
search__form.addEventListener('focusout', function(e) {
|
|
||||||
if (e.relatedTarget === null) {
|
|
||||||
search_toggle_focus(e);
|
|
||||||
}
|
|
||||||
else if (e.relatedTarget.type === 'submit') {
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Toggle focus UI of form
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function search_toggle_focus(e) {
|
|
||||||
// order of operations is very important to keep focus where it should stay
|
|
||||||
if (!search__focus) {
|
|
||||||
// search__button.value = '⨯';
|
|
||||||
search__form.setAttribute('data-focus', true);
|
|
||||||
search__input.focus(); // move focus to search box
|
|
||||||
search__focus = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// search__button.value = '⌕';
|
|
||||||
search__form.setAttribute('data-focus', false);
|
|
||||||
document.activeElement.blur(); // remove focus from search box
|
|
||||||
search__focus = false;
|
|
||||||
}
|
|
||||||
// console.log(search__focus,e); // DEBUG
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Fetch some json without jquery
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function fetch_JSON(path, callback) {
|
|
||||||
var httpRequest = new XMLHttpRequest();
|
|
||||||
httpRequest.onreadystatechange = function() {
|
|
||||||
if (httpRequest.readyState === 4) {
|
|
||||||
if (httpRequest.status === 200) {
|
|
||||||
var data = JSON.parse(httpRequest.responseText);
|
|
||||||
if (callback) callback(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
httpRequest.open('GET', path);
|
|
||||||
httpRequest.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Load script
|
|
||||||
based on https://stackoverflow.com/a/55451823
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function load_script(url) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
let script = document.createElement("script");
|
|
||||||
script.onerror = reject;
|
|
||||||
script.onload = resolve;
|
|
||||||
if (document.currentScript) {
|
|
||||||
document.currentScript.parentNode.insertBefore(script, document.currentScript);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
document.head.appendChild(script)
|
|
||||||
}
|
|
||||||
script.src = url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Load our search index, only executed once
|
|
||||||
on first call of search box (Ctrl + /)
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function search_init() {
|
|
||||||
if (first_run) {
|
|
||||||
load_script(window.location.origin + '/scripts/askolonion/fuse.basic.min.js').then(() => {
|
|
||||||
search__input.value = ""; // reset default value
|
|
||||||
first_run = false; // let's never do this again
|
|
||||||
fetch_JSON(search__form.getAttribute('data-language-prefix') + '/index.json', function(data){
|
|
||||||
var options = { // fuse.js options; check fuse.js website for details
|
|
||||||
shouldSort: true,
|
|
||||||
location: 0,
|
|
||||||
distance: 100,
|
|
||||||
threshold: 0.4,
|
|
||||||
minMatchCharLength: 2,
|
|
||||||
keys: [
|
|
||||||
'permalink',
|
|
||||||
'title',
|
|
||||||
'date',
|
|
||||||
'summary',
|
|
||||||
'section',
|
|
||||||
'categories',
|
|
||||||
'tags'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
fuse = new Fuse(data, options); // build the index from the json file
|
|
||||||
|
|
||||||
search__input.addEventListener('keyup', function(e) { // execute search as each character is typed
|
|
||||||
search_exec(this.value);
|
|
||||||
});
|
|
||||||
// console.log("index.json loaded"); // DEBUG
|
|
||||||
});
|
|
||||||
}).catch((error) => { console.log('askolonion failed to load: ' + error); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
Using the index we loaded on Ctrl + /, run
|
|
||||||
a search query (for "term") every time a letter is typed
|
|
||||||
in the search box
|
|
||||||
--------------------------------------------------------------*/
|
|
||||||
function search_exec(term) {
|
|
||||||
let results = fuse.search(term); // the actual query being run using fuse.js
|
|
||||||
let search_items = ''; // our results bucket
|
|
||||||
|
|
||||||
if (results.length === 0) { // no results based on what was typed into the input box
|
|
||||||
results_available = false;
|
|
||||||
search_items = '';
|
|
||||||
} else { // build our html
|
|
||||||
for (let item in results.slice(0,50)) { // only show first 5 results
|
|
||||||
search_items = search_items +
|
|
||||||
`<article><a href="${results[item].item.permalink}" tabindex="0">
|
|
||||||
<time class="time">${results[item].item.date}</time>
|
|
||||||
<h3 class="title">${results[item].item.title}</h3>
|
|
||||||
<p class="summary">${results[item].item.summary}</p>
|
|
||||||
<span class="section">${results[item].item.section}</span>
|
|
||||||
<span class="categories">${results[item].item.categories.join(', ')}</span>
|
|
||||||
<span class="tags">${results[item].item.tags.join(', ')}</span>
|
|
||||||
</article>`;
|
|
||||||
}
|
|
||||||
results_available = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
search__results.innerHTML = search_items;
|
|
||||||
if (results.length > 0) {
|
|
||||||
first = search__results.firstChild.firstElementChild; // first result container — used for checking against keyboard up/down location
|
|
||||||
last = search__results.lastChild.firstElementChild; // last result container — used for checking against keyboard up/down location
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
}
|
|
9
static/scripts/fixedsearch/fuse.basic.min.js
vendored
9
static/scripts/fixedsearch/fuse.basic.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user