front_findstr-search_index.js
import domReady from '@wordpress/dom-ready';
import { createHooks } from '@wordpress/hooks';
import { _x } from '@wordpress/i18n';
const findstr = window.findstr || {};
import { search } from './src/search';
import { findstrInit } from './src/facet';
// fields
import './src/fields';
//url management
import './src/url';
import './index.scss';
import * as helpers from './src/helpers';
window.findstr.helpers = helpers;
const Handlebars = helpers.Handlebars || {};
if (
findstr.config &&
findstr.config.host &&
findstr.config.publicKey &&
findstr.config.index
) {
} else {
console.warn('findstr is not configured', findstr.config);
}
findstr.hooks = createHooks();
domReady(() => {
//Earliest event to allow other scripts to hook into findstr
const firstEvent = new CustomEvent('findstrInit', {
detail: findstr,
});
document.dispatchEvent(firstEvent);
if (!findstr.config || !findstr.config.host || !findstr.config.index) {
console.error('findstr.config is not defined');
return;
}
const defaultQuery = JSON.parse(findstr.config.defaultQuery);
findstr.search = search;
search('', defaultQuery)
.then((response) => {
if ('undefined' === typeof response) {
throw new Error(
'Findstr Error: MeiliSearch is not running or the index is not found.'
);
}
//keep original facets data
if (!findstr.facets) {
//resort facets alphabetically, because MeiliSearch doesn't take care of accents
const facets = {};
for (const [key, value] of Object.entries(
response.facetDistribution
)) {
facets[key] = Object.keys(value)
.sort(Intl.Collator().compare)
.reduce(function (acc, k) {
acc[k] = value[k];
return acc;
}, {});
}
/**
* Filter the facet distribution
*
* @hook setFacetsDistribution
*
* @param {Object} facets - The facets object
*
* @return {Object} - The filtered facets object
*/
findstr.facets = findstr.hooks.applyFilters(
'setFacetsDistribution',
facets
);
}
//once we get the first response, it means findstr is fully loaded
const event = new CustomEvent('findstrLoaded', {
detail: response,
});
// Dispatch the event.
document.dispatchEvent(event);
/**
* Triggered when the search results are first loaded
*
* @hook searchResultsFirstLoad
*
* @param {Object} response - The search results
*/
findstr.hooks.doAction('searchResultsFirstLoad', response);
findstrInit();
})
.catch((error) => {
console.error('Findstr search error', error);
});
findstr.clearResults = function (group) {
const resultsContainer = document.querySelector(
`[data-findstr-results="${group}"] .findstrResultsTemplate`
);
resultsContainer.innerHTML = '';
};
findstr.resetFilters = function (group, launchSearch = true) {
const resultsContainer = document.querySelector(
`[data-findstr-results="${group}"]`
);
if (resultsContainer) {
const query = JSON.parse(resultsContainer.dataset.findstrQuery);
/**
* Triggered when the filters are reset
* @hook resetFilters
*
* @param {string} group - The group name
*/
findstr.hooks.doAction('resetFilters', group, query);
if( true === launchSearch ) {
findstr.search('', query, group);
}
}
};
/* empty alert */
if (findstr) {
const setEmptyAlert = (group, resultsCount) => {
const emptyAlertContainer = document.querySelector(
'.findstr-empty-alert[data-group="' + group + '"]'
);
if (emptyAlertContainer) {
const emptyAlertTemplate = Handlebars.compile(
document.querySelector(
`[data-group="${group}"].findstrEmptyResultsTemplate`
).innerHTML
);
if (emptyAlertContainer.classList.contains('visible')) {
emptyAlertContainer.classList.remove('visible');
emptyAlertContainer.innerHTML = '';
}
setTimeout(() => {
if (0 === resultsCount) {
emptyAlertContainer.classList.add('visible');
emptyAlertContainer.innerHTML = emptyAlertTemplate(
/**
* Filter the data for the empty results alert.
*
* By default, emptyResultsText is set to "No results found. Please try again."
* The data is used in the empty alert template `empty-results.hbs.php`
*
* @hook findstrEmptyResultsData
* @param {Object} data - The data
*
* @return {Object} - The filtered data
*/
findstr.hooks.applyFilters(
'findstrEmptyResultsData',
{
emptyResultsText: _x(
'No results found. Please try again.',
'search results',
'findstr'
),
}
)
);
}
}, 150);
}
};
findstr.hooks.addAction(
'searchResults',
'findstr-search',
(results, group) => {
setEmptyAlert(group, results.hits.length);
}
);
findstr.hooks.addAction('findstrInit', 'findstr-search', (findstr) => {
const resultsContainers =
document.querySelectorAll('.findstr-results');
resultsContainers.forEach((resultsContainer) => {
const group = resultsContainer.dataset.findstrResults;
const container = resultsContainer.querySelector(
'.findstrResultsContainer'
);
/**
* When this filter is set to false, the empty alert will not be shown on first page load.
*
* @hook findstrEmptyResultsMessageOnInit
*
* @param {boolean} setEmptyAlertOnInit - Set the empty alert on init
* @param {string} group - The group name
*
* @return {boolean} - Set the empty alert on init (true by default)
*/
const setEmptyAlertOnInit = findstr.hooks.applyFilters(
'findstrEmptyResultsMessageOnInit',
true,
group,
resultsContainer
);
//if setEmptyAlertOnInit is false, it means we don't want to show the empty alert on init
if (true === setEmptyAlertOnInit) {
setEmptyAlert(group, container.childElementCount);
}
});
});
}
});
/* search block */
domReady(() => {
const searchBlocks = document.querySelectorAll('.search-findstr-block');
if (0 < searchBlocks.length) {
searchBlocks.forEach((searchBlock) => {
const searchInput = searchBlock.querySelector('input[type=search]');
searchInput.addEventListener('input', () => {
if ('' === searchInput.value) {
searchBlock.classList.remove('dropdown-active');
} else {
searchBlock.classList.add('dropdown-active');
}
});
window.addEventListener('click', (e) => {
const outsideClick = !searchBlock.contains(e.target);
if (
outsideClick &&
searchBlock.classList.contains('dropdown-active')
) {
searchBlock.classList.remove('dropdown-active');
} else if (
!outsideClick &&
!searchBlock.classList.contains('dropdown-active') &&
'' !== searchInput.value
) {
searchBlock.classList.add('dropdown-active');
}
});
});
}
});