PageSourceSearch

https://www.volksbund.de/typo3temp/assets/compressed/termine-6ff1804795b81c3e5209fab43dcc0ca8.js?1790233887

js volksbund.de collected 2026-09-24 09:29:48 UTC 16,033 bytes, 429 lines download raw bytes

1const TerminFilter = (function() {
2    let picker = null;
3    let fromField = null;
4    let toField = null;
5    let searchWord = '';
6    let topics = ''; // 'thema'
7    let types = ''; // 'terminart
8    let host = null; // veranstalter
9    let initialHosts = '' // this is set from plugin''
10    let range = 0;
11    let searchDebounceTimer;
12    let lastFoundEvents = document.querySelector('#lastFoundAppointments');
13    // coutry und catlist kann glaub ich weg
14    let requestParams = {
15        type: 98877,
16        offset: 10,
17        limit: 10,
18        mode: 'append',
19        range: 0,
20        storagePids: '',
21        detuid: '',
22        catlist: '',
23        from: '',
24        to: '',
25        host: '',
26        country: null,
27        searchWord: '',
28        types: '',
29        topics: ''
30    }
31
32    function formatToIsoDate(date) {
33        const year = date.getFullYear();
34        const month = String(date.getMonth() + 1).padStart(2, "0");
35        const day = String(date.getDate()).padStart(2, "0");
36        return `${year}-${month}-${day}`;
37    }
38
39    function initializeDatepicker() {
40        var curr = new Date();
41        picker = new Litepicker({
42            element: document.getElementById('datepicker'),
43            numberOfMonths: 2,
44            numberOfColumns: 2,
45            inlineMode: true,
46            format: 'YYYY-MM-DD',
47            lang: 'de-DE',
48            singleMode: false,
49            showTooltip: false,
50            minDate: curr,
51            minDate: '2024-01-01',
52            onSelect: function(date1, date2) {
53                fromField.value = formatToIsoDate(date1);
54                toField.value = formatToIsoDate(date2);
55                reload();
56            }
57        });
58    }
59
60    function setEventListeners() {
61        const rangeTimeselects = document.querySelectorAll('button.timeselect.range');
62        const dateTimeselects  = document.querySelectorAll('button.timeselect.date');
63        const searchInput = document.getElementById('searchInput');
64        const terminartInputs = document.querySelectorAll('input[name="type[]"]');
65        const hostInputs = document.querySelectorAll('input[name="host"]');
66        const topicInputs = document.querySelectorAll('input[name="topics[]"]');
67        const loadMore = document.getElementById('loadmore');
68        const loadMoreButton = document.getElementById('loadtermine');
69        const abroadInputs = document.querySelectorAll('input[name="countryfilter"]');
70
71        if (abroadInputs.length > 0) {
72            abroadInputs.forEach((el) => {
73                el.addEventListener('change', function() {
74                    if (el.checked) {
75                        el.setAttribute('checked', 'checked');
76                    } else {
77                        el.removeAttribute('checked');
78                    }
79                    requestParams.country = el.value;
80                    reload();
81                })
82            })
83        }
84
85        // For radio buttons (where only one can be selected)
86        if (hostInputs.length > 0) {
87            // Initialize with any pre-selected value
88            hostInputs.forEach((el) => {
89                if (el.checked) {
90                    requestParams.host = el.value;
91                }
92            });
93
94            // Handle changes
95            hostInputs.forEach((el) => {
96                el.addEventListener('change', function() {
97                    // For radio buttons, just set the value directly - no need for else case
98                    // since only one can be checked at a time
99                    requestParams.host = el.value;
100                    reload();
101                });
102            });
103        }
104
105        if ( terminartInputs.length > 0 ) {
106            let terminArtArray = [];
107            terminartInputs.forEach((el) => {
108                el.addEventListener('change', function() {
109                    if(el.checked) {
110                        el.setAttribute('checked', 'checked');
111                        terminArtArray.push(el.value);
112                    } else {
113                        el.removeAttribute('checked');
114                        terminArtArray = terminArtArray.filter((type) => type !== el.value);
115                    }
116                    types = terminArtArray.join(',');
117                    reload();
118                });
119            });
120        }
121
122        if ( topicInputs.length > 0 ) {
123            let topicArray = [];
124            topicInputs.forEach((el) => {
125                el.addEventListener('change', function() {
126                    if(el.checked) {
127                        el.setAttribute('checked', 'checked');
128                        topicArray.push(el.value);
129                    } else {
130                        el.removeAttribute('checked');
131                        topicArray = topicArray.filter((topic) => topic !== el.value);
132                    }
133                    topics = topicArray.join(',');
134                    reload();
135                });
136            });
137        }
138
139        searchInput.addEventListener('keyup', function(event) {
140            const searchValue = event.target.value;
141            filterSearchInput(searchValue);
142        })
143        searchInput.addEventListener('search', function(event) {
144            searchWord = '';
145            reload();
146        });
147
148        rangeTimeselects.forEach((el) => {
149            el.addEventListener('click', function(e) {
150                e.preventDefault();
151                document.querySelectorAll('button.timeselect.range').forEach((el) => {
152                    el.classList.remove('active');
153                })
154                if(el.classList.contains('active')) {
155                    el.classList.remove('active');
156                }
157                else {
158                    el.classList.add('active');
159                }
160                reload();
161            })
162        });
163
164        dateTimeselects.forEach((el) => {
165            el.addEventListener('click', function(e) {
166                e.preventDefault();
167                document.querySelectorAll('button.timeselect.date').forEach((el) => {
168                    el.classList.remove('active');
169                })
170                if(el.classList.contains('active')) {
171                    el.classList.remove('active');
172                } else {
173                    el.classList.add('active');
174                }
175                const type = el.dataset.time;
176                switch (type) {
177                    case 'today':
178                        const today = new Date();
179                        picker.setDateRange(new Date(), new Date());
180                        picker.hide();
181                        break;
182                    case 'week':
183                        picker.clearSelection();
184                        // caclulate start and end of the current week
185                        // week starts on monday and ends on sunday
186                        const currentDate = new Date();
187                        const currentDay = currentDate.getDay();
188                        const daysTillMonday = currentDay === 0 ? -6 : 1 - currentDay;
189                        const mondayThisWeek = new Date(currentDate)
190                        mondayThisWeek.setDate(currentDate.getDate() + daysTillMonday);
191                        const sundayThisWeek = new Date(mondayThisWeek);
192                        sundayThisWeek.setDate(mondayThisWeek.getDate() + 6);
193
194                        picker.setDateRange(mondayThisWeek, sundayThisWeek);
195                        picker.hide();
196                        break;
197                    case 'nextweek':
198                        // caclulate start and end of the next week
199                        // week starts on monday and ends on sunday
200                        const baseDate = new Date();
201                        const baseDay = baseDate.getDay();
202                        const daysTillNextMonday = (baseDay === 0 ? -6 : 1 - baseDay) + 7;
203                        const mondayNextWeek = new Date(baseDate);
204                        mondayNextWeek.setDate(baseDate.getDate() + daysTillNextMonday);
205                        const sundayNextWeek = new Date(mondayNextWeek);
206                        sundayNextWeek.setDate(mondayNextWeek.getDate() + 6);
207
208                        picker.setDateRange(mondayNextWeek, sundayNextWeek);
209                        picker.hide();
210                        break;
211                    case 'all':
212                        let now = new Date().getTime();
213                        picker.clearSelection();
214                        picker.hide();
215                        fromField.value = '';
216                        toField.value = '';
217                        reload();
218                        break;
219                }
220                //reload();
221            })
222        });
223        filterSearchInput = (value) => {
224            searchWord = value;
225
226            clearTimeout(searchDebounceTimer)
227
228            searchDebounceTimer = setTimeout(function() {
229                clearFiltersForSearch();
230                resetAllFiltersInFrontend();
231                picker.clearSelection();
232                reload();
233            }, 1300)
234        }
235
236        resetAllFiltersInFrontend = () => {
237            filters = [
238                terminartInputs,
239                hostInputs,
240                topicInputs,
241                dateTimeselects,
242                rangeTimeselects
243            ]
244            filters.forEach((filterType) => {
245                filterType.forEach((filter) => {
246                    const type = filter.getAttribute('type');
247
248                    if (type === 'checkbox') {
249                        filter.checked = false;
250                    }
251                    else if (type === 'radio') {
252                        filter.checked = false;
253                    }
254                    else if (type === null) {
255                        filter.classList.remove('active');
256                        removeActiveStateInCalendar = true;
257                    }
258                })
259            })
260        }
261
262        clearFiltersForSearch = () => {
263            topics = '';
264            types = '';
265            host = null;
266            range = 0;
267            fromField.value = '';
268            toField.value = '';
269        }
270    }
271
272    /**
273     * Filter search input
274     * Debounce the search input to avoid multiple requests
275     *
276     * If a search is triggered, all other filters will be cleared
277     */
278
279    // function filterSearchInput(value) {
280    //     searchWord = value;
281
282
283    // }
284
285    function reload() {
286        const loadMoreDiv = document.getElementById('loadmore');
287        const params = {
288            type: 98877,
289            offset: 0,
290            limit: 10,
291            mode: 'replace',
292            range: 0,
293            storagePids: loadMoreDiv.dataset.storagePids || '',
294            detuid: loadMoreDiv.dataset.detuid || '',
295            catlist: loadMoreDiv.dataset.catlist || '',
296            from: fromField ? fromField.value : '',
297            to: toField ? toField.value: '',
298            host: requestParams.host ?? '',
299            country: requestParams.country ?? null,
300            searchWord: searchWord || '',
301            types: types || '',
302            topics: topics || ''
303        };
304
305        $('button.timeselect.range').each(function (){
306            if($(this).hasClass('active')) {
307                if($(this).data('range') != '0') params.range = $(this).data('range');
308            }
309        });
310        loadMore(params);
311    }
312
313    function loadMore(params) {
314        const loadingCircle = document.getElementById('loadingCircle')
315        loadingCircle.classList.remove('d-none');
316
317        requestParams = {...requestParams, ...params};
318
319
320        const urlParams = new URLSearchParams();
321
322        Object.entries(requestParams).forEach(([key, value]) => {
323            if (value !== undefined && value !== null && value !== "undefined" && value !== "") {
324                urlParams.set(key, value);
325            }
326        })
327
328
329        // base url
330        //var url = "/?type=98877&pos="+pos+"&num="+num+"&mode="+mode+"&range="+range+"&idlist="+idlist+"&detuid="+detuid;
331        if (lastFoundEvents) lastFoundEvents.remove();
332        $.ajax({
333            url: '/?'+ urlParams.toString(),
334            dataType: 'json'
335        })
336        .fail(function(response) {
337            console.log('error' + JSON.stringify(response));
338        })
339        .done(function(response) {
340            const data = response.html;
341            const count = response.count;
342
343            if (requestParams.mode === 'replace') {
344                document.querySelectorAll('.event-card').forEach((el) => el.remove());
345                requestParams.mode = 'append';
346            }
347
348            if(data !== '###NOROWS###') {
349                const loadMore = document.getElementById('loadmore');
350                if (loadMore) {
351                    loadMore.insertAdjacentHTML('beforebegin', data);
352                }
353
354                // Ladeindikator entfernen
355                const loadingCircle = document.getElementById('loadingCircle');
356                if (loadingCircle) {
357                    loadingCircle.classList.add('d-none');
358                }
359
360                const eventCards = document.querySelectorAll('.event-card');
361
362                const nextOffset = requestParams.offset + requestParams.limit;
363
364                loadMoreButton = loadMore.querySelector('#loadtermine');
365                if (count < requestParams.limit) {
366                    loadMoreButton.removeAttribute('onclick');
367                    loadMoreButton.setAttribute('disabled', 'disabled');
368                    loadMoreButton.style.display = 'none';
369                } else {
370                    loadMoreButton.removeAttribute('disabled');
371                    loadMoreButton.style.display = '';
372                    loadMoreButton.textContent = 'Weitere Termine laden';
373                    loadMoreButton.setAttribute('onclick',
374                        `javascript:TerminFilter.handleLoadMoreClick({
375                            offset: ${nextOffset},
376                            limit: 10,
377                            mode: 'append'
378                        })`
379                    );
380                }
381
382            } else {
383                const loadMore = document.getElementById('loadmore');
384                const loadMoreButton = loadMore.querySelector('#loadtermine');
385                const loadingCircle = document.getElementById('loadingCircle');
386                loadMoreButton.removeAttribute('onclick');
387                loadMoreButton.setAttribute('disabled', 'disabled');
388                loadMoreButton.style.display = 'none';
389                if (loadingCircle) {
390                    loadingCircle.classList.add('d-none');
391                }
392            }
393        })
394    }
395
396    return {
397        init: function() {
398            document.addEventListener('DOMContentLoaded', function() {
399                fromField = document.querySelector('input#fromDate');
400                toField = document.querySelector('input#toDate');
401
402                if (document.querySelectorAll('.events').length) {
403                    initializeDatepicker();
404                    setEventListeners();
405                    const loadMore = document.getElementById('loadmore');
406                    if (loadMore) {
407                        requestParams = {
408                            ...requestParams,
409                            storagePids: loadMore.dataset.storagePids || '',
410                            detuid: loadMore.dataset.detuid || '',
411                            catlist: loadMore.dataset.catlist || '',
412                            from: loadMore.dataset.from || '',
413                            to: loadMore.dataset.to || '',
414                        }
415                    }
416                }
417            })
418        },
419        // initial load more call and after filtering
420        // nice to have: after filtering only show loadmore button if there are more than $numberPerPage events
421        handleLoadMoreClick: function(params) {
422            loadMore(params);
423        }
424
425    }
426})();
427
428TerminFilter.init();
429

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.