Hide snippet until matching result returns

In my code, I am returning the text snippet. But I want to hide it until the user starts searching and there is a match. It’s visible as soon as you click the search box.

Right now, the snippet is visible on the search page.

Using Instant Search.js

  instantsearch.widgets.hits({
    container: "#hits",
    templates: {
      item(hit) {
        const apiTitle = (endpoint) => {
          const [method, pathname] = endpoint.split(" ").map((v) => v.trim());
          return `<span class="api-method-${method.toLowerCase()} mr-4">${method}</span> <span>${pathname}</span>`;
        };
        return `
          <div>
            <h2 class="hit-name text-sm font-semibold text-n-black leading-8">
             <a href="${hit.url}"> ${
          hit.apiMethod ? apiTitle(hit.endpoint) : `<span>${hit.title}</span> `
        } 
            </h2>
            <p class="hit-description text-n-gray-dark text-base">
            ${instantsearch.highlight({ attribute: "description", hit })}
            </p>
            <p class="hit-text text-n-gray text-sm underline">
            ${instantsearch.snippet({ attribute: "text", hit })} 
            </p>
            </a>
          </div>
        `;
      },
    },
  }),

I needed this as well. I wrote a bit of javascript that does the trick. First, you should set your snippet to display:none in the template. Then have javascript run after every search to see if the snippet div contains tags that are highlighting something, if it does you can display:block otherwise display:none. I found this only works when it’s ran on a debounce. Here’s my implementation:

This uses jQuery.

// Debounce function
function alg_debounce(func, wait, immediate) {
	var timeout;
	return function() {
		var context = this, args = arguments;
		var later = function() {
			timeout = null;
			if (!immediate) func.apply(context, args);
		};
		var callNow = immediate && !timeout;
		clearTimeout(timeout);
		timeout = setTimeout(later, wait);
		if (callNow) func.apply(context, args);
	};
};

const snippet_class = ".hit-text";
const snippet_tag = "strong";

// find all snippet divs on the page, if there are no results then hide the snippet.
const hide_unused_snippets = alg_debounce(() => {
    $(snippet_class).each(function(i, element) {
        if ($(element).find(snippet_tag).length > 0) {
            $(element).css('display', 'block');
        } else {
            $(element).css('display', 'none');
        }
    });
}, 250, false);

const search = instantsearch({
    indexName: "My Index",
    searchClient,
    onStateChange: (event) => { // the magic is here
        // runs every time a search is performed
        hide_unused_snippets();

        // trigger the search for the rest of the components
        event.setUiState(event.uiState);
    }
});

2 Likes