PageSourceSearch

https://www.amstetten.at/wp2021/wp-content/plugins/falke-vadb-amst…/js/falke_vadb_am.js?ts=6ab58ff48af322026

js amstetten.at collected 2026-09-24 23:53:36 UTC 38,651 bytes, 754 lines download raw bytes

1const DEV = false; // false in production
2const VERBOSE = false; // false in production
3
4// document.addEventListener('DOMContentLoaded', function() {
5//     const form = document.querySelector('#falke-events-search-form');
6//     let isPrefilled = false;
7
8//     if (form) {
9//         const inputs = form.querySelectorAll('input:not([type="checkbox"]), select, textarea');
10//         const checkboxes = form.querySelectorAll('input[type="checkbox"]');
11//         inputs.forEach(input => {
12//             // if input type is hidden check if the value if different from 1 (the default)
13//             // if(VERBOSE) console.log(input.type, input.value);
14//             if (input.type === 'hidden') {
15//                 if(input.value != '1') {
16//                     if(VERBOSE) console.log("hidden: ", input, input.value);
17//                     isPrefilled = true;
18//                 }
19//             } else if (input.value) {
20//                 if(VERBOSE) console.log("input: ", input, input.value);
21//                 isPrefilled = true;
22//             }
23//         });
24
25//         // Check checkboxes for :checked
26//         checkboxes.forEach(checkbox => {
27//             if (checkbox.checked) {
28//                 if(VERBOSE) console.log("checkbox: ", checkbox, checkbox.checked);
29//                 isPrefilled = true;
30//             }
31//         });
32
33//         if (isPrefilled) {
34//             if(VERBOSE) console.log('Form fields are prefilled from browser cache.');
35//             // Optionally, you can trigger the form submission here
36//             // form.submit();
37//         } else {
38//             if(VERBOSE) console.log('Form fields are not prefilled.');
39//         }
40//     }
41// });
42
43jQuery(document).ready(function () {
44
45    if(DEV) console.profile("falke_vadb_am"); 
46
47    // console.log, console.info, console.debug, console.warn, console.error
48    if(VERBOSE) console.info("loaded js file falke_vadb_am.js");
49
50    // search-form datepicker
51    // check if element exists
52    if(jQuery("#falke-search-form-events-date").length > 0) {
53        let toggleDates = true; // toggle between true/false to set 1st or 2nd date
54        let startDate = "";
55        let endDate = "";
56        jQuery("#falke-search-form-events-date").daterangepicker({
57            initialText: "Datum wählen",
58            icon: "", // custom icon like the others that changes when it is active ;)
59            applyButtonText: "Schließen", // Anwenden
60            clearButtonText: "Datum zurücksetzen",
61            cancelButtonText: "", // Abbrechen
62            rangeSplitter: " - ",
63            dateFormat: "d.m.yy", // formats: http://api.jqueryui.com/datepicker/#utility-formatDate
64            altFormat: "yy-mm-dd",
65            verticalOffset: 20,
66            datepickerOptions: {
67                // see https://api.jqueryui.com/datepicker/#options
68                numberOfMonths: 1,
69                // autoSize: true, // no effect?
70                minDate: new Date(),
71                maxDate: null,
72                // weekHeader: "W",
73                firstDay: 1, // Monday
74                regional: "de-AT",
75                dayNames: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
76                dayNamesMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
77                // don't set => error in January!
78                monthNames: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
79                // monthNamesShort: ["Jän", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
80                onSelect: function(dateText, inst) {
81                    // if(VERBOSE) console.log("onSelect", dateText, inst);
82                    // month + 1 because month is 0 based
83                    let dateString = `${inst.selectedYear}-${inst.selectedMonth + 1}-${inst.selectedDay}`;
84                    if(toggleDates) {
85                        startDate = new Date(dateString);
86                    } else {
87                        endDate = new Date(dateString);
88                    }
89                    toggleDates = !toggleDates; // switch to the other date the next time
90    
91                    // not working because this also automatically resets the UI => work with open/close
92                    // jQuery('#falke-search-form-events-date').daterangepicker('setRange', {start: startDate, end: endDate});
93                }
94            },
95            presetRanges: [
96                {
97                    text: "Heute",
98                    dateStart: function () {
99                        return moment();
100                    },
101                    dateEnd: function () {
102                        return moment();
103                    }
104                }, {
105                    text: "Morgen",
106                    dateStart: function () {
107                        return moment().add(1, "days");
108                    },
109                    dateEnd: function () {
110                        return moment().add(1, "days");
111                    }
112                }, {
113                    text: "Am Wochenende",
114                    dateStart: function () {
115                        return moment().day(6);
116                    },
117                    dateEnd: function () {
118                        return moment().day(7);
119                    }
120                }
121            ],
122            "open": function(event, data) {
123                // reset dates and where we were (date 1 or date 2 = first or second click)
124                startDate = "";
125                endDate = "";
126                toggleDates = true;
127
128                // check if the datepicker elements are tabbable
129                let buttons = document.querySelectorAll('.comiseo-daterangepicker.ui-widget-content ul div');
130                buttons.forEach(function(button) {
131                    // if tabindex = -1 set it to 0 (regular tab order)
132                    if(button.getAttribute("tabindex") === "-1") {
133                        button.setAttribute("tabindex", "0");
134                    }
135                    // set title to the text content of the node
136                    // but only if there is no title attribute set already
137                    if(!button.hasAttribute("title")) {
138                        let text = button.textContent;
139                        text = text.charAt(0).toLowerCase() + text.slice(1);
140                        button.setAttribute("title", `nach Events ${text} suchen`);
141
142                        button.addEventListener("keydown", function(event) {
143                            if(event.key === "Enter") {
144                                button.click();
145                            }
146                        });
147                    }
148                });
149
150                // if the contents of .comiseo-daterangepicker-calendar changes, make sure the links are tabbable
151                let calendar = document.querySelector('.comiseo-daterangepicker-calendar');
152                let observer = new MutationObserver(function(mutations) {
153                    mutations.forEach(function(mutation) {
154                        if(mutation.addedNodes.length > 0) {
155                            let addedNodes = mutation.addedNodes;
156                            addedNodes.forEach(function(addedNode) {
157                                let children_prev_next = addedNode.querySelectorAll('.ui-widget-header a');
158                                children_prev_next.forEach(function(a) {
159                                    // if the element does not have the class .ui-state-disabled
160                                    if(!a.classList.contains("ui-state-disabled" && a.getAttribute("tabindex") === "-1")) {
161                                        // if tabindex = -1 set it to 0 (regular tab order)
162                                        a.setAttribute("tabindex", "0");
163
164                                        // on keydown on a, if it is the enter key, click the a element
165                                        a.addEventListener("keyup", function(event) {
166                                            if(event.key === "Enter") {
167                                                a.click();
168                                            }
169                                        });
170                                    }
171                                });
172
173                                // can be deleted
174                                // let children_days = addedNode.querySelectorAll('td a.ui-state-default');
175                                // if(VERBOSE) console.log("children_days observer", children_days);
176                                // children_days.forEach(function(a) {
177                                //     // on keydown on a, if it is the enter key, click the a element
178                                //     // if(VERBOSE) console.log("a", a);
179                                //     a.addEventListener("keyup", function(event) {
180                                //         if(event.key === "Enter") {
181                                //             if(VERBOSE) console.log("pressed enter observer")
182                                //             // a.click();
183                                //             // a.focus();
184                                //         }
185                                //     });
186                                // });
187
188                                // set focus to .ui-datepicker-current-day
189                                document.querySelector('.ui-datepicker-current-day a').focus();
190                            });
191                        }
192                    });
193                });
194                // Observe changes to the child elements of the calendar
195                observer.observe(calendar, { childList: true, subtree: true });
196
197                // set tabbable to a by default
198                let children_prev_next = document.querySelectorAll('.comiseo-daterangepicker-calendar .ui-widget-header a');
199                children_prev_next.forEach(function(a) {
200                    // if the element does not have the class .ui-state-disabled
201                    if(!a.classList.contains("ui-state-disabled") && !a.hasAttribute("tabindex")) {
202                        // if tabindex = -1 set it to 0 (regular tab order)
203                        a.setAttribute("tabindex", "0");
204                        
205                        // on keydown on a, if it is the enter key, click the a element
206                        a.addEventListener("keydown", function(event) {
207                            if(event.key === "Enter") {
208                                a.click();
209                            }
210                        });
211                    }
212                });
213
214                // set the focus to the .comiseo-daterangepicker div that contains the datepicker
215                // this is necessary to be able to use the keyboard to navigate through the datepicker
216                // jQuery('.comiseo-daterangepicker.ui-front').focus();
217                if(VERBOSE) console.log(document.querySelector('.comiseo-daterangepicker.ui-widget-content ul div'));
218                document.querySelector('.comiseo-daterangepicker.ui-widget-content ul div').focus();
219                if(VERBOSE) console.log("currently focused element: ", document.activeElement);
220            },
221            "close": function(event, data) {
222                // on close set the range to the previously selected dates
223                // this is necessary to not need the button to apply the dates
224                // if start date is later than end date switch the dates (because the user clicked the other way, last date first)
225                // but don't switch if there is no endDate set, meaning the user only clicked on 1 day
226                if(endDate !== "" && startDate >
226 endDate) {
227                    let temp = startDate;
228                    startDate = endDate;
229                    endDate = temp;
230                }
231                jQuery('#falke-search-form-events-date').daterangepicker('setRange', {start: startDate, end: endDate});
232
233                // set focus to .comiseo-daterangepicker-triggerbutton ui-button
234                // this is necessary to be able to use the keyboard to navigate through the datepicker
235                jQuery('.comiseo-daterangepicker-triggerbutton').focus();
236            }
237        });
238
239        falke_vadb_check_session_storage_and_request();
240    }
241    
242    // search-form multiselect
243    // get element with class falke-search-multiselect-trigger-container
244    let multiselectContainers = document.querySelectorAll(".falke-search-form-events-multiselect");
245    if(multiselectContainers) {
246        multiselectContainers.forEach(function(multiselectContainer) {
247            let triggerContainer = multiselectContainer.querySelector(".falke-search-multiselect-trigger-container");
248            triggerContainer.addEventListener("click", function(event) {
249                let checkboxes = multiselectContainer.querySelector(".falke-search-checkboxes");
250                // if multiselectContainer has class falke-search-checkboxes-expanded it is expanded
251                let expanded = multiselectContainer.classList.contains("falke-search-checkboxes-expanded");
252                if (!expanded) {
253                    checkboxes.style.display = "block";
254                    // wait before adding class
255                    setTimeout(() => {
256                        multiselectContainer.classList.add("falke-search-checkboxes-expanded");
257                    }, 100);
258                } else {
259                    checkboxes.style.display = "none";
260                    multiselectContainer.classList.remove("falke-search-checkboxes-expanded");
261                }
262            });
263
264            // add event listener to checkboxes
265            let checkboxes = multiselectContainer.querySelectorAll(".falke-search-checkboxes input");
266            // don't send the form on tapping "ENTER" on the keyboard to select the checkbox
267            checkboxes.forEach(function(checkbox) {
268                checkbox.addEventListener("keydown", function(event) {
269                    if(event.key === "Enter") {
270                        event.preventDefault();
271                        checkbox.checked = !checkbox.checked;
272                        let changeEvent = new Event("change");
273                        checkbox.dispatchEvent(changeEvent);
274                    }
275                });
276            });
277        });
278        
279        // when using TAB to navigate, close the multiselect if the user tabs out of the multiselect
280        let form = document.querySelector("#falke-events-search-form");
281        if(form) {
282            form.addEventListener("keyup", function(event) {
283                if(event.key === "Tab") {
284                    // if there is a multiselect opened (.falke-search-checkboxes-expanded) and the currently focused element is not inside the multiselect, close the multiselect
285                    let currentlyExpandedMultiselect = document.querySelector(".falke-search-checkboxes-expanded");
286                    if(currentlyExpandedMultiselect) {
287                        let checkboxes = currentlyExpandedMultiselect.querySelector(".falke-search-checkboxes");
288                        let triggerContainer = currentlyExpandedMultiselect.querySelector(".falke-search-multiselect-trigger-container");
289                        if (!triggerContainer.contains(document.activeElement) && !checkboxes.contains(document.activeElement) ) {
290                            checkboxes.style.display = "none";
291                            currentlyExpandedMultiselect.classList.remove("falke-search-checkboxes-expanded");
292                        }
293                    }
294                }
295            });
296        }
297        
298        // only on pages where a multiselect is present
299        // Close all multiselect dropdowns when clicking outside
300        document.addEventListener("click", function(event) {
301            // check if page contains the class falke-search-checkboxes-expanded
302            let currentlyExpandedMultiselect = document.querySelector(".falke-search-checkboxes-expanded");
303            if(currentlyExpandedMultiselect) {
304                // there is currently a multiselect expanded
305                // there can be different multiselects opened but only one at a time
306                // only close the multiselect if you click outside of the currently opened multiselect
307
308                let checkboxes = currentlyExpandedMultiselect.querySelector(".falke-search-checkboxes");
309                let triggerContainer = currentlyExpandedMultiselect.querySelector(".falke-search-multiselect-trigger-container");
310                if (!triggerContainer.contains(event.target) && !c
310heckboxes.contains(event.target) && !event.target.classList.contains("searchButton") && !event.target.classList.contains("resetButton")) {
311                    // if(VERBOSE) console.log("click on target: ", event.target);
312                    checkboxes.style.display = "none";
313                    currentlyExpandedMultiselect.classList.remove("falke-search-checkboxes-expanded");
314                }
315            }
316        });
317
318        // add event listener to checkboxes
319        let checkboxes = document.querySelectorAll(".falke-search-checkboxes input");
320        if(checkboxes) {
321            // on load of page -> update the multiselect in case someone returns from an event page (with form data still prefilled)
322            falke_reapply_form_data_on_load(3);
323
324            // add change event listener to checkboxes
325            checkboxes.forEach(function(checkbox) {
326                checkbox.addEventListener("change", function(event) {
327                    // if(VERBOSE) console.log("checkbox changed", event.target);
328                    // get data attribute data-search-for of parent .falke-search-checkboxes
329                    let searchFor = event.target.closest(".falke-search-checkboxes").dataset.searchFor;
330                    if(searchFor === "event_categories") {
331                        falke_vadb_update_multiselect_number();
332                    } else if(searchFor === "event_target_group") {
333                        falke_vadb_update_multiselect_number("event_target_group", "Geeignet für", "Geeignet für");
334                    } else {
335                        console.error("searchFor not found", eventTarget.closest(".falke-search-checkboxes"));
336                    }
337                });
338            });
339        }
340    }
341
342    // search-form submit
343    let searchForm = jQuery("#falke-events-search-form");
344    if(searchForm) {
345        searchForm.submit(function(e) {
346            // custom search not default one
347            e.preventDefault();
348
349            // can be removed
350            // text input
351            // let event_search_term = jQuery("#falke-events-search-input").val();
352
353            // // event_dates
354            // let event_dates = jQuery("#falke-search-form-events-date").daterangepicker("getRange");
355            // let event_date_start = "";
356            // let event_date_end = "";
357            // if(event_dates !== null) {
358            //     event_date_start = moment(event_dates.start).format("YYYY-MM-DD");
359            //     event_date_end = moment(event_dates.end).format("YYYY-MM-DD");
360            // }
361
362            // // event_category
363            // let searchCategoryInputs = jQuery("#falke-search-events-categories input:checked");
364            // let searchCategoryIds = [];
365            // searchCategoryInputs.each(function() {
366            //     searchCategoryIds.push(jQuery(this).val());
367            // });
368            // let event_categories = searchCategoryIds.join(";");
369
370            // // event_target_group
371            // let searchTargetGroupInputs = jQuery("#falke-search-events-target-groups input:checked");
372            // let searchTargetGroupIds = [];
373            // searchTargetGroupInputs.each(function() {
374            //     searchTargetGroupIds.push(jQuery(this).val());
375            // });
376            // let event_target_groups = searchTargetGroupIds.join(";");
377
378            // reset page number
379            jQuery('#falke-events-search-form input[name="page"]').val(1);
380
381            // get data
382            let { event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, page } = falke_vadb_collect_form_data();
383            
384            // submit search form
385            falke_vadb_submit_search_form(event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, true, page);
386        });
387    }
388
389    // search-form reset
390    let resetButton = jQuery("#falke-events-search-form .search-reset");
391    if(resetButton) {
392        resetButton.click(function(e) {
393            // usual default stuff of unsetting all input...
394
395            // reset datepicker
396            jQuery("#falke-search-form-events-date").daterangepicker("clearRange");
397
398            // reset page number
399            // reset page number
400            jQuery('#falke-events-search-form input[name="page"]').val(1);
401
402            // force reset of multiselect number to 0 (without force you would need a timeout which we want to avoid)
403            falke_vadb_update_multiselect_number("event_categories", "Kategorie", "Alle Kategorien", true);
404            falke_vadb_update_multiselect_number("event_target_group", "Geeignet für", "Geeignet für", true);
405
406            // don't get data from DOM because it might not be reset yet
407            // let { event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, page } = falke_vadb_collect_form_data();
408            
409            // reset session storage
410            sessionStorage.removeItem('falkeEventSearchFormData');
411
412            // submit search form
413            falke_vadb_submit_search_form("", "", "", "", "", true, 1);
414        });
415    }
416
417    // on click on load more
418    falke_vadb_clickhandler_load_more_button();
419
420    if(DEV) console.profileEnd("falke_vadb_am");
421});
422
423function falke_vadb_clickhandler_load_more_button() {
424    // if(VERBOSE) console.log("clickhandler load more button");
425    let loadMoreButton = jQuery("#falke-events-load-more");
426    if(loadMoreButton) {
427        loadMoreButton.click(function(e) {
428            e.preventDefault();
429            
430            let { event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, page } = falke_vadb_collect_form_data();
431            falke_vadb_submit_search_form(event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, false, page );
432        });
433        return true;
434    } else {
435        return false;
436    }
437}
438
439function falke_vadb_collect_form_data() {
440    // text input
441    let event_search_term = jQuery("#falke-events-search-input").val();
442
443    // event_dates
444    let event_dates = jQuery("#falke-search-form-events-date").daterangepicker("getRange");
445    let event_date_start = "";
446    let event_date_end = "";
447    if(event_dates !== null) {
448        event_date_start = moment(event_dates.start).format("YYYY-MM-DD");
449        event_date_end = moment(event_dates.end).format("YYYY-MM-DD");
450    }
451
452    // event_category
453    let searchCategoryInputs = jQuery("#falke-search-events-categories input:checked");
454    let searchCategoryIds = [];
455    searchCategoryInputs.each(function() {
456        searchCategoryIds.push(jQuery(this).val());
457    });
458    let event_categories = searchCategoryIds.join(";");
459
460    // event_target_group
461    let searchTargetGroupInputs = jQuery("#falke-search-events-target-groups input:checked");
462    let searchTargetGroupIds = [];
463    searchTargetGroupInputs.each(function() {
464        searchTargetGroupIds.push(jQuery(this).val());
465    });
466    let event_target_groups = searchTargetGroupIds.join(";");
467
468    // page
469    let page = jQuery('#falke-events-search-form input[name="page"]').val();
470    if(VERBOSE) console.log("collect form data: ", { event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, page });
471
472    return { event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, page };
473}
474
475async function falke_vadb_submit_search_form(event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, replace = true, page = 1, with_row = false, skip_setting_session_data = false) {
476    // if replace false it is about loading more content => increase page number
477    if(!replace) page++;
478
479    // check how many .falke-events-custom-highlight are on the site
480    n_custom_highlights = jQuery(".falke-events-custom-highlight").length;
481    ppp = 12 - n_custom_highlights;
482
483    if(VERBOSE) console.log("submit search form: ", { "event_search_term": event_search_term, 
484        "event_date_start": event_date_start, 
485        "event_date_end": event_date_end, 
486        "event_categories": event_categories, 
487        "event_target_groups": event_target_groups,
488        "ppp": ppp,
489        "page": page,
490        "with_row": with_row
491    });
492
493    return new Promise((resolve, reject) => {
494        // submit ajax call to request events that match the search criteria
495        jQuery.ajax({
496            type: "GET",
497            dataType: "json",
498            url: falke_vadb_am_ajax.ajax_url,
499            data: {
500                action: "falke_vadb_search_events",
501                event_search_term: event_search_term,
502                event_date_start: event_date_start,
503                event_date_end: event_date_end,
504                event_categories: event_categories,
505                event_target_groups: event_target_groups,
506                page: page,
507                ppp: ppp,
508                with_load_more_button: false,
509                with_row: with_row
510            },
511            success: function(response) {
512                if(VERBOSE) console.log(response)
513                if(response.success) {
514                    let html = response.data.html;
515                    let more_results = response.data.more_results;
516                    if(replace) {
517                        // remove all children of div in case there are multiple rows
518                        jQuery(".falke-event-overview .falke-events-content .row").empty();
519            
520                        // replace content of div with response
521                        jQuery(".falke-event-overview .falke-events-content .row").html(html);
522            
523                        // reset page number
524                        jQuery('#falke-events-search-form input[name="page"]').val(1);
525                    } else {
526                        // append to existing content
527                        jQuery(".falke-event-overview .falke-events-content .row").append(html);
528        
529                        // increase page number
530                        jQuery('#falke-events-search-form input[name="page"]').val(parseInt(page));
531                    }
532    
533                    // check if there are more results ready to be loaded => if so display the load more button, else hide it
534                    if(more_results) {
535                        if(VERBOSE) console.log("more results available, showing load more button");
536                        let loadMoreButtonHtml = response.data.load_more_button_html;
537                        if(loadMoreButtonHtml) {
538                            // check if the button is already present - if so nothing needs to be done, else add it to the DOM and attach clickhandler
539                            if(!jQuery(".falke-events-load-more-container").length) {
540                                if(VERBOSE) console.log("load more button not present on page, adding it now");
541                                // add load more button
542                                jQuery(".falke-event-overview").append(loadMoreButtonHtml);
543                                // add clickhandler to load more button
544                                falke_vadb_clickhandler_load_more_button();
545                            } else {
546                                if(VERBOSE) console.log("load more button already present on page, showing it now");
547                                // show already present load more html that could be hidden
548                                jQuery(".falke-events-load-more-container").show();
549                            }
550                        } else {
551                            console.error("load more button html not found in response", response);
552                        }
553                    } else {
554                        if(VERBOSE) console.log("no more results available, hiding load more button");
555                        // hide load more button container
556                        jQuery(".falke-events-load-more-container").hide();
557                    }
558        
559                    // can be deleted
560                    // check if result contains "Keine Veranstaltungen gefunden." => old, unreliable version
561                    // let noEventsFound = jQuery(".falke-event-overview .falke-events-content").text().includes("Keine Veranstaltungen gefunden.");
562                    // if(noEventsFound) {
563                    //     // hide load more button
564                    //     jQuery(".falke-events-load-more-container").hide();
565                    // }
566        
567                    falke_vadb_update_multiselect_number();
568                    falke_vadb_update_multiselect_number("event_target_group", "Geeignet für", "Geeignet für");
569    
570                    if(!skip_setting_session_data) {
571                        falke_vadb_update_session_storage();
572                    }
573                    resolve(response);
574                } else {
575                    console.error("response not successful", response);
576                    reject(response);
577                }
578            },
579            error: function(response) {
580                console.error("error", response);
581                reject(response);
582            }
583        });
584    });
585}
586
587function falke_vadb_update_multiselect_number(searchFor = "event_categories", singularName = "Kategorie", pluralName = "Alle Kategorien", forceResetToZero = false) {
588    // get container with checkboxes inside
589    let searchCheckboxesContainer = document.querySelector(`.falke-search-checkboxes[data-search-for='${searchFor}']`);
590    // chount how many checkboxes are checked
591    let checkedItems = searchCheckboxesContainer.querySelectorAll("input:checked").length;
592    // get the button that displays how many are currently checked
593    let currentlySelectedButton = document.querySelector(`.falke-search-multiselect-trigger-container[data-search-for='${searchFor}'] button`);
594    if(checkedItems > 0 && !forceResetToZero) {
595        // create span element that contains the number of checked items
596        let spanElement = document.createElement('span');
597        spanElement.className = 'falke-search-count';
598        spanElement.textContent = checkedItems;
599
600        currentlySelectedButton.innerHTML = "";
601        currentlySelectedButton.appendChild(document.createTextNode(`${singularName} `));
602        currentlySelectedButton.appendChild(spanElement);
603        // document.querySelectorAll('.falke-search-form-events-multiselect.falke-categories')[0].classList.add("falke-search-form-events-multiselect-active");
604        currentlySelectedButton.closest(".falke-search-form-events-multiselect").classList.add("falke-search-form-events-multiselect-active");
605    } else {
606        currentlySelectedButton.textContent = pluralName;
607        // document.querySelectorAll('.falke-search-form-events-multiselect.falke-categories')[0].classList.remove("falke-search-form-events-multiselect-active");
608        currentlySelectedButton.closest(".falke-search-form-events-multiselect").classList.remove("falke-search-form-events-multiselect-active");
609    }
610}
611
612function falke_reapply_form_data_on_load(retries = 3) {
613    let checkedItems = document.querySelectorAll('.falke-search-checkboxes input:checked').length;
614    if (checkedItems > 0) {
615        falke_vadb_update_multiselect_number();
616        falke_vadb_update_multiselect_number("event_target_group", "Geeignet für", "Geeignet für");
617    } else if (retries > 0) {
618        setTimeout(() => {
619            falke_reapply_form_data_on_load(retries - 1);
620        }, 500);
621    } else {
622        if(VERBOSE) console.error('Failed to find checked items after 3 retries');
623    }
624}
625
626function falke_vadb_update_session_storage() {
627    // Save form data to session storage on form submit TODO keep?
628    const last_submit = {};
629    const form = document.querySelector('#falke-events-search-form');
630    if(form) {
631        if(VERBOSE) console.log("form found");
632        
633        // Save all form data except checkboxes
634        new FormData(form).forEach((value, key) => {
635            last_submit[key] = value;
636        });
637
638        // Manually add checkbox values
639        const checkboxes_categories = form.querySelectorAll('#falke-search-events-categories input[type="checkbox"]');
640        last_submit["categories"] = [];
641        checkboxes_categories.forEach(checkbox => {
642            if(checkbox.checked) {
643                last_submit["categories"].push(checkbox.value);
644            }
645        });
646        const checkboxes_target_groups = form.querySelectorAll('#falke-search-events-target-groups input[type="checkbox"]');
647        last_submit["target_groups"] = [];
648        checkboxes_target_groups.forEach(checkbox => {
649            if(checkbox.checked) {
650                last_submit["target_groups"].push(checkbox.value);
651            }
652        });
653
654        sessionStorage.setItem('falkeEventSearchFormData', JSON.stringify(last_submit));
655
656        if(VERBOSE) console.log("set session data: ", last_submit);
657    }
658}
659
660async function falke_vadb_check_session_storage_and_request() {
661    // check where the user comes from
662    let referrer = document.referrer;
663    // if we have no referrer or the referrer does not contain /veranstaltungen/ (TODO find solution for browser back) reset the formData and start fresh
664    if(!referrer || referrer.indexOf("/veranstaltungen/") == -1) {
665        if(VERBOSE) console.log("no referrer found, resetting session storage");
666        sessionStorage.removeItem('falkeEventSearchFormData');
667        return;
668    } else {
669        if(VERBOSE) console.log("referrer found: ", referrer);
670    }
671
672    // check if session storage contains any values
673    let sessionData = sessionStorage.getItem('falkeEventSearchFormData');
674    if(sessionData) {
675        // parse the data
676        let formData = JSON.parse(sessionData);
677        if(VERBOSE) console.log("session data found: ", formData);
678
679        // get data
680        let { s, event_date, page, categories, target_groups } = formData;
681        event_date = event_date ? JSON.parse(event_date) : { start: "", end: "" };
682        event_date.start = event_date.start ? new Date(event_date.start) : "";
683        event_date.end = event_date.end ? new Date(event_date.end) : "";
684        page = parseInt(page);
685
686        // if any data is not empty
687        if(s != "" || event_date.start || page > 1 || (categories && categories.length > 0) || (target_groups && target_groups.length > 0)) {
688            if(VERBOSE) console.log("submit because session data found");
689
690            // ensure the correct values are all set in the form
691            // search text input
692            jQuery("#falke-events-search-input").val(s);
693            // datepicker
694            jQuery("#falke-search-form-events-date").daterangepicker("setRange", {start: event_date.start, end: event_date.end});
695            // checkboxes
696            if(categories && categories.length > 0) {
697                categories.forEach(category => {
698                    jQuery(`#falke-search-events-categories input[value="${category}"]`).prop("checked", true);
699                });
700            }
701            if(target_groups && target_groups.length > 0) {
702                target_groups.forEach(target_group => {
703                    jQuery(`#falke-search-events-target-groups input[value="${target_group}"]`).prop("checked", true);
704                });
705            }
706            // hidden page attribute
707            jQuery('#falke-events-search-form input[name="page"]').val(page);
708
709            if(VERBOSE) console.log("updated form with current values");
710
711            // submit search form
712            // if page is bigger than 1 load the content page by page
713            if(page > 1) {
714                if(VERBOSE) console.log("page > 1");
715                // submit search form
716                current_page = 1;
717                for (let i = 1; i <= page; i++) {
718                    // on the first page use replace = true, on the following pages use replace = false
719                    if(i == 1) {
720                        if(VERBOSE) console.log("loading page 1 with replace = true");
721                        await falke_vadb_submit_search_form(s, event_date.start, event_date.end, categories.join(";"), target_groups.join(";"), true, i, false, true);
722                    } else {
723                        if(VERBOSE) console.log("loading page ", i, " with replace = false");
724                        await falke_vadb_submit_search_form(s, event_date.start, event_date.end, categories.join(";"), target_groups.join(";"), false, i - 1, false, true);
725                    }                }
726            } else {
727                if(VERBOSE) console.log("loading page 1 with replace = true (only request)");
728                await falke_vadb_submit_search_form(s, event_date.start, event_date.end, categories.join(";"), target_groups.join(";"), true, page, false, true);
729            }
730
731            // try to scroll to the last event that was clicked
732            if(referrer) {
733                let url = new URL(referrer);
734                if(url) {
735                    let cleanURL = `${url.protocol}//${url.host}${url.pathname}`;
736                    let element = document.querySelector(`a[href="${cleanURL}"]`);
737                    if(element) {
738                        // element.scrollIntoView({ behavior: 'smooth' });
739                        const yOffset = -150;
740                        const y = element.getBoundingClientRect().top + window.scrollY + yOffset;
741                        window.scrollTo({top: y, behavior: 'smooth'});
742                    }
743                }
744            } else {
745                if(VERBOSE) console.log("no referrer found");
746            }
747        } else {
748            if(VERBOSE) console.log("no data found in session storage");
749        }
750        
751        // submit search form
752        // falke_vadb_submit_search_form(event_search_term, event_date_start, event_date_end, event_categories, event_target_groups, true, page);
753    }
754}

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.