@@ -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 ( / (?: & n b s p ; | \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