PageSourceSearch

https://chdors.org/wp-content/themes/pitheme/js/events-script.js

js chdors.org collected 2026-09-29 19:11:50 UTC 16,937 bytes, 412 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function() {
2    function getInitialTargetIndex(slides) {
3        const highlightIndex = slides.findIndex(slide => slide.getAttribute('data-highlight') === 'true');
4        if (highlightIndex !== -1) return highlightIndex;
5
6        const todayStr = new Date().toISOString().split('T')[0];
7        const todayIndex = slides.findIndex(slide => {
8            const eventDate = slide.getAttribute('data-event-date');
9            return eventDate && eventDate.startsWith(todayStr);
10        });
11
12        return todayIndex !== -1 ? todayIndex : 0;
13    }
14
15    function updateActiveDayClass(index, slides, container) {
16        const currentSlide = slides[index];
17        if (!currentSlide) return;
18
19        const eventDateTime = currentSlide.getAttribute('data-event-date');
20        const category = currentSlide.getAttribute('data-category');
21        const scope = container.closest('.tab-pane');
22        if (!scope) return;
23
24        if (eventDateTime) {
25            const eventDate = eventDateTime.split(' ')[0];
26
27            if (window.innerWidth > 825) {
28                scope.querySelectorAll('[data-day-date].active-slide').forEach(el => el.classList.remove('active-slide'));
29                const dayEl = scope.querySelector(`[data-day-date="${eventDate}"]`);
30                if (dayEl) dayEl.classList.add('active-slide');
31            } else {
32                scope.querySelectorAll('[data-day-datemobile].active-slide-mobile').forEach(el => el.classList.remove('active-slide-mobile'));
33                const dayEl = scope.querySelector(`[data-day-datemobile="${eventDate}"]`);
34                if (dayEl) dayEl.classList.add('active-slide-mobile');
35            }
36        }
37
38        const sidebar = scope.querySelector('.calendar-sidebar .swiper-container');
39        if (sidebar && category) {
40            sidebar.setAttribute('data-category', category);
41        }
42
43        // Loop over all h3 elements inside this scope
44        const headings = scope.querySelectorAll('h3.tribe-common-h4');
45        headings.forEach(h3 => {
46            h3.setAttribute('data-category', category);
47
48            // Find the closest wrapper div (customize this selector as needed)
49            const wrapper = h3.closest('.tribe-events-calendar-month__day');
50            if (wrapper) {
51                wrapper.classList.add('tribe-events-calendar-month__day');
52                wrapper.setAttribute('data-category', category);
53            }
54        });
55        if ($(window).width() < 825) {
56
57
58            const categoriesToRemove = ['dors-west', 'dors-central', 'dors-northwest'];
59
60            $('.school-events.school-buletin .dors-south-div .tribe-events-calendar-month__day-cell').each(function() {
61                const $el = $(this);
62                const categoryAttr = $el.attr('data-category');
63
64                // Proceed only if data-category exists and is not empty
65                if (typeof categoryAttr !== 'undefined' && categoryAttr.length > 0) {
66                    let categories = categoryAttr.split(',');
67
68                    // Filter out all categories that are in the removal list
69                    categories = categories.filter(cat => !categoriesToRemove.includes(cat.trim()));
70
71                    // Update the attribute (can be empty if all were removed)
72                    $el.attr('data-category', categories.join(','));
73                }
74            });
75
76            const categoriesToRemove2 = ['dors-south', 'dors-central', 'dors-northwest'];
77
78            $('.school-events.school-buletin .dors-west-div .tribe-events-calendar-month__day-cell').each(function() {
79                const $el = $(this);
80                const categoryAttr = $el.attr('data-category');
81
82                // Proceed only if data-category exists and is not empty
83                if (typeof categoryAttr !== 'undefined' && categoryAttr.length > 0) {
84                    let categories = categoryAttr.split(',');
85
86                    // Filter out all categories that are in the removal list
87                    categories = categories.filter(cat => !categoriesToRemove2.includes(cat.trim()));
88
89                    // Update the attribute (can be empty if all were removed)
90                    $el.attr('data-category', categories.join(','));
91                }
92            });
93
94            const categoriesToRemove3 = ['dors-south', 'dors-west', 'dors-northwest'];
95
96            $('.school-events.school-buletin .dors-central-div .tribe-events-calendar-month__day-cell').each(function() {
97                const $el = $(this);
98                const categoryAttr = $el.attr('data-category');
99
100                // Proceed only if data-category exists and is not empty
101                if (typeof categoryAttr !== 'undefined' && categoryAttr.length > 0) {
102                    let categories = categoryAttr.split(',');
103
104                    // Filter out all categories that are in the removal list
105                    categories = categories.filter(cat => !categoriesToRemove3.includes(cat.trim()));
106
107                    // Update the attribute (can be empty if all were removed)
108                    $el.attr('data-category', categories.join(','));
109                }
110            });
111
112            const categoriesToRemove4 = ['dors-south', 'dors-west', 'dors-central'];
113
114            $('.school-events.school-buletin .dors-northwest-div .tribe-events-calendar-month__day-cell').each(function() {
115                const $el = $(this);
116                const categoryAttr = $el.attr('data-category');
117
118                // Proceed only if data-category exists and is not empty
119                if (typeof categoryAttr !== 'undefined' && categoryAttr.length > 0) {
120                    let categories = categoryAttr.split(',');
121
122                    // Filter out all categories that are in the removal list
123                    categories = categories.filter(cat => !categoriesToRemove4.includes(cat.trim()));
124
125                    // Update the attribute (can be empty if all were removed)
126                    $el.attr('data-category', categories.join(','));
127                }
128            });
129
130            const sidebar = scope.querySelector('.calendar-sidebar .swiper-container');
131            if (sidebar) {
132                sidebar.setAttribute('data-category', category || '');
133            }
134
135            const headings = scope.querySelectorAll('.tab-pane .tribe-events-calendar-month__day-cell');
136
137            headings.forEach(h3 => {
138                // Always set the attribute — with category if available, else blank
139                h3.setAttribute('data-mobile-category', category || '');
140
141                const wrapper = h3.closest('.tab-pane .tribe-events-calendar-month__day');
142                if (wrapper) {
143                    wrapper.classList.add('tribe-events-calendar-month__day');
144                    wrapper.setAttribute('data-mobile-category', category || '');
145                }
146            });
147
148
149        }
150
151    }
152
153    function toggleNavigationVisibility(container, slides, activeIndex) {
154        const currentSlide = slides[activeIndex];
155        const nextBtn = container.querySelector('.swiper-button-next');
156        const prevBtn = container.querySelector('.swiper-button-prev');
157        const navWrapper = container.closest('.tab-pane')?.querySelector('.s-nbavigaton');
158
159        if (!currentSlide || !nextBtn || !prevBtn) return;
160
161        const eventDateTime = currentSlide.getAttribute('data-event-date');
162        if (!eventDateTime) {
163            nextBtn.style.display = 'none';
164            prevBtn.style.display = 'none';
165            if (navWrapper) navWrapper.style.display = 'none';
166            return;
167        }
168
169        const eventDate = eventDateTime.split(' ')[0];
170        const sameDateSlides = slides
171            .map((slide, i) => ({
172                slide,
173                index: i
174            }))
175            .filter(item => {
176                const date = item.slide.getAttribute('data-event-date');
177                return date && date.startsWith(eventDate);
178            });
179
180        const showNavigation = sameDateSlides.length > 1;
181        const currentInGroupIndex = sameDateSlides.findIndex(item => item.index === activeIndex);
182
183        nextBtn.style.display = showNavigation ? '' : 'none';
184        prevBtn.style.display = showNavigation ? '' : 'none';
185        if (navWrapper) {
186            navWrapper.style.display = showNavigation ? '' : 'none';
187
188            const scope = container.closest('.tab-pane');
189            if (scope) {
190                const btnGrey = scope.querySelector('.school-events .btn-grey');
191                if (btnGrey) {
192                    if (showNavigation) {
193                        btnGrey.classList.add('active-nav-visible'); // You can use any class name you need
194                    } else {
195                        btnGrey.classList.remove('active-nav-visible');
196                    }
197                }
198            }
199        }
200
201        if (showNavigation) {
202            nextBtn.classList.toggle('swiper-button-disabled', currentInGroupIndex === sameDateSlides.length - 1);
203            prevBtn.classList.toggle('swiper-button-disabled', currentInGroupIndex === 0);
204        }
205    }
206
207    function initSwiper(container) {
208        if (!container) return;
209        if (container.swiper && !container.swiper.destroyed) {
210            container.swiper.update();
211            return;
212        }
213
214        const swiperWrapper = container.querySelector('.swiper-wrapper');
215        const slides = Array.from(container.querySelectorAll('.swiper-slide'));
216        swiperWrapper.innerHTML = '';
217        slides.forEach(slide => swiperWrapper.appendChild(slide));
218
219        const targetIndex = getInitialTargetIndex(slides);
220
221        const swiper = new Swiper(container, {
222        loop: false,
223            initialSlide: targetIndex,
224            slidesPerView: 1,
225            spaceBetween: 20,
226            navigation: {
227                nextEl: container.querySelector('.swiper-button-next'),
228                prevEl: container.querySelector('.swiper-button-prev'),
229            },
230            pagination: {
231                el: container.querySelector('.swiper-pagination'),
232                clickable: true,
233            },
234            observer: true,
235            observeParents: true,
236            simulateTouch: window.innerWidth <= 767, // ✅ Allow swipe only on mobile
237            allowTouchMove: window.innerWidth <= 767 // ✅ Disable drag on desktop
238        });
239
240
241        updateActiveDayClass(targetIndex, slides, container);
242        toggleNavigationVisibility(container, slides, targetIndex);
243
244        swiper.on('slideChange', function() {
245            updateActiveDayClass(swiper.activeIndex, slides, container);
246            toggleNavigationVisibility(container, slides, swiper.activeIndex);
247
248            const scope = container.closest('.tab-pane');
249            if (scope) {
250                scope.querySelectorAll('[data-day-date].activeclick, [data-day-datemobile].activeclick')
251                    .forEach(el => el.classList.remove('activeclick'));
252            }
253        });
254
255        // test3 SAFELY attach custom prev/next button logic to avoid stacking
256        const nextBtn = container.querySelector('.swiper-button-next');
257        const prevBtn = container.querySelector('.swiper-button-prev');
258
259        if (nextBtn && prevBtn) {
260            nextBtn.onclick = function(e) {
261                e.preventDefault();
262
263                const currentIndex = swiper.activeIndex;
264                const currentSlide = swiper.slides[currentIndex];
265                const currentDate = currentSlide?.getAttribute('data-event-date')?.split(' ')[0];
266
267                let sameDateSlides = [];
268
269                try {
270                    if (typeof swiper.slides.map === 'function') {
271                        sameDateSlides = swiper.slides
272                            .map((slide, index) => ({
273                                slide,
274                                index
275                            }))
276                            .filter(item => {
277                                const date = item.slide.getAttribute('data-event-date');
278                                return date && date.split(' ')[0] === currentDate;
279                            });
280                    } else {
281                        return; // silent exit if map is not a function
282                    }
283                } catch (err) {
284                    return; // completely silent fail
285                }
286
287                const currentPos = sameDateSlides.findIndex(item => item.index === currentIndex);
288                const nextItem = sameDateSlides[currentPos + 1];
289
290                if (nextItem) {
291                    swiper.slideTo(nextItem.index);
292                }
293            };
294
295
296
297
298            prevBtn.onclick = function(e) {
299                e.preventDefault();
300
301                const currentIndex = swiper.activeIndex;
302                const currentSlide = swiper.slides[currentIndex];
303                const currentDate = currentSlide?.getAttribute('data-event-date')?.split(' ')[0];
304
305                let sameDateSlides = [];
306
307                try {
308                    if (typeof swiper.slides.map === 'function') {
309                        sameDateSlides = swiper.slides
310                            .map((slide, index) => ({
311                                slide,
312                                index
313                            }))
314                            .filter(item => {
315                                const date = item.slide.getAttribute('data-event-date');
316                                return date && date.split(' ')[0] === currentDate;
317                            });
318                    } else {
319                        return;
320                    }
321                } catch (err) {
322                    return;
323                }
324
325                const currentPos = sameDateSlides.findIndex(item => item.index === currentIndex);
326                const prevItem = sameDateSlides[currentPos - 1];
327
328                if (prevItem) {
329                    swiper.slideTo(prevItem.index);
330                }
331            };
332
333
334
335
336        }
337
338        container.swiper = swiper;
339    }
340
341    const activeTabPane = document.querySelector('.tab-pane:not(.hidden-bul)');
342    if (activeTabPane) {
343        const container = activeTabPane.querySelector('.swiper-container');
344        if (container) {
345            initSwiper(container);
346        }
347    }
348
349    document.addEventListener('click', function(e) {
350        const targetDesktop = e.target.closest('[data-day-date]');
351        const targetMobile = e.target.closest('[data-day-datemobile]');
352        const clickedDate = targetDesktop?.getAttribute('data-day-date') || targetMobile?.getAttribute('data-day-datemobile');
353        if (!clickedDate) return;
354
355        const scope = targetDesktop?.closest('.tab-pane') || targetMobile?.closest('.tab-pane');
356        if (!scope) return;
357
358        scope.querySelectorAll('[data-day-date].activeclick, [data-day-datemobile].activeclick')
359            .forEach(el => el.classList.remove('activeclick'));
360
361        if (targetDesktop) targetDesktop.classList.add('activeclick');
362        if (targetMobile) targetMobile.classList.add('activeclick');
363
364        const container = scope.querySelector('.swiper-container');
365        if (!container || !container.swiper) return;
366
367        const slides = Array.from(container.querySelectorAll('.swiper-slide'));
368        const matchIndex = slides.findIndex(slide => {
369            const slideDate = slide.getAttribute('data-event-date');
370            return slideDate && slideDate.startsWith(clickedDate);
371        });
372
373        if (matchIndex !== -1) {
374            container.swiper.slideTo(matchIndex);
375        }
376    });
377
378    $(document).ready(function() {
379        $('.school-buletin-tabs .tab-link').click(function() {
380            $('.school-buletin-tabs .tab-link').removeClass('active-bul');
381            $(this).addClass('active-bul');
382
383            $('.school-wappers .tab-pane').addClass('hidden-bul');
384            const target = $(this).data('target');
385            const $targetPane = $(target);
386            if ($targetPane.length === 0) return;
387
388            $targetPane.removeClass('hidden-bul');
389
390            setTimeout(() => {
391                const container = $targetPane.find('.swiper-container').get(0);
392                if (container) {
393                    initSwiper(container);
394                }
395
396                window.dispatchEvent(new Event('resize'));
397                $('.tribe-events-calendar-month:visible').each(function() {
398                    const calendar = $(this).data('fc');
399                    if (calendar && typeof calendar.updateSize === 'function') {
400                        calendar.updateSize();
401                    }
402                });
403
404                if (typeof tribe !== 'undefined' && tribe.events?.views?.manager?.refresh) {
405                    tribe.events.views.manager.refresh();
406                }
407            }, 50);
408        });
409    });
410});
411
412

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.