/************************************************* * Academic * https://github.com/gcushen/hugo-academic * * In-built Fuse based search algorithm. **************************************************/ /* --------------------------------------------------------------------------- * Configuration. * --------------------------------------------------------------------------- */ // Configure Fuse. let fuseOptions = { shouldSort: true, includeMatches: true, tokenize: true, threshold: search_config.threshold, // Set to ~0.3 for parsing diacritics and CJK languages. location: 0, distance: 100, maxPatternLength: 32, minMatchCharLength: search_config.minLength, // Set to 1 for parsing CJK languages. keys: [ {name:'title', weight:0.99}, /* 1.0 doesn't work o_O */ {name:'summary', weight:0.6}, {name:'authors', weight:0.5}, {name:'content', weight:0.2}, {name:'tags', weight:0.5}, {name:'categories', weight:0.5} ] }; // Configure summary. let summaryLength = 60; /* --------------------------------------------------------------------------- * Functions. * --------------------------------------------------------------------------- */ // Get query from URI. function getSearchQuery(name) { return decodeURIComponent((location.search.split(name + '=')[1] || '').split('&')[0]).replace(/\+/g, ' '); } // Set query in URI without reloading the page. function updateURL(url) { if (history.replaceState) { window.history.replaceState({path:url}, '', url); } } // Pre-process new search query. function initSearch(force, fuse) { let query = document.querySelector("#search-query").value; // If query deleted, clear results. if (query.length < 1) { document.querySelector('#search-hits').innerHTML = ""; } // Check for timer event (enter key not pressed) and query less than minimum length required. if (!force && query.length < fuseOptions.minMatchCharLength) return; // Do search. document.querySelector('#search-hits').innerHTML = ""; searchAcademic(query, fuse); let newURL = window.location.protocol + "//" + window.location.host + window.location.pathname + '?q=' + encodeURIComponent(query) + window.location.hash; updateURL(newURL); } // Perform search. function searchAcademic(query, fuse) { let results = fuse.search(query); // console.log({"results": results}); if (results.length > 0) { document.querySelector('#search-hits').insertAdjacentHTML('beforeend', '

' + results.length + ' ' + i18n.results + '

'); parseResults(query, results); } else { document.querySelector('#search-hits').insertAdjacentHTML('beforeend', '
' + i18n.no_results + '
'); } } // Parse search results. function parseResults(query, results) { console.log(results); results.forEach(function (value, key) { let content_key = value.item.section; let content = ""; let snippet = ""; let snippetHighlights = []; // Show abstract in results for content types where the abstract is often the primary content. if (["publication", "talk"].includes(content_key)) { content = value.item.summary; } else { content = value.item.content; } if ( fuseOptions.tokenize ) { snippetHighlights.push(query); } else { value.matches.forEach(function(matchValue, matchKey) { if (matchValue.key == "content") { let start = (matchValue.indices[0][0]-summaryLength>0) ? matchValue.indices[0][0]-summaryLength : 0; let end = (matchValue.indices[0][1]+summaryLength response.json()).then(function (search_index) { let fuse = new Fuse(search_index, fuseOptions); // On page load, check for search query in URL. if (query = getSearchQuery('q')) { document.querySelector("body").classList.add('searching'); document.querySelector("#search-query").value = query; document.querySelector("#search-query").focus(); initSearch(true, fuse); } // On search box key up, process query. document.querySelector('#search-query').addEventListener('keyup', function (e) { clearTimeout(this.dataset.searchTimer); if (e.keyCode == 13) { initSearch(true, fuse); } else { this.dataset.searchTimer = setTimeout(function () { initSearch(false, fuse); }, 250); } }); }); }