My products have a “tags” field I use to categorize them. Each category has a dedicated “list” page at http://mysite.com/tags/[tag_name] where [tag_name] is the name of the tag. How can I show these tag pages in my autocomplete?
You can extend the Swiftype jQuery autocomplete plugin using the following code. An explanation of what it’s doing is below:
// Given a collection of Swiftype results (results), return a
// collection of count hashes like:
// [{tag: "jacket", count: "5", url:"http://mysite.com/tags/jacket"}, ... ]
//
// Requires Underscore.js.
//
var mostPopular = function(results, attribute) {
var allTags = [];
var base_url = "http://MYSITE.com/tag/";
jQuery.each(results, function(idx, result) {
allTags = allTags.concat(result[attribute]);
});
// Removes undefined, null, "" etc...
allTags = allTags.filter(function(e){return e});
var counts = {};
for (var i = 0, j = allTags.length; i < j; i++) {
counts[allTags[i]] = (counts[allTags[i]] || 0) + 1;
}
// Customize this to how you URLify tags.
var urlify = function(tag) {
return tag.toLowerCase().replace(/ /g,'-');
};
counts = jQuery.map(counts, function(count, tag) {
return {tag: tag, count: count, url: base_url + urlify(tag)};
});
return _.sortBy(counts, function(c) {
return c.count;
}).reverse();
};
// Returns the highlighted title if it exists. Falls back to the
// title field if not.
var getTitle = function(item) {
return item.highlight['title'] || item['title'];
}
var customResultRenderFunction = function(ctx, results) {
var $list = ctx.list,
config = ctx.config;
// Change this if using the Swiftype API.
var document_type = "page";
var field_name = "tags";
var maximum_results = 5;
var maximum_categories = 3;
var categories = mostPopular(results[document_type], field_name);
results = results[document_type];
categories = categories.slice(0, maximum_categories);
results = results.slice(0, maximum_results);
jQuery('<li class="heading">Categories</li>').appendTo($list);
jQuery.each(categories, function(idx, category) {
ctx.registerResult(jQuery('<li class="result">' + category.tag + '</li>').appendTo($list), category);
});
jQuery('<li class="heading">Products</li>').appendTo($list);
jQuery.each(results, function(idx, item) {
ctx.registerResult(jQuery('<li class="result">' + getTitle(item) + '</li>').appendTo($list), item);
});
};
jQuery(handle).swiftype({
resultRenderFunction: customResultRenderFunction,
engineKey: "YOUR_KEY"
});
How does this work?
First, tell the autocomplete plugin to render results using a custom function customResultRenderFunction
jQuery(handle).swiftype({
resultRenderFunction: customResultRenderFunction,
engineKey: "YOUR_KEY"
});
customResultRenderFunction first takes a list of records and passes them to the mostPopular function. mostPopular returns an array of results and an attribute name and converts them to a counted array, ordered by count, formatted like:
[{tag: "jacket", count: "5", url:"http://mysite.com/tags/jacket"}, ...
customResultRenderFunction then limits the categories and results using the maximum_categories and maximum_results variables and prints them according to the code below:
jQuery('<li class="heading">Categories</li>').appendTo($list);
jQuery.each(categories, function(idx, category) {
ctx.registerResult(jQuery('<li class="result">' + category.tag + '</li>').appendTo($list), category);
});
The actual results are then rendered in their own section.
jQuery('<li class="heading">Products</li>').appendTo($list);
jQuery.each(results, function(idx, item) {
ctx.registerResult(jQuery('<li class="result">' + getTitle(item) + '</li>').appendTo($list), item);
});
It’s likely you’ll want to change the following variables in customResultRenderFunction:
var document_type = "page";
var field_name = "tags";
var maximum_results = 5;
var maximum_categories = 3;
You’ll probably also want to change these items in mostPopular:
var base_url = "http://MYSITE.com/tag/";
// Customize this to how you URLify tags.
var urlify = function(tag) {
return tag.toLowerCase().replace(/ /g,'-');
};