front_findstr-search_src_search.js
import { parseFilters, parseSort } from './helpers';
import { Handlebars } from './handlebars';
import { MeiliSearch } from 'meilisearch';
let index = null;
const findstr = window.findstr || {};
let currentAbortController = null;
try {
const client = new MeiliSearch( {
host: findstr.config.host,
apiKey: findstr.config.publicKey,
} );
index = client.index( findstr.config.index );
} catch ( error ) {
console.warn( error );
}
async function search(
query,
parameters = {},
group = '',
field = null,
currentElement = null,
useAbortController = true,
isDisableSearchAsYouType = false,
triggerEvent = 'input',
keyValue = null
) {
if ( ! parameters.filter ) {
parameters.filter = { clauses: {} };
}
if ( isDisableSearchAsYouType && 'keyup' === triggerEvent && 'Enter' !== keyValue ) {
return new Promise( () => {} );
}
/**
* Limit the search field to 3 characters minimum
*
* @hook findstrQueryMinLength
*
* @param {number} queryMinLength - The minimum length of the query
* @param {string} group - The group name
* @param {Object} field - The field object
* @param {Object} currentElement - The current element who triggered the event
* @param {Object} parameters - The search parameters
*
* @return {number} queryMinLength - The minimum length of the query
*/
const queryMinLength = findstr.hooks.applyFilters(
'findstrQueryMinLength',
2,
group,
field,
currentElement,
parameters
);
if ( field && field.type === 'search' && parameters.q ) {
if ( parameters.q.length <= queryMinLength && parameters.q.length > 0 ) {
return new Promise( () => {} );
}
}
const queryClone = JSON.parse( JSON.stringify( parameters ) ); //clone the object query;
queryClone.filter = parseFilters( parameters.filter );
queryClone.sort = parseSort( parameters.sort );
/**
* Triggered before the search is performed.
*
* @hook beforeSearch
*
* @param {string} group - The group name
* @param {Object} parameters - The search parameters
* @param {Object} field - The field object
* @param {Object} current_element - The current element who triggered the event
* @param {Object} index - The meilisearch index
*/
findstr.hooks.doAction(
'beforeSearch',
group,
parameters,
field,
currentElement,
index
);
// Annuler la recherche précédente si elle existe
if ( useAbortController && currentAbortController ) {
currentAbortController.abort(
'Findstr search aborted by a new search request'
);
}
// Créer un nouveau AbortController pour cette recherche
if ( useAbortController ) {
currentAbortController = new AbortController();
}
// Options pour fetch avec le signal d'AbortController si nécessaire
const options = useAbortController
? { signal: currentAbortController.signal }
: {};
return await index
.search( query, queryClone, options )
.then( ( results ) => {
results.translations = findstr.translations;
results.hits.forEach( ( hit ) => {
hit.post_type_label =
findstr.translations?.post_type?.[ hit.post_type ] ??
hit.post_type;
} );
results.totalHits =
results.facetDistribution?.language?.[ findstr.currentLanguage ] ||
results.totalHits;
/**
* Filter the search results
*
* @hook searchResults
*
* @param {Object} results - The search results
* @param {string} group - The group name
* @param {Object} field - The field object
* @param {Object} current_element - The current element who triggered the event
* @param {Object} parameters - The search parameters
*
* @return {Object} results - The search results
*/
results = findstr.hooks.applyFilters(
'searchResults',
results,
group,
field,
currentElement,
parameters
);
/**
* Triggered when the search results are loaded
*
* @hook searchResults
*
* @param {Object} results - The search results
* @param {string} group - The group name
* @param {Object} field - The field object
* @param {Object} current_element - The current element who triggered the event
* @param {Object} parameters - The search parameters
* @param {Object} index - The meilisearch index
*/
findstr.hooks.doAction(
'searchResults',
results,
group,
field,
currentElement,
parameters,
index
);
if ( group ) {
const resultsTemplate = Handlebars.compile(
document.querySelector(
`[data-findstr-results="${ group }"] .findstrResultsTemplate`
).innerHTML
);
const resultsContainer = document.querySelector(
`[data-findstr-results="${ group }"] .findstrResultsContainer`
);
/**
* Append the search results.
*
* Check if we need to replace the results or append them,
* If the filter returns true, we append the results, otherwise we replace them.
*
* Usage: infinite scroll or load more button
*
* @hook appendResults
*
* @param {boolean} append - Append the results
* @param {Object} results - The search results
* @param {string} group - The group name
* @param {Object} field - The field object
* @param {Object} current_element - The current element who triggered the event
* @param {Object} parameters - The search parameters
* @param {Object} resultsContainer - The results container
*
* @return {boolean} append - Append the results
*/
const appendResults = findstr.hooks.applyFilters(
'appendResults',
false,
results,
group,
field,
currentElement,
parameters,
resultsContainer
);
appendResults
? resultsContainer.insertAdjacentHTML(
'beforeend',
resultsTemplate( results )
)
: ( resultsContainer.innerHTML = resultsTemplate( results ) );
//if query is empty, clear the results
if ( ! parameters.q && ! parameters.filter ) {
resultsContainer.innerHTML = '';
}
resultsContainer.scrollTop = 0;
/**
* Triggered after the search results are loaded
*
* @hook afterSearchResults
*
* @param {Object} results - The search results
* @param {string} group - The group name
* @param {Object} field - The field object
* @param {Object} current_element - The current element who triggered the event
* @param {Object} parameters - The search parameters
* @param {Object} resultsContainer - The results container
*/
findstr.hooks.doAction(
'afterSearchResults',
results,
group,
field,
currentElement,
parameters,
resultsContainer
);
}
findstr.query = parameters; //store the object query in the global variable
return results;
} )
.catch( ( error ) => {
console.warn( 'Findstr search error : ', error );
} );
}
export { search };