document.addEventListener('alpine:init', () => {
Alpine.data('predictiveSearch', () => ({
dropdown_open: false,
query: '',
loading_suggestions: false,
preferred_suggestion_count: 10,
suggestions: [],
open() {
if (this.dropdown_open || !this.query.length) return;
this.dropdown_open = true;
},
close(focusAfter) {
if (!this.dropdown_open) return;
this.dropdown_open = false;
focusAfter && focusAfter.focus && focusAfter.focus()
},
async getSuggestions(query) {
const vm = this;
// abort any previous requests still in progress
if (vm.fetchController) {
vm.fetchController.abort();
}
if (!query.length) {
vm.query = '';
vm.close(vm.$refs.searchInput);
return;
}
const reqBody = {
billable_account_id: '36124',
search_limit: vm.preferred_suggestion_count,
search_term: vm.query,
}
try {
vm.fetchController = new AbortController();
const params = new URLSearchParams(reqBody).toString();
const url = `/api/internal/wf-appliance/predictive-search-terms-get?API_KEY=WSKYRINYDNCQUADFAKXHUQSABSPHABPYTICFKKYOVDTPWYNSAJJTJMHGBAGU&${params}`;
const res = await fetch(url,
{ signal: vm.fetchController.signal }
);
if (!res.ok) throw new Error('Predictive search endpoint not found');
const { success, suggested_terms } = await res.json();
if (!success) throw new Error('Error predicting search terms');
if (!suggested_terms.length) return vm.close(vm.$refs.searchInput);
vm.suggestions = suggested_terms.map(term => term.toLowerCase());
if (!vm.dropdown_open) vm.open();
} catch (err) {
if (err.name === 'AbortError') {
return;
}
vm.suggestions = [];
vm.close(vm.$refs.searchInput);
}
},
onSuggestionClick(suggestion) {
this.close();
this.query = suggestion;
this.$nextTick(() => this.$refs.searchForm.submit())
},
highlightNonMatchingSubstring(suggestion) {
const query = this.query.toLowerCase();
const suggestionLowercase = suggestion.toLowerCase();
// check if the suggestion exactly matches the query
if (suggestionLowercase === query) {
return `
<
span>${suggestion}`;
}
// check if the suggestion starts with the query
if (suggestionLowercase.indexOf(query) === 0) {
const nonMatching = suggestion.substring(query.length);
return `<
span>${query}
<
strong>${nonMatching}
`;
}
// highlight non-matching substrings
const normalizedQuery = query.replaceAll('(', '').replaceAll(')', '').replaceAll('[', '').replaceAll(']', '').replaceAll('\\', '');
const regex = new RegExp(`(?!${normalizedQuery})\\b\\w+\\b`, 'gi');
const highlighted = suggestion.replace(regex, '<
strong>$&');
return `<
span>${highlighted}
`;
},
titleCase(str = '') {
if (!str || typeof str !== 'string') return str;
return str
.trim()
.split(' ')
.map(word => word[0]?.toUpperCase() + word.slice(1)?.toLowerCase())
.join(' ');
},
}))
})
Vintage Overdye Collection