Newer
Older
'use strict';
{{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }}
{{ $searchData := resources.Get "search-data.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify }}
(function() {
const input = document.querySelector('#gdoc-search-input');
const results = document.querySelector('#gdoc-search-results');
let showParent = {{ if .Site.Params.GeekdocSearchShowParent }}true{{ else }}false{{ end }}
if (input) {
input.addEventListener('focus', init);
input.addEventListener('keyup', search);
}
function init() {
input.removeEventListener('focus', init); // init once
loadScript('{{ index .Site.Data.assets "js/groupBy.min.js" | relURL }}');
loadScript('{{ index .Site.Data.assets "js/flexsearch.min.js" | relURL }}', function() {
const indexCfgDefaults = {
tokenize: 'forward'
}
const indexCfg = {{ with .Scratch.Get "geekdocSearchConfig" }}{{ . | jsonify }}{{ else }}indexCfgDefaults{{ end }};
const dataUrl = '{{ $searchData.RelPermalink }}'
indexCfg.document = {
key: 'id',
index: ['title', 'content'],
store: ['title', 'href', 'parent'],
};
const index = new FlexSearch.Document(indexCfg);
window.geekdocSearchIndex = index;
getJson(dataUrl, function(data) {
data.forEach(obj => {
window.geekdocSearchIndex.add(obj);
});
});
});
}
function search() {
const searchCfg = {
enrich: true,
limit: 10
};
while (results.firstChild) {
results.removeChild(results.firstChild);
}
if (!input.value) {
return results.classList.remove('has-hits');
let searchHits = flattenHits(window.geekdocSearchIndex.search(input.value, searchCfg));
return results.classList.remove('has-hits');
results.classList.add('has-hits');
if (showParent === true) {
searchHits = groupBy(searchHits, hit => hit.parent);
}
const items = [];
if (showParent === true) {
for (const section in searchHits) {
const item = document.createElement('li'),
title = item.appendChild(document.createElement('span')),
subList = item.appendChild(document.createElement('ul'));
title.textContent = section;
createLinks(searchHits[section], subList);
items.push(item);
}
} else {
const item = document.createElement('li'),
title = item.appendChild(document.createElement('span')),
subList = item.appendChild(document.createElement('ul'));
title.textContent = 'Results';
createLinks(searchHits, subList);
items.push(item);
}
items.forEach(item => {
results.appendChild(item);
})
}
/**
* Creates links to given fields and either returns them in an array or attaches them to a target element
* @param {Object} fields Page to which the link should point to
* @param {HTMLElement} target Element to which the links should be attatched
* @returns {Array} If target is not specified, returns an array of built links
*/
function createLinks(pages, target) {
const items = [];
for (const page of pages) {
const item = document.createElement("li"),
entry = item.appendChild(document.createElement("span")),
a = entry.appendChild(document.createElement("a"));
entry.classList.add('flex')
a.href = page.href;
a.textContent = page.title;
a.classList.add('gdoc-search__entry')
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
if (target) {
target.appendChild(item);
continue
}
items.push(item);
}
return items;
}
function fetchErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
function getJson(src, callback) {
fetch(src)
.then(fetchErrors)
.then(response => response.json())
.then(json => callback(json))
.catch(function(error) {
console.log(error);
});
}
function flattenHits(results) {
const items = [];
const map = new Map();
for (const field of results) {
for (const page of field.result) {
if(!map.has(page.doc.href)){
map.set(page.doc.href, true);
items.push(page.doc);
}
}
}
return items
}
function loadScript(src, callback) {
let script = document.createElement('script');
script.defer = true;
script.async = false;
script.src = src;
script.onload = callback;
document.body.appendChild(script);
}
})();