Get Our Newsletter

Internet
Science
with Kirk M.
(@saricden)

Jekyll Spotlight Search

If you'd prefer, there is a video version of this tutorial available:

In this tutorial, we’ll be looking at how to setup a “spotlight search” using plain ol’ JavaScript that integrates with a JekyllRB blog.

By spotlight search, I simply mean a search bar that as you type, results appear with each keystroke / change to the input.

This tutorial assumes you’re familiar with the basics of JekyllRB, and JavaScript (we’ll be using ES5 in this article to keep older browsers happy).

Let’s get into it.

Step 1: Create a JSON feed

In order to have data for our search to read, we’re going to be creating a JSON file that automatically updates as your Jekyll blog does.

Create a new file in the _includes directory, and name it post-feed.html. We’re going to format this as JSON, then inject the text into a <script> tag that can be read on every page we want to show our search on.

[
  {% for post in site.tags.post %}
    {
      "title": "{{ post.title }}",
      "snippet": "{{ post.content | truncatewords: 25 | strip_html }}",
      "href": "{{ post.permalink }}"
    }{% if forloop.last == false %},{% endif %}
  {% endfor %}
]

Note these specifics pertain to my website, you’ll likely want to modify the loop above such that it’s iterating over the posts you want to display in your search.

Step 2: Read your JSON into your JavaScript

Next, we want to take our JSON object, output it somewhere in our HTML, then access it with our JavaScript.

To output the JSON I added the following to the bottom of my default layout:

<script type="application/json" id="search-data">{% include post-feed.html %}</script>

Then, in my JavaScript file, I load in the output JSON like so:

var searchData = JSON.parse(document.getElementById('search-data').textContent);

Step 3: Create Some Search Elements

Now we’re going to create the HTML elements that will house our search. The ones on my own site are a bit fancier, and this is certainly an area to get creative with, but for the sake of our tutorial we’re going to keep ours pretty simple.

<input type="search" id="search-bar" placeholder="Type here to search." />

<div id="search-results"></div>

You’ll definitely want to style them up and make them pretty, but this is the skeleton of our search ready to go!

Step 4: Write a Search Function

You’re almost there, keep going!

In this step, we’ll put everything we have so far together into the function that powers our search.

// First, parse the JSON we've thrown into the DOM
var searchData = JSON.parse(document.getElementById('search-data').textContent);

// Create a reference to our search results
var searchResultsList = document.getElementById('search-results');

// And one for our search input
var searchInput = document.getElementById('search-bar');

var updateSearchResults = function(e) {
  // Make the query case-insensitive
  var q = e.target.value.toLowerCase();

  // Make sure it isn't empty
  if (q.trim() !== '') {

    // Empty the search results DOM element
    searchResultsList.innerHTML = "";

    // Loop over all the items in our JSON blob
    for (let i in searchData) {
      var searchItem = searchData[i];

      // Check if the title or snippet includes our query string
      if (searchItem.title.toLowerCase().includes(q) || searchItem.snippet.toLowerCase().includes(q)) {

        // If it does, append a link to our results element
        var searchLink = document.createElement('a');
        var searchContent = document.createTextNode(searchItem.title);

        searchLink.setAttribute('href', searchItem.href);
        searchLink.appendChild(searchContent);
        searchResultsList.appendChild(searchLink);
      }
    }
  }
};

// Finally, bind our new function to the search input element
searchInput.addEventListener('keyup', updateSearchResults);

Now, it should be noted that without a doubt, there are more optimal solutions to this. But for the sake of simplicity, I’m going with this relatively straight-forward solution.

And with that, we should be done. Fire up your blog with jekyll serve if you haven’t already, and take it for a spin!

As always, happy hacking!

Love Kirk M. (@saricden)


Header Image courtesy of Mick Haupt via Unsplash

Start typing to find blog posts...