Skip to content

Commit e0c6f55

Browse files
committed
update: adding cache layer to results to improve performance
1 parent 95bf9dd commit e0c6f55

1 file changed

Lines changed: 116 additions & 13 deletions

File tree

Dist/WebflowOnly/CMSFilter.js

Lines changed: 116 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class CMSFilter {
5656
}
5757
this.SetupEventListeners();
5858

59+
this.InitializeTagTemplate();
5960
// Capture original display styles before any filtering occurs
6061
this.captureOriginalDisplayStyles();
6162

@@ -67,10 +68,12 @@ class CMSFilter {
6768

6869
// Calculate range slider bounds once from original data (never changes during filtering)
6970
this.calculateInitialRanges();
71+
72+
// Initialize range inputs defaults (from=min, to=max) once
73+
this.initializeRangeInputsDefaults();
7074

7175
this.activeFilters = this.GetFilters();
7276
this.ShowResultCount();
73-
this.InitializeTagTemplate();
7477
}
7578

7679
/**
@@ -105,8 +108,6 @@ class CMSFilter {
105108

106109
// Configure range sliders with calculated ranges (only once)
107110
this.configureRangeSliders();
108-
109-
console.log('Calculated initial data ranges (static):', this.dataRanges);
110111
}
111112

112113
/**
@@ -117,7 +118,9 @@ class CMSFilter {
117118
configureRangeSliders() {
118119
// Find all range slider elements
119120
const rangeSliders = document.querySelectorAll('[wt-rangeslider-element="slider"]');
120-
121+
122+
if(!rangeSliders.length) return;
123+
121124
rangeSliders.forEach(slider => {
122125
// Try to get category from slider attribute first
123126
let category = slider.getAttribute('wt-rangeslider-category');
@@ -161,6 +164,98 @@ class CMSFilter {
161164
});
162165
}
163166

167+
/**
168+
* Build and store search cache for all items
169+
*/
170+
cacheItemSearchData() {
171+
if (!this.allItems || this.allItems.length === 0) return;
172+
this.allItems.forEach(item => this.cacheItemForSearch(item));
173+
}
174+
175+
/**
176+
* Build and attach a normalized search cache for a single item
177+
* Cache shape:
178+
* {
179+
* globalSearchText: string,
180+
* datasetValues: Map<datasetKey, string>,
181+
* categoryTexts: Map<categoryAttr, string>
182+
* }
183+
*/
184+
cacheItemForSearch(item) {
185+
if (!item || !(item instanceof Element)) return;
186+
187+
const normalize = (text) => (text || '')
188+
.toString()
189+
.toLowerCase()
190+
.replace(/(?:&nbsp;|\s)+/gi, ' ')
191+
.trim();
192+
193+
const datasetValues = new Map();
194+
const categoryTexts = new Map();
195+
196+
// Cache dataset values (normalized)
197+
if (item.dataset) {
198+
Object.keys(item.dataset).forEach(key => {
199+
const value = item.dataset[key];
200+
datasetValues.set(key, normalize(value));
201+
});
202+
}
203+
204+
// Cache category-specific text found inside the item
205+
const categoryNodes = item.querySelectorAll('[wt-cmsfilter-category]');
206+
categoryNodes.forEach(node => {
207+
const category = node.getAttribute('wt-cmsfilter-category');
208+
if (!category) return;
209+
const text = node.textContent || node.innerText || '';
210+
categoryTexts.set(category, normalize(text));
211+
});
212+
213+
// Global searchable text: item's text + dataset values
214+
const itemText = normalize(item.textContent || item.innerText || '');
215+
const datasetConcat = Array.from(datasetValues.values()).join(' ');
216+
const globalSearchText = normalize(`${itemText} ${datasetConcat}`);
217+
218+
item._wtSearchCache = { globalSearchText, datasetValues, categoryTexts };
219+
}
220+
221+
/**
222+
* Initialize default values for range inputs using precomputed data ranges
223+
* - Sets wt-cmsfilter-default to min (from) or max (to) if not present
224+
* - Populates the input's value if it's empty
225+
*/
226+
initializeRangeInputsDefaults() {
227+
if (!this.filterElements || !this.dataRanges) return;
228+
229+
this.filterElements.forEach(element => {
230+
const input = (element.tagName === 'INPUT')
231+
? element
232+
: element.querySelector('input[type="text"]');
233+
234+
if (!input || input.type !== 'text') return;
235+
236+
const rangeType = element.getAttribute('wt-cmsfilter-range');
237+
if (rangeType !== 'from' && rangeType !== 'to') return;
238+
239+
const categoryAttr = element.getAttribute('wt-cmsfilter-category');
240+
if (!categoryAttr) return;
241+
242+
const datasetCategory = this.GetDataSet(categoryAttr);
243+
const ranges = this.dataRanges[datasetCategory];
244+
if (!ranges) return;
245+
246+
const defaultValue = rangeType === 'from' ? ranges.min : ranges.max;
247+
if (!Number.isFinite(defaultValue)) return;
248+
249+
if (!input.hasAttribute('wt-cmsfilter-default')) {
250+
input.setAttribute('wt-cmsfilter-default', String(defaultValue));
251+
}
252+
253+
if (input.value.trim() === '') {
254+
input.value = String(defaultValue);
255+
}
256+
});
257+
}
258+
164259
SetupEventListeners() {
165260
// Create a debounced version of ApplyFilters
166261
const debouncedApplyFilters = this.debounce(() => this.ApplyFilters(), this.debounceDelay);
@@ -474,17 +569,21 @@ class CMSFilter {
474569
if (!rangeFilters[category]) {
475570
rangeFilters[category] = { from: null, to: null };
476571
}
477-
572+
478573
const value = parseFloat(input.value.trim());
479-
if (!isNaN(value)) {
480-
if(!input.hasAttribute('wt-cmsfilter-default')){
481-
input.setAttribute('wt-cmsfilter-default', value)
574+
if (Number.isFinite(value)) {
575+
const datasetCategory = this.GetDataSet(category);
576+
const ranges = this.dataRanges ? this.dataRanges[datasetCategory] : null;
577+
// Determine default for comparison without mutating attributes here
578+
let numericDefault = parseFloat(input.getAttribute('wt-cmsfilter-default'));
579+
if (!Number.isFinite(numericDefault) && ranges) {
580+
numericDefault = rangeType === 'from' ? ranges.min : ranges.max;
482581
}
483-
else {
484-
let _default = input.getAttribute('wt-cmsfilter-default');
485-
if (rangeType === 'from' && _default != value ) {
582+
583+
if (Number.isFinite(numericDefault)) {
584+
if (rangeType === 'from' && value !== numericDefault) {
486585
rangeFilters[category].from = value;
487-
} else if (rangeType === 'to' && _default != value) {
586+
} else if (rangeType === 'to' && value !== numericDefault) {
488587
rangeFilters[category].to = value;
489588
}
490589
}
@@ -818,7 +917,11 @@ class CMSFilter {
818917
'results': this.GetResults(),
819918
'per-page-items': this.itemsPerPage,
820919
'total-pages': this.totalPages,
821-
'current-page': this.currentPage
920+
'current-page': this.currentPage,
921+
'all-items': this.allItems,
922+
'filtered-items': this.filteredItems,
923+
'load-mode': this.loadMode,
924+
'range-sliders': this.dataRanges
822925
}
823926
return filterData;
824927
}

0 commit comments

Comments
 (0)