Skip to content

Instantly share code, notes, and snippets.

@c7x43t
Last active November 7, 2024 14:09
Show Gist options
  • Save c7x43t/765c3f859ff966bd75c85f5e322d74aa to your computer and use it in GitHub Desktop.
Save c7x43t/765c3f859ff966bd75c85f5e322d74aa to your computer and use it in GitHub Desktop.
const campaigns = [
@foreach($facebookCampaigns as $campaign)
{ id: '{{ $campaign->id }}', text: `{!! addslashes($campaign->name) !!}` },
@endforeach
];
window.campaigns = campaigns;
const products = [
@foreach($wooCommerceProducts as $product)
{ id: '{{ $product->product_id }}', text: `{!! addslashes($product->name) !!}` },
@endforeach
];
window.products = products;
// Initialize a FlexSearch Document index with typo-tolerance and partial matching
const flexIndex = new FlexSearch.Document({
preset: 'match',
charset: "latin:advanced", // Enables typo tolerant search
tokenize: "full", // Improves partial term matching
resolution: 20,
document: {
id: "id",
index: [
{
field: "text",
tokenize: "full",
threshold: 5,
resolution: 9,
depth: 5
}
]
},
context: {
resolution: 7,
depth: 5,
bidirectional: true
}
});
// Add both campaigns and products to the FlexSearch index
[...campaigns, ...products].forEach(item => flexIndex.add(item));
// Define a common matcher function for FlexSearch
function flexSearchMatcher(params, data) {
if ($.trim(params.term) === '') return data;
// Search in the FlexSearch index
let results = flexIndex.search(params.term, { enrich: true });
let resultIds = results.flatMap(result => result.result);
// Remove already-selected campaigns if it's the campaign field
if (data.element && data.element.closest('#facebook_campaigns')) {
const selectedCampaigns = $('#facebook_campaigns').val() || [];
resultIds = resultIds.filter(id => !selectedCampaigns.includes(id));
}
// Return data if it matches the search results
return resultIds.includes(data.id) ? data : null;
}
var Utils = $.fn.select2.amd.require('select2/utils');
var Dropdown = $.fn.select2.amd.require('select2/dropdown');
var DropdownSearch = $.fn.select2.amd.require('select2/dropdown/search');
var CloseOnSelect = $.fn.select2.amd.require('select2/dropdown/closeOnSelect');
var AttachBody = $.fn.select2.amd.require('select2/dropdown/attachBody');
var dropdownAdapter = Utils.Decorate(Utils.Decorate(Utils.Decorate(Dropdown, DropdownSearch), CloseOnSelect), AttachBody);
// Initialize Select2 for campaigns and products with the same FlexSearch matcher
$('#facebook_campaigns').select2({
dropdownAdapter,
data: campaigns,
placeholder: "Select campaigns",
width: '100%',
dropdownAutoWidth: true,
minimumResultsForSearch: 0,
matcher: flexSearchMatcher,
multiple: true
})
.on('select2:opening', function (event) {
$(this).parent().find('.select2-search__field').prop('disabled', true);
})
.on('select2:closing', function (event) {
$(this).parent().find('.select2-search__field').prop('disabled', false);
})
.on('select2:open', ()=>{
$('.select2-search--dropdown .select2-search__field')[0].focus();
setTimeout(()=>$('.select2-search--dropdown .select2-search__field')[0].focus(),0)
});
$('#woocommerce_product').select2({
data: products,
placeholder: "Select a product",
allowClear: true,
width: '100%',
dropdownAutoWidth: true,
minimumResultsForSearch: 0,
matcher: flexSearchMatcher
})
.on('select2:opening', function (event) {
$(this).parent().find('.select2-search__field').prop('disabled', false);
})
.on('select2:open', ()=>{
$('.select2-search--dropdown .select2-search__field')[0].focus();
setTimeout(()=>$('.select2-search--dropdown .select2-search__field')[0].focus(),0)
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment