var lunrIndex var lunrResult var pagesIndex var bigramTokeniser = function (obj, metadata) { if (obj == null || obj == undefined) { return [] } if (Array.isArray(obj)) { return obj.map(function (t) { return new lunr.Token( lunr.utils.asString(t).toLowerCase(), lunr.utils.clone(metadata) ) }) } var str = obj.toString().trim().toLowerCase(), tokens = [] for(var i = 0; i <= str.length - 2; i++) { var tokenMetadata = lunr.utils.clone(metadata) || {} tokenMetadata["position"] = [i, i + 2] tokenMetadata["index"] = tokens.length tokens.push( new lunr.Token ( str.slice(i, i + 2), tokenMetadata ) ) } return tokens } var queryNgramSeparator = function (query) { var str = query.toString().trim().toLowerCase(), tokens = [] for(var i = 0; i <= str.length - 2; i++) { tokens.push(str.slice(i, i + 2)) } return tokens.join(' ') } /** * Preparation for using lunr.js */ function initLunr () { $.getJSON('index.json').done(function (index) { pagesIndex = index lunrIndex = lunr(function () { this.tokenizer = bigramTokeniser this.pipeline.reset() this.ref('ref') this.field('title', { boost: 10 }) this.field('body') this.metadataWhitelist = ['position'] for (var page of pagesIndex) { this.add(page) } }) }).fail(function (jqxhr, textStatus, error) { var err = textStatus + ', ' + error console.error('Error getting Hugo index flie:', err) }) } /** * Searching pages using lunr * @param {String} query Query string for searching * @return {Object[]} Array of search results */ function search (query) { lunrResult = lunrIndex.search(queryNgramSeparator(query)) return lunrResult.map(function (result) { return pagesIndex.filter(function (page) { return page.ref === result.ref })[0] }) } /** * Setup UI for Search */ function initUI () { // Clear query when clear icon is clicked $('#searchBoxIcon').click(function () { $('#searchBoxInput').val('') $('#searchBoxInput').trigger('keyup') }) // Event when chenging query $('#searchBoxInput').keyup(function () { var $searchResults = $('#searchResults') var query = $(this).val() // Icon switching if (query.length) { $('#searchBoxIcon').attr('src', '/img/clear.png') $('#searchBoxIcon').css('cursor', 'pointer') } else { $('#searchBoxIcon').attr('src', '/img/search.png') $('#searchBoxIcon').css('cursor', 'default') } // Only trigger a search when 2 chars. at least have been provided if (query.length < 2) { $searchResults.hide() return } // Display search results renderResults(search(query)) $searchResults.show() }) // Emit keyup event for when the query is already setted with browser back etc. $('#searchBoxInput').trigger('keyup') } /** * Rendering search results * @param {Object[]} results Array of search results */ function renderResults (results) { var $searchResults = $('#searchResults') var query = $('#searchBoxInput').val() var BODY_LENGTH = 100 var MAX_PAGES = 10 // Clear search result $searchResults.empty() // Show message when results is empty if (!results.length) { $searchResults.append('