Skip to content

Instantly share code, notes, and snippets.

@naile
Created February 3, 2019 20:55
Show Gist options
  • Save naile/47e3e8aa62c6d1410d7b51b80f13bcfe to your computer and use it in GitHub Desktop.
Save naile/47e3e8aa62c6d1410d7b51b80f13bcfe to your computer and use it in GitHub Desktop.

Revisions

  1. naile created this gist Feb 3, 2019.
    115 changes: 115 additions & 0 deletions search.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,115 @@
    //vanilla js version of https://gist.github.com/sebz/efddfc8fdcb6b480f567

    var lunrIndex,
    $results,
    pagesIndex;

    // Initialize lunrjs using our generated index file
    function initLunr() {
    var request = new XMLHttpRequest();
    request.open('GET', 'js/lunr/index.json', true);

    request.onload = function () {
    if (request.status >= 200 && request.status < 400) {

    pagesIndex = JSON.parse(request.responseText);
    console.log("index:", pagesIndex);

    // Set up lunrjs by declaring the fields we use
    // Also provide their boost level for the ranking
    lunrIndex = lunr(function () {
    this.field("title", {
    boost: 10
    });
    this.field("tags", {
    boost: 5
    });
    this.field("content");

    // ref is the result item identifier (I chose the page URL)
    this.ref("href");
    this.add({ field: "test", text: 'hello' });
    for (var i = 0; i < pagesIndex.length; ++i) {
    this.add(pagesIndex[i]);
    }
    });
    } else {
    var err = textStatus + ", " + error;
    console.error("Error getting Hugo index flie:", err);
    }
    };

    request.send();
    }

    // Nothing crazy here, just hook up a event handler on the input field
    function initUI() {
    $results = document.getElementById("results");
    $search = document.getElementById("search");
    $search.onkeyup = function () {
    while ($results.firstChild) {
    $results.removeChild($results.firstChild);
    }

    // Only trigger a search when 2 chars. at least have been provided
    var query = $search.value;
    if (query.length < 2) {
    return;
    }

    //add some fuzzyness to the string matching to help with spelling mistakes.
    var fuzzLength = Math.round(Math.min(Math.max(query.length / 4, 1), 3));
    var fuzzyQuery = query + '~' + fuzzLength;

    var results = search(fuzzyQuery);
    renderResults(results);
    };
    }

    /**
    * Trigger a search in lunr and transform the result
    *
    * @param {String} query
    * @return {Array} results
    */
    function search(query) {
    // Find the item in our index corresponding to the lunr one to have more info
    // Lunr result:
    // {ref: "/section/page1", score: 0.2725657778206127}
    // Our result:
    // {title:"Page1", href:"/section/page1", ...}
    return lunrIndex.search(query).map(function (result) {
    return pagesIndex.filter(function (page) {
    return page.href === result.ref;
    })[0];
    });
    }

    /**
    * Display the 10 first results
    *
    * @param {Array} results to display
    */
    function renderResults(results) {
    if (!results.length) {
    return;
    }

    // Only show the ten first results
    $results = document.getElementById("results");
    results.slice(0, 10).forEach(function (result) {
    var li = document.createElement('li');
    var ahref = document.createElement('a');
    ahref.href = result.href;
    ahref.text = "» " + result.title;
    li.append(ahref);
    $results.appendChild(li);
    });
    }

    // Let's get started
    initLunr();

    document.addEventListener("DOMContentLoaded", function () {
    initUI();
    })