Customize Autocomplete modern template debounce and stallThreshold values - WebDevStudios/wp-search-with-algolia GitHub Wiki
To customize the Algolia Autocomplete (search dropdown) debounce and stallThreshold values, it is necessary to add some custom code to the search template. This page outlines the steps necessary to create a WordPress plugin to do this.
Note: This is only applicable when using the Modern Autocomplete template (1.19.x). When using the Autocomplete Classic template (0.38.1) the steps outlined in this file are not necessary.
First, create a new folder in your site's plugins directory: wp-search-with-algolia-modern-autocomplete-debounce
Next, create a plugin file in the above directory: wp-search-with-algolia-modern-autocomplete-debounce.php
Add the following contents to the plugin file:
<?php
/**
* Plugin Name: Algolia Modern Autocomplete Debounce
* Description: Customizes the Autocomplete debounce value for WP Search with Algolia when using the modern template.
*/
// Serve our copy of the modern autocomplete template.
add_filter( 'algolia_custom_template_location', function ( $location, $file ) {
if ( 'autocomplete-modern.php' === $file ) {
return __DIR__ . '/templates/autocomplete-modern.php';
}
return $location;
}, 10, 2 );
// Expose a debounce value (ms) to the front end as algolia.autocomplete.debounce.
add_filter( 'algolia_config', function ( $config ) {
$debounce = Algolia_Plugin_Factory::create()->get_settings()->get_autocomplete_debounce(); // honors the admin setting + 'algolia_autocomplete_debounce' filter
$config['autocomplete']['debounce'] = (int) apply_filters( 'my_algolia_modern_debounce', $debounce );
// Time (ms) before a pending request is considered "stalled". Autocomplete's default is 300.
$config['autocomplete']['stall_threshold'] = (int) apply_filters( 'my_algolia_modern_stall_threshold', 300 );
return $config;
} );
Now, create a templates folder in your wp-search-with-algolia-modern-autocomplete-debounce directory.
Copy the plugin's templates/autocomplete-modern.php into your plugin as-is. Then add a debounce helper and change getSources() in the config object (around the bottom of the file):
Add near the top, after searchClient is defined:
// START CUSTOM DEBOUNCE 1/2.
function debouncePromise(fn, time) {
let timerId;
return function (...args) {
if (timerId) {
clearTimeout(timerId);
}
return new Promise((resolve) => {
timerId = setTimeout(() => resolve(fn(...args)), time);
});
};
}
const debouncedSources = debouncePromise((query) => get_sources(query), algolia.autocomplete.debounce || 0);
// Optional: Uncomment the next two lines to confirm the debounce value being used.
console.log('algolia.autocomplete.debounce');
console.log(algolia.autocomplete.debounce);
// Optional: Uncomment the next two lines to confirm the stall_threshold value being used.
console.log('algolia.autocomplete.stall_threshold');
console.log(algolia.autocomplete.stall_threshold);
// END CUSTOM DEBOUNCE 1/2.
Then in config:
stallThreshold: algolia.autocomplete.stall_threshold ?? 300,
getSources({query}) {
if (!query) {
return [];
}
return debouncedSources(query);
},
Here is a full example of the customized autocomplete-modern.php template as of v2.13.0 of the plugin:
<?php
/**
* WP Search With Algolia autocomplete template file.
*
* @author WebDevStudios <[email protected]>
*
* @since 2.13.0
* @version 2.13.0
* @package WebDevStudios\WPSWA
*/
?>
<script type="text/javascript">
window.addEventListener('load', function () {
const {autocomplete, getAlgoliaResults} = window['@algolia/autocomplete-js'];
const searchClient = algoliasearch(algolia.application_id, algolia.search_api_key);
// START CUSTOM DEBOUNCE 1/2.
function debouncePromise(fn, time) {
let timerId;
return function (...args) {
if (timerId) {
clearTimeout(timerId);
}
return new Promise((resolve) => {
timerId = setTimeout(() => resolve(fn(...args)), time);
});
};
}
const debouncedSources = debouncePromise((query) => get_sources(query), algolia.autocomplete.debounce || 0);
// Optional: Uncomment the next two lines to confirm the debounce value being used.
// console.log('algolia.autocomplete.debounce');
// console.log(algolia.autocomplete.debounce);
// Optional: Uncomment the next two lines to confirm the stall_threshold value being used.
// console.log('algolia.autocomplete.stall_threshold');
// console.log(algolia.autocomplete.stall_threshold);
// END CUSTOM DEBOUNCE 1/2.
function get_sources(query) {
let sources = [];
algolia.autocomplete.sources.forEach(function (config) {
sources.push(
{
sourceId: config.index_id,
getItems() {
return getAlgoliaResults({
searchClient,
queries: [
{
indexName: config.index_name,
query,
params : {
hitsPerPage : config['max_suggestions'],
attributesToHighlight: ['post_title', 'content'],
},
},
],
});
},
templates: {
header: function ({html}) {
return html`
<div class="autocomplete-header">
<div class="autocomplete-header-title">${config['label']}</div>
<div class="clear"></div>
</div>`;
},
item({item, components, html}) {
let value = '';
switch (config['tmpl_suggestion']) {
case 'autocomplete-post-suggestion':
let img = '';
if (item.images && typeof item.images.thumbnail !== 'undefined') {
img = html`<img class="suggestion-post-thumbnail" src="${item.images.thumbnail.url}" alt="${item.post_title}" />`
}
value = html`<div><a class="suggestion-link" href="${item.permalink}" title="${item.post_title}">
${img}
<div class="suggestion-post-attributes">
<span class="suggestion-post-title">
${components.Highlight({
hit : item,
attribute: ['post_title'],
tagName : 'em',
})}
</span>
<span class="suggestion-post-content">
${components.Snippet({
hit : item,
attribute: ['content'],
tagName : 'em',
})}
</span>
</div>
</a></div>`;
break;
case 'autocomplete-user-suggestion':
value = html`<div><a class="suggestion-link user-suggestion-link" href="${item.posts_url}" title="${item.display_name}">
<img class="suggestion-user-thumbnail" src="${item.avatar_url}}" alt="${item.display_name}" />
<span class="suggestion-post-title">
${components.Highlight({
hit : item,
attribute: ['display_name'],
tagName : 'em',
})}
</span>
</a></div>`;
break;
case 'autocomplete-term-suggestion':
value = html`<div><a class="suggestion-link" href="${item.permalink}" title="${item.name}">
<svg viewBox="0 0 21 21" width="21" height="21">
<svg width="21" height="21" viewBox="0 0 21 21">
<path
d="M4.662 8.72l-1.23 1.23c-.682.682-.68 1.792.004 2.477l5.135 5.135c.7.693 1.8.688 2.48.005l1.23-1.23 5.35-5.346c.31-.31.54-.92.51-1.36l-.32-4.29c-.09-1.09-1.05-2.06-2.15-2.14l-4.3-.33c-.43-.03-1.05.2-1.36.51l-.79.8-2.27 2.28-2.28 2.27zm9.826-.98c.69 0 1.25-.56 1.25-1.25s-.56-1.25-1.25-1.25-1.25.56-1.25 1.25.56 1.25 1.25 1.25z"
fill-rule="evenodd"></path>
</svg>
</svg>
<span class="suggestion-post-title">
${components.Highlight({
hit : item,
attribute: ['name'],
tagName : 'em',
})}
</span>
</a></div>`
break;
}
return value;
},
noResults({state, html}) {
return html`<div class="autocomplete-empty">
<?php esc_html_e( 'No results matched your query ', 'wp-search-with-algolia' ); ?>
<span class="empty-query">"${state.query}"</span>
</div>`
}
}
}
);
});
let last = sources.length - 1;
sources[last].templates.footer = function ({html}) {
return html`<div class="autocomplete-footer">
<div class="autocomplete-footer-branding">
<a href="#" class="algolia-powered-by-link" title="Algolia">
<svg width="150px" height="25px" viewBox="0 0 572 64">
<path fill="#36395A" d="M16 48.3c-3.4 0-6.3-.6-8.7-1.7A12.4 12.4 0 0 1 1.9 42C.6 40 0 38 0 35.4h6.5a6.7 6.7 0 0 0 3.9 6c1.4.7 3.3 1.1 5.6 1.1 2.2 0 4-.3 5.4-1a7 7 0 0 0 3-2.4 6 6 0 0 0 1-3.4c0-1.5-.6-2.8-1.9-3.7-1.3-1-3.3-1.6-5.9-1.8l-4-.4c-3.7-.3-6.6-1.4-8.8-3.4a10 10 0 0 1-3.3-7.9c0-2.4.6-4.6 1.8-6.4a12 12 0 0 1 5-4.3c2.2-1 4.7-1.6 7.5-1.6s5.5.5 7.6 1.6a12 12 0 0 1 5 4.4c1.2 1.8 1.8 4 1.8 6.7h-6.5a6.4 6.4 0 0 0-3.5-5.9c-1-.6-2.6-1-4.4-1s-3.2.3-4.4 1c-1.1.6-2 1.4-2.6 2.4-.5 1-.8 2-.8 3.1a5 5 0 0 0 1.5 3.6c1 1 2.6 1.7 4.7 1.9l4 .3c2.8.2 5.2.8 7.2 1.8 2.1 1 3.7 2.2 4.9 3.8a9.7 9.7 0 0 1 1.7 5.8c0 2.5-.7 4.7-2 6.6a13 13 0 0 1-5.6 4.4c-2.4 1-5.2 1.6-8.4 1.6Zm35.6 0c-2.6 0-4.8-.4-6.7-1.3a13 13 0 0 1-4.7-3.5 17.1 17.1 0 0 1-3.6-10.4v-1c0-2 .3-3.8 1-5.6a13 13 0 0 1 7.3-8.3 15 15 0 0 1 6.3-1.4A13.2 13.2 0 0 1 64 24.3c1 2.2 1.6 4.6 1.6 7.2V34H39.4v-4.3h21.8l-1.8 2.2c0-2-.3-3.7-.9-5.1a7.3 7.3 0 0 0-2.7-3.4c-1.2-.7-2.7-1.1-4.6-1.1s-3.4.4-4.7 1.3a8 8 0 0 0-2.9 3.6c-.6 1.5-.9 3.3-.9 5.4 0 2 .3 3.7 1 5.3a7.9 7.9 0 0 0 2.8 3.7c1.3.8 3 1.3 5 1.3s3.8-.5 5.1-1.3c1.3-1 2.1-2 2.4-3.2h6a11.8 11.8 0 0 1-7 8.7 16 16 0 0 1-6.4 1.2ZM80 48c-2.2 0-4-.3-5.7-1a8.4 8.4 0 0 1-3.7-3.3 9.7 9.7 0 0 1-1.3-5.2c0-2 .5-3.8 1.5-5.2a9 9 0 0 1 4.3-3.1c1.8-.7 4-1 6.7-1H89v4.1h-7.5c-2 0-3.4.5-4.4 1.4-1 1-1.6 2.1-1.6 3.6s.5 2.7 1.6 3.6c1 1 2.5 1.4 4.4 1.4 1.1 0 2.2-.2 3.2-.7 1-.4 1.9-1 2.6-2 .6-1 1-2.4 1-4.2l1.7 2.1c-.2 2-.7 3.8-1.5 5.2a9 9 0 0 1-3.4 3.3 12 12 0 0 1-5.3 1Zm9.5-.7v-8.8h-1v-10c0-1.8-.5-3.2-1.4-4.1-1-1-2.4-1.4-4.2-1.4a142.9 142.9 0 0 0-10.2.4v-5.6a74.8 74.8 0 0 1 8.6-.4c3 0 5.5.4 7.5 1.2s3.4 2 4.4 3.6c1 1.7 1.4 4 1.4 6.7v18.4h-5Zm12.9 0V17.8h5v12.3h-.2c0-4.2 1-7.4 2.8-9.5a11 11 0 0 1 8.3-3.1h1v5.6h-2a9 9 0 0 0-6.3 2.2c-1.5 1.5-2.2 3.6-2.2 6.4v15.6h-6.4Zm34.4 1a15 15 0 0 1-6.6-1.3c-1.9-.9-3.4-2-4.7-3.5a15.5 15.5 0 0 1-2.7-5c-.6-1.7-1-3.6-1-5.4v-1c0-2 .4-3.8 1-5.6a15 15 0 0 1 2.8-4.9c1.3-1.5 2.8-2.6 4.6-3.5a16.4 16.4 0 0 1 13.3.2c2 1 3.5 2.3 4.8 4a12 12 0 0 1 2 6H144c-.2-1.6-1-3-2.2-4.1a7.5 7.5 0 0 0-5.2-1.7 8 8 0 0 0-4.7 1.3 8 8 0 0 0-2.8 3.6 13.8 13.8 0 0 0 0 10.3c.6 1.5 1.5 2.7 2.8 3.6s2.8 1.3 4.8 1.3c1.5 0 2.7-.2 3.8-.8a7 7 0 0 0 2.6-2c.7-1 1-2 1.2-3.2h6.2a11 11 0 0 1-2 6.2 15.1 15.1 0 0 1-11.8 5.5Zm19.7-1v-40h6.4V31h-1.3c0-3 .4-5.5 1.1-7.6a9.7 9.7 0 0 1 3.5-4.8A9.9 9.9 0 0 1 172 17h.3c3.5 0 6 1.1 7.9 3.5 1.7 2.3 2.6 5.7 2.6 10v16.8h-6.4V29.6c0-2.1-.6-3.8-1.8-5a6.4 6.4 0 0 0-4.8-1.8c-2 0-3.7.7-5 2a7.8 7.8 0 0 0-1.9 5.5v17h-6.4Zm63.8 1a12.2 12.2 0 0 1-10.9-6.2 19 19 0 0 1-1.8-7.3h1.4v12.5h-5.1v-40h6.4v19.8l-2 3.5c.2-3.1.8-5.7 1.9-7.7a11 11 0 0 1 4.4-4.5c1.8-1 3.9-1.5 6.1-1.5a13.4 13.4 0 0 1 12.8 9.1c.7 1.9 1 3.8 1 6v1c0 2.2-.3 4.1-1 6a13.6 13.6 0 0 1-13.2 9.4Zm-1.2-5.5a8.4 8.4 0 0 0 7.9-5c.7-1.5 1.1-3.3 1.1-5.3s-.4-3.8-1.1-5.3a8.7 8.7 0 0 0-3.2-3.6 9.6 9.6 0 0 0-9.2-.2 8.5 8.5 0 0 0-3.3 3.2c-.8 1.4-1.3 3-1.3 5v2.3a9 9 0 0 0 1.3 4.8 9 9 0 0 0 3.4 3c1.4.7 2.8 1 4.4 1Zm27.3 3.9-10-28.9h6.5l9.5 28.9h-6Zm-7.5 12.2v-5.7h4.9c1 0 2-.1 2.9-.4a4 4 0 0 0 2-1.4c.4-.7.9-1.6 1.2-2.7l8.6-30.9h6.2l-9.3 32.4a14 14 0 0 1-2.5 5 8.9 8.9 0 0 1-4 2.8c-1.5.6-3.4.9-5.6.9h-4.4Zm9-12.2v-5.2h6.4v5.2H248Z"></path>
<path fill="#003DFF" d="M534.4 9.1H528a.8.8 0 0 1-.7-.7V1.8c0-.4.2-.7.6-.8l6.5-1c.4 0 .8.2.9.6v7.8c0 .4-.4.7-.8.7zM428 35.2V.8c0-.5-.3-.8-.7-.8h-.2l-6.4 1c-.4 0-.7.4-.7.8v35c0 1.6 0 11.8 12.3 12.2.5 0 .8-.4.8-.8V43c0-.4-.3-.7-.6-.8-4.5-.5-4.5-6-4.5-7zm106.5-21.8H528c-.4 0-.7.4-.7.8v34c0 .4.3.8.7.8h6.5c.4 0 .8-.4.8-.8v-34c0-.5-.4-.8-.8-.8zm-17.7 21.8V.8c0-.5-.3-.8-.8-.8l-6.5 1c-.4 0-.7.4-.7.8v35c0 1.6 0 11.8 12.3 12.2.4 0 .8-.4.8-.8V43c0-.4-.3-.7-.7-.8-4.4-.5-4.4-6-4.4-7zm-22.2-20.6a16.5 16.5 0 0 1 8.6 9.3c.8 2.2 1.3 4.8 1.3 7.5a19.4 19.4 0 0 1-4.6 12.6 14.8 14.8 0 0 1-5.2 3.6c-2 .9-5.2 1.4-6.8 1.4a21 21 0 0 1-6.7-1.4 15.4 15.4 0 0 1-8.6-9.3 21.3 21.3 0 0 1 0-14.4 15.2 15.2 0 0 1 8.6-9.3c2-.8 4.3-1.2 6.7-1.2s4.6.4 6.7 1.2zm-6.7 27.6c2.7 0 4.7-1 6.2-3s2.2-4.3 2.2-7.8-.7-6.3-2.2-8.3-3.5-3-6.2-3-4.7 1-6.1 3c-1.5 2-2.2 4.8-2.2 8.3s.7 5.8 2.2 7.8 3.5 3 6.2 3zm-88.8-28.8c-6.2 0-11.7 3.3-14.8 8.2a18.6 18.6 0 0 0 4.8 25.2c1.8 1.2 4 1.8 6.2 1.7s.1 0 .1 0h.9c4.2-.7 8-4 9.1-8.1v7.4c0 .4.3.7.8.7h6.4a.7.7 0 0 0 .7-.7V14.2c0-.5-.3-.8-.7-.8h-13.5zm6.3 26.5a9.8 9.8 0 0 1-5.7 2h-.5a10 10 0 0 1-9.2-14c1.4-3.7 5-6.3 9-6.3h6.4v18.3zm152.3-26.5h13.5c.5 0 .8.3.8.7v33.7c0 .4-.3.7-.8.7h-6.4a.7.7 0 0 1-.8-.7v-7.4c-1.2 4-4.8 7.4-9 8h-.1a4.2 4.2 0 0 1-.5.1h-.9a10.3 10.3 0 0 1-7-2.6c-4-3.3-6.5-8.4-6.5-14.2 0-3.7 1-7.2 3-10 3-5 8.5-8.3 14.7-8.3zm.6 28.4c2.2-.1 4.2-.6 5.7-2V21.7h-6.3a9.8 9.8 0 0 0-9 6.4 10.2 10.2 0 0 0 9.1 13.9h.5zM452.8 13.4c-6.2 0-11.7 3.3-14.8 8.2a18.5 18.5 0 0 0 3.6 24.3 10.4 10.4 0 0 0 13 .6c2.2-1.5 3.8-3.7 4.5-6.1v7.8c0 2.8-.8 5-2.2 6.3-1.5 1.5-4 2.2-7.5 2.2l-6-.3c-.3 0-.7.2-.8.5l-1.6 5.5c-.1.4.1.8.5 1h.1c2.8.4 5.5.6 7 .6 6.3 0 11-1.4 14-4.1 2.7-2.5 4.2-6.3 4.5-11.4V14.2c0-.5-.4-.8-.8-.8h-13.5zm6.3 8.2v18.3a9.6 9.6 0 0 1-5.6 2h-1a10.3 10.3 0 0 1-8.8-14c1.4-3.7 5-6.3 9-6.3h6.4zM291 31.5A32 32 0 0 1 322.8 0h30.8c.6 0 1.2.5 1.2 1.2v61.5c0 1.1-1.3 1.7-2.2 1l-19.2-17a18 18 0 0 1-11 3.4 18.1 18.1 0 1 1 18.2-14.8c-.1.4-.5.7-.9.6-.1 0-.3 0-.4-.2l-3.8-3.4c-.4-.3-.6-.8-.7-1.4a12 12 0 1 0-2.4 8.3c.4-.4 1-.5 1.6-.2l14.7 13.1v-46H323a26 26 0 1 0 10 49.7c.8-.4 1.6-.2 2.3.3l3 2.7c.3.2.3.7 0 1l-.2.2a32 32 0 0 1-47.2-28.6z"></path>
</svg>
</a>
</div>
</div>`
}
return sources;
}
let config = {
container : algolia.autocomplete.input_selector_modern,
openOnFocus: true,
debug : algolia.debug,
insights : algolia.insights_enabled,
// START CUSTOM DEBOUNCE 2/2.
stallThreshold: algolia.autocomplete.stall_threshold ?? 300,
getSources({query}) {
if (!query) {
return [];
}
return debouncedSources(query);
},
// END CUSTOM DEBOUNCE 2/2.
onStateChange({state}) {
if (state.isOpen) {
let algoliaPoweredLink = document.querySelector('.algolia-powered-by-link');
if (algoliaPoweredLink) {
algoliaPoweredLink.addEventListener('click', function (e) {
e.preventDefault();
window.location = "https://www.algolia.com/?utm_source=WordPress&utm_medium=extension&utm_content=" + window.location.hostname + "&utm_campaign=poweredby";
});
}
}
},
}
autocomplete(config);
});
</script>
Finally, activate the plugin. The modern Autocomplete template will now pull the debounce value from the settings supplied in WP Dashboard > Algolia Search > Autocomplete > Autocomplete Debounce.
Using a value of 0 will disable debounce. A suggested debounce value is 200 but you can adjust this to fit your preferences.
See the following doc for more information: https://www.algolia.com/doc/ui-libraries/autocomplete/guides/debouncing-sources