PageSourceSearch

https://truthencounters.com/wp-content/plugins/advanced-sermons/styling/js/asp-frontend.js?ver=3.7

js truthencounters.com collected 2026-10-09 05:22:00 UTC 15,927 bytes, 483 lines download raw bytes

1/** Global Settings **/
2window.disableLitepickerStyles = true;
3
4/** Detect Mobile devices **/
5function asp_detect_mobile() {
6    const Devices = [
7        /Android/i,
8        /webOS/i,
9        /iPhone/i,
10        /iPad/i,
11        /iPod/i,
12        /BlackBerry/i,
13        /Windows Phone/i
14    ];
15
16    return Devices.some( ( Device ) => {
17        return navigator.userAgent.match( Device );
18    } );
19}
20
21/** Change URL state based on search & filters **/
22function asp_change_url( Data ) {
23    const ExcludeQuery = {
24        'action' : true,
25        'mode' : true,
26        'path' : true,
27        'paged' : 1,
28        'order' : 'DESC',
29        'type' : true,
30    };
31    const IncludeSearchParams = {
32        'p' : true,
33        'page_id' : true,
34        'post_type' : true,
35    };
36
37    // Exclude default params from URL
38    const VisibleData = Object.entries( Data ).reduce((acc, [ Key,  Value ]) => {
39        if( !Value || Object.keys( ExcludeQuery ).includes( Key )
40            && ( ExcludeQuery[ Key ] === Value || ExcludeQuery[ Key ] === true ) ) {
41            return acc;
42        }
43
44        return {...acc, [Key]: Value};
45    }, {});
46
47    const SearchParams = new URLSearchParams( VisibleData );
48    const SourceParams = new URLSearchParams( window.location.search );
49    const PageURL = (window.location.origin + window.location.pathname).replace( /\/page\/[0-9]*/gm, '' );
50    const Target = new URL( PageURL );
51
52    // Only WP params to be kept
53    Object.keys( Object.fromEntries( SourceParams ) ).forEach( Key => {
54        if( !Object.keys( IncludeSearchParams ).includes( Key ) ) {
55            SourceParams.delete( Key );
56        }
57    });
58
59    // Combine params groups
60    const TargetParams = new URLSearchParams( {
61        ...Object.fromEntries( SourceParams ),
62        ...Object.fromEntries( SearchParams ),
63    } );
64
65    Target.search = TargetParams.toString();
66
67    window.history.pushState( 'page', null, Target.toString() );
68}
69
70/** Define scoped Filters function **/
71function asp_init_date_pickers( FilterBar ) {
72
73
74    const Pickers = FilterBar.querySelectorAll( '.sermon-date-container' );
75    const PickersInstances = [];
76
77    if( !Pickers ) {
78        return;
79    }
80
81    Pickers.forEach( Picker => {
82        const Input = Picker.querySelector('.asp-filter-date');
83
84        PickersInstances.push( new Litepicker( {
85            element: Input,
86            startDate: new Date(),
87            numberOfMonths: 2,
88            numberOfColumns: 2,
89            singleMode: false,
90            resetButton: true,
91            setup: Instance => {
92                Instance.on( 'selected', ( Start, End ) => {
93                    if( Start && End ) {
94                        Input.dispatchEvent( new CustomEvent( 'asp.filter.change' ) );
95                    }
96                } );
97
98                Instance.on( 'clear:selection', () => {
99                    Input.dispatchEvent( new CustomEvent( 'asp.filter.change' ) );
100                } );
101            },
102        } ) );
103
104        // After initializing, wrap the Litepicker in a asp-litepicker-wrapper div to reduce conflicts
105        const litepickerEl = document.querySelector('.litepicker');
106        const wrapperDiv = document.createElement('div');
107        wrapperDiv.className = 'asp-litepicker-wrapper'; // your desired class name
108
109        // Move litepicker inside the wrapper
110        wrapperDiv.appendChild(litepickerEl);
111
112        // Append the wrapperDiv to the body
113        document.body.appendChild(wrapperDiv);
114
115    } );
116
117    return PickersInstances;
118}
119
120/** Set initial query values **/
121function asp_set_initial_query( Query, FilterBar ) {
122
123    if( !FilterBar ) {
124        return Query;
125    }
126
127    const Filters = FilterBar.querySelectorAll( 'input, select' );
128
129    Filters.forEach( Filter => {
130        Query[ Filter.getAttribute( 'name' ) ] = Filter.value;
131    });
132
133    return Query;
134}
135
136// Flag to track if the featured content has been loaded initially
137let featuredContentLoaded = false;
138
139/** Initialize and handle change of filters value **/
140function asp_init_filters( SermonsGrid, FilterBar, Query, DatePickers ) {
141
142
143    const Filters = FilterBar.querySelectorAll( 'input, select' );
144
145    Filters.forEach( Filter => {
146        // Listen for future changes
147        Filter.addEventListener( 'asp.filter.change', () => {
148            Query[ 'mode' ] = 'filter';
149            Query[ 'paged' ] = 1;
150            Query[ Filter.getAttribute( 'name' ) ] = Filter.value;
151        } );
152
153        // Enable custom events for simple filters
154        if( Filter.getAttribute( 'name' ) !== 'sermon_dates' ) {
155            Filter.addEventListener( 'change', () => {
156                featuredContentLoaded = false;
157                Filter.dispatchEvent( new CustomEvent( 'asp.filter.change' ) );
158            } );
159        }
160    });
161
162    SermonsGrid.addEventListener( 'click', Event => {
163        if( !Event.target.classList.contains( 'asp-clear-filter-criteria' ) ) {
164            return;
165        }
166
167        Event.preventDefault();
168
169        asp_clear_filters( SermonsGrid, FilterBar, Query, DatePickers );
170    } );
171}
172
173function asp_clear_filters( SermonsGrid, FilterBar, QueryProxy, DatePickers ) {
174
175
176    const Filters = FilterBar.querySelectorAll( 'input, select' );
177    const Sermons = SermonsGrid.querySelector( '.sermon-archive-holder' );
178    const Pagination = SermonsGrid.querySelector( '.asp-pagination-wrapper' );
179    const FeaturedContent = SermonsGrid.querySelector( '.asp-details-top-holder' );
180    const CriteriaBar = SermonsGrid.querySelector( '.asp-criteria-box-wrapper' );
181
182    SermonsGrid.querySelector('.asp-load-more-button')?.removeAttribute('data-asp-page');
183
184    Filters.forEach( Filter => {
185        if( Filter.nodeName === 'SELECT' ) {
186            Filter.value = Filter.querySelector( 'option' ).value;
187        } else {
188            Filter.value = null;
189        }
190
191        if( Filter.classList.contains( 'asp-filter-date' ) ) {
192            DatePickers.forEach( DatePicker => DatePicker.clearSelection() );
193        }
194
195    } );
196
197    // Reset the featuredContentLoaded flag
198    featuredContentLoaded = false;
199
200    // Reset FeaturedContent and CriteriaBar
201    if (FeaturedContent) {
202        FeaturedContent.innerHTML = ''; // or set to default content
203    }
204    if (CriteriaBar) {
205        CriteriaBar.innerHTML = ''; // reset criteria display
206    }
207
208    Sermons.innerHTML = '';
209    Pagination.innerHTML = '';
210    QueryProxy.reset = {}
211}
212
213function asp_set_filters( SermonsGrid, FilterBar, QueryProxy, NewFilters ) {
214
215
216    const Filters = FilterBar.querySelectorAll( 'input, select' );
217
218    Filters.forEach( Filter => {
219        if( Filter.nodeName === 'SELECT' ) {
220            Filter.value = NewFilters[ Filter.getAttribute( 'name' ) ] ?? Filter.querySelector( 'option' ).value;
221        } else {
222            Filter.value = NewFilters[ Filter.getAttribute( 'name' ) ] ?? null;
223        }
224    } );
225
226    QueryProxy.reset = NewFilters;
227}
228
229/** Replace the content with the newly generated **/
230function asp_render(SermonsGrid, FilterBar, Data = {}, Override = true) {
231    const CriteriaBar = SermonsGrid.querySelector('.asp-criteria-box-wrapper');
232    const ArchiveScrollTo = SermonsGrid.querySelector('.asp-archive-ajax-scrollto');
233    const Sermons = SermonsGrid.querySelector('.sermon-archive-holder');
234    const FeaturedContent = SermonsGrid.querySelector('.asp-details-top-holder');
235    const Pagination = SermonsGrid.querySelector('.asp-pagination-wrapper');
236
237    // Update CriteriaBar and Pagination content
238    if (CriteriaBar) {
239        CriteriaBar.innerHTML = Data.active_filters;
240    }
241    if (Pagination) {
242        Pagination.innerHTML = Data.pagination;
243    }
244
245    // Update FeaturedContent if not a pagination action or if featured content has not been loaded yet
246    if (FeaturedContent && (Override || !featuredContentLoaded)) {
247        FeaturedContent.innerHTML = Data.featured;
248        featuredContentLoaded = true; // Set the flag after initial load or refresh
249    }
250
251    // Update Sermons content
252    if (Data.sermons) {
253        if (Override) {
254            Sermons.innerHTML = Data.sermons;
255            window.scrollTo({
256                top: ArchiveScrollTo.getBoundingClientRect().y + window.scrollY - 125,
257                behavior: 'smooth'
258            });
259        } else {
260            Sermons.insertAdjacentHTML('beforeend', Data.sermons);
261        }
262
263        setTimeout(() => {
264            Sermons.querySelectorAll('li').forEach(Sermon => Sermon.removeAttribute('style'));
265        }, 150);
266    }
267}
268
269/** Initialize the filtering, pagination and load more logic **/
270function asp_init( SermonsGrid ) {
271    const FiltersBar = SermonsGrid.querySelector( '.asp-archive-filter' );
272    const InfinityScrollHandler = SermonsGrid.querySelector( '.asp-pagination-wrapper' );
273    const Type = SermonsGrid.getAttribute( 'data-asp-pagination');
274
275    /** Creates listenable proxy for Query changes **/
276    let QueryDebouncer;
277    const InitialQuery = {
278        'action' : 'asp_generate_sermons',
279        'paged' : 1,
280        'type' : SermonsGrid.getAttribute( 'data-asp-pagination' ),
281        'path' : window.location.pathname,
282        'order' : 'DESC'
283    }
284
285    const QueryHandler = {
286        set( Target, Property, Value ) {
287            if( Property === 'reset' ) {
288                Object.keys( Target ).forEach( Key => {
289                    if( InitialQuery[ Key ] ) {
290                        Target[ Key ] = InitialQuery[ Key ];
291                    } else {
292                        delete Target[ Key ];
293                    }
294                });
295
296                Object.keys( Value ).forEach( Key => {
297                    Target[ Key ] = Value[ Key ];
298                });
299            } else {
300                Target[ Property ] = Value;
301            }
302
303            if( Property !== 'mode' ) {
304                clearInterval( QueryDebouncer );
305                QueryDebouncer = setTimeout( () => {
306                    SermonsGrid.dispatchEvent( new CustomEvent( 'asp.reload' ) )
307                }, 250 );
308            }
309
310            return Target;
311        }
312    };
313    const QueryProxy = new Proxy( asp_set_initial_query( {
314        'action' : 'asp_generate_sermons',
315        'paged' : 1,
316        'type' : SermonsGrid.getAttribute( 'data-asp-pagination' ),
317        'path' : window.location.pathname,
318        'order' : 'DESC'
319    }, FiltersBar ), QueryHandler );
320
321    /** Init Filters **/
322    if( FiltersBar ) {
323        const DatePickers = asp_init_date_pickers( FiltersBar );
324        asp_init_filters( SermonsGrid, FiltersBar, QueryProxy, DatePickers );
325    }
326
327    /** Init Infinity Scroll on Desktop **/
328    if( InfinityScrollHandler && Type === 'infinity' && !asp_detect_mobile() ) {
329        const InfinityScrollObserver = new IntersectionObserver( Entries => {
330            Entries.forEach( Entry => {
331                if( Entry.isIntersecting && InfinityScrollHandler.querySelector( '.asp-load-more-button' ) ) {
332                    QueryProxy.mode = 'infinity';
333                    QueryProxy.paged = InfinityScrollHandler.querySelector( '.asp-load-more-button' ).getAttribute( 'data-asp-page' );
334                }
335            } );
336        }, {
337            root: null,
338            threshold: 0.1,
339        } );
340
341        InfinityScrollObserver.observe( InfinityScrollHandler );
342    }
343
344    /** Init Infinity Scroll on Mobile **/
345    if( InfinityScrollHandler && Type === 'infinity' && asp_detect_mobile() ) {
346        const InfinityScrollObserver = new IntersectionObserver( Entries => {
347            Entries.forEach( Entry => {
348                if( Entry.isIntersecting && InfinityScrollHandler.querySelector( '.asp-load-more-button' ) ) {
349                    QueryProxy.mode = 'infinity';
350                    QueryProxy.paged = InfinityScrollHandler.querySelector( '.asp-load-more-button' ).getAttribute( 'data-asp-page' );
351                }
352            } );
353        }, {
354            root: null,
355            threshold: 0.1,
356        } );
357
358        InfinityScrollObserver.observe( InfinityScrollHandler );
359    }
360
361    /** Init Load More on Mobile **/
362    if( Type !== 'infinity' && asp_detect_mobile() ) {
363        const LoadMoreButton = InfinityScrollHandler.querySelector('.asp-load-more-button');
364        if( Type !== 'default') {
365            LoadMoreButton.removeAttribute( 'data-asp-pagination' );
366            LoadMoreButton.addEventListener( 'click', () => {
367                QueryProxy.mode = 'default';
368                QueryProxy.paged = LoadMoreButton.querySelector( '.asp-load-more-button' );
369            });
370        }
371    }
372
373    /** Init Pagination **/
374    SermonsGrid.addEventListener( 'click', Event => {
375        if( !InfinityScrollHandler.contains( Event.target ) ) {
376            return;
377        }
378
379        const Page = Event.target.getAttribute('data-asp-page');
380        const Mode = Event.target.getAttribute( 'data-asp-type' ) ? 'infinity' : 'default';
381
382        if ( !Page ) {
383            return;
384        }
385
386        Event.preventDefault();
387
388        QueryProxy.mode = Mode;
389        QueryProxy.paged = Page;
390    });
391
392    /** Init Any link filtering **/
393    SermonsGrid.addEventListener( 'click', Event => {
394        const Link = Event.target.href;
395
396        if( InfinityScrollHandler.contains( Event.target ) ) {
397            return;
398        }
399
400        if ( !Link || Link?.indexOf( window.location.pathname ) === -1
401            || Link?.indexOf( '?' ) === -1
402            || Link?.indexOf( '?sermons=' ) > -1
403            || Link?.indexOf( '?page_id=' ) > -1
404            || Link?.indexOf( '?p=' ) > -1 ) {
405            return;
406        }
407
408        if (FiltersBar) {
409            Event.preventDefault();
410        }
411
412        const SearchParams = new URLSearchParams( Link.substr( Link.indexOf('?') + 1 ) );
413        const Filters = {};
414
415        for( let Key of SearchParams.keys() ) {
416            Filters[ Key ] = SearchParams.get( Key );
417        }
418
419        asp_set_filters( SermonsGrid, FiltersBar, QueryProxy, Filters );
420    });
421
422    /** Handle data reload event **/
423    SermonsGrid.addEventListener( 'asp.reload', () => {
424        if( SermonsGrid.getAttribute( 'data-state' ) === 'pending' ) {
425            return;
426        }
427
428        const RenderMode = QueryProxy.mode;
429        const Data = new FormData();
430
431        for( let Key in QueryProxy ) {
432            if( !QueryProxy[ Key ] ) {
433                continue;
434            }
435
436            Data.append( Key, QueryProxy[ Key ] );
437        }
438
439        if( RenderMode !== 'infinity' ) {
440            SermonsGrid.querySelector( '.asp-pagination-wrapper' ).innerHTML = '';
441        }
442
443        SermonsGrid.setAttribute( 'data-state', 'pending' );
444
445        fetch( window.asp_ajax.url, {
446            method: 'POST',
447            body: Data
448        } ).then( ( Response ) => Response.json() ).then( Response => {
449            asp_render( SermonsGrid, FiltersBar, Response.data, RenderMode !== 'infinity' );
450        } ).then( () => {
451            asp_change_url( QueryProxy );
452        }).finally(() => {
453            SermonsGrid.setAttribute( 'data-state', 'idle' );
454        });
455    } );
456}
457
458/** Initialize Filtering processing with support for multiple filters (shortcodes) **/
459const SermonsGrids = document.querySelectorAll( '.asp-archive-container' );
460
461if( SermonsGrids ) {
462    SermonsGrids.forEach( SermonsGrid => {
463        asp_init( SermonsGrid );
464    } );
465}
466
467
468/** Improves compatability with 3rd party plugins and themes by removing select2 */
469(function($) {
470    $(document).ready(function() {
471        $(".asp-filter-order, .asp-filter-series, .asp-filter-topic, .asp-filter-speaker, .asp-filter-book, .asp-filter-campus, .asp-filter-service-type").each(function() {
472            // Check if Select2 is applied and destroy it
473            if ($(this).data('select2')) {
474                $(this).select2('destroy');
475            }
476
477            // Check if it's wrapped in .fancy-select-wrap and unwrap it
478            if ($(this).parent().hasClass('fancy-select-wrap')) {
479                $(this).unwrap();
480            }
481        });
482    });
483})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.