1jQuery(document).ready(function ($){ 2function replacePlaceholder(str, num){ 3return str.replace(/%d/g, num); 4} 5function getFieldMessage($field, key, fallback, num){ 6let msg=$field.attr("data-msg-" + key)||fallback||""; 7if(num!==undefined){ 8msg=replacePlaceholder(msg, num); 9} 10return msg; 11} 12function setInvalidState($field, invalid){ 13const $controls=$field.find("input:not([type='hidden']), textarea, .rne-select-trigger"); 14if(!$controls.length) return; 15$controls.removeAttr("aria-invalid"); 16if(invalid){ 17$controls.first().attr("aria-invalid", "true"); 18}} 19function showFieldError($field, message){ 20const $errorMessage=$field.find(".error-message").first(); 21const $text=$errorMessage.find(".error-text"); 22if($text.length){ 23$errorMessage.find(".sr-only").text((window.rne_translations.forms.errorPrefix||"Fehler:") + " "); 24$text.text(message); 25}else{ 26$errorMessage.text(message); 27} 28$errorMessage.show(); 29setInvalidState($field, true); 30} 31function clearFieldError($field){ 32const $errorMessage=$field.find(".error-message").first(); 33const $text=$errorMessage.find(".error-text"); 34if($text.length){ 35$errorMessage.find(".sr-only").text(""); 36$text.text(""); 37}else{ 38$errorMessage.text(""); 39} 40$errorMessage.hide(); 41setInvalidState($field, false); 42} 43function initializeForm(formSelector){ 44const $form=$(formSelector); 45$form.attr("novalidate", true); 46const $submitButton=$form.find(".rne-submit-button"); 47const $formSteps=$form.find(".form-step"); 48const hasSteps=$formSteps.length > 0; 49let currentStep=1; 50const totalSteps=hasSteps ? $formSteps.length:1; 51let $captchaInput=$form.find('input[name="captcha_at_solution"]'); 52if(!$captchaInput.length){ 53$captchaInput=$("<input>", { 54type: "hidden", 55name: "captcha_at_solution" 56}).appendTo($form); 57} 58function fetchCaptcha(){ 59return KROT.getSolution().then((sol)=> { 60$captchaInput.val(JSON.stringify(sol)); 61return sol; 62}); 63} 64async function ensureFreshCaptcha(){ 65try { 66const cur=JSON.parse($captchaInput.val()||"{}"); 67if(!cur.expires||Date.now() > cur.expires - 15_000){ 68return fetchCaptcha(); 69} 70return cur; 71} catch (_){ 72return fetchCaptcha(); 73}} 74let captchaTimer=null; 75function startCaptchaWatchdog(sol){ 76clearTimeout(captchaTimer); 77if(!sol.expires) return; 78const delay=Math.max(sol.expires - Date.now() - 15_000, 30_000); 79captchaTimer=setTimeout(async ()=> { 80const newSol=await ensureFreshCaptcha(); 81startCaptchaWatchdog(newSol); 82}, delay); 83} 84$form.one("focusin", ":input:not([type='hidden']):not(:disabled)", async ()=> { 85try { 86const sol=await fetchCaptcha(); 87startCaptchaWatchdog(sol); 88} catch (err){ 89console.error("captcha bootstrap failed", err); 90}}); 91$form.on("remove", ()=> clearTimeout(captchaTimer)); 92function validateCheckbox($input){ 93const $field=$input.closest(".form-item"); 94clearFieldError($field); 95$field.removeClass("not-valid is-valid"); 96if($input.closest(".rne-multi-checkbox-group").length){ 97return validateMultiCheckbox($input.closest(".rne-multi-checkbox-group")); 98}else{ 99return validateSingleCheckbox($input); 100}} 101function validateSingleCheckbox($input){ 102const $field=$input.closest(".form-item"); 103if($input.prop("required")&&!$input.prop("checked")){ 104showFieldError($field, getFieldMessage($field, "required", window.rne_translations.forms.requiredField)); 105$field.addClass("not-valid"); 106return false; 107} 108$field.addClass("is-valid"); 109return true; 110} 111function validateMultiCheckbox($group){ 112const $field=$group.closest(".form-item"); 113const checkedCount=$group.find('input[type="checkbox"]:checked').length; 114const maxSelections=$field.data("max-selections")||Infinity; 115const minSelections=$field.data("required")===true ? 1:0; 116$field.removeClass("not-valid is-valid"); 117clearFieldError($field); 118if(checkedCount < minSelections){ 119showFieldError($field, getFieldMessage($field, "min", window.rne_translations.forms.minSelections, minSelections)); 120$field.addClass("not-valid"); 121return false; 122} 123else if(checkedCount > maxSelections){ 124showFieldError($field, getFieldMessage($field, "max", window.rne_translations.forms.maxSelections, maxSelections)); 125$field.addClass("not-valid"); 126return false; 127} 128$field.addClass("is-valid"); 129return true; 130} 131function validateSelect($input){ 132const $field=$input.closest(".form-item"); 133const $selectTrigger=$field.find(".rne-select-trigger"); 134$selectTrigger.removeClass("not-valid is-valid"); 135$field.removeClass("not-valid is-valid"); 136clearFieldError($field); 137const value=$input.val(); 138if($input.prop("required")&&!value){ 139showFieldError($field, getFieldMessage($field, "required", window.rne_translations.forms.requiredField)); 140$selectTrigger.addClass("not-valid"); 141$field.addClass("not-valid"); 142return false;
143} 144$selectTrigger.addClass("is-valid"); 145$field.addClass("is-valid"); 146return true; 147} 148function validateField($input){ 149const $field=$input.closest(".form-item"); 150const value=$input.val(); 151clearFieldError($field); 152$field.removeClass("not-valid is-valid"); 153if($input.attr("type")==="checkbox"){ 154return validateCheckbox($input); 155} 156if($input.attr("type")==="hidden"&&$input.closest(".rne-select-container").length){ 157return validateSelect($input); 158} 159if($input.prop("required")&&!value){ 160showFieldError($field, getFieldMessage($field, "required", window.rne_translations.forms.requiredField)); 161$field.addClass("not-valid"); 162return false; 163}else if(value){ 164switch ($input.attr("type")){ 165case "email": 166if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)){ 167showFieldError($field, getFieldMessage($field, "invalid", window.rne_translations.forms.invalidEmail)); 168$field.addClass("not-valid"); 169return false; 170} 171break; 172case "number": 173if(!/^\d+$/.test(value)){ 174showFieldError($field, getFieldMessage($field, "invalid", window.rne_translations.forms.invalidNumber)); 175$field.addClass("not-valid"); 176return false; 177} 178break; 179case "url": 180try { 181const url=value.startsWith("http://")||value.startsWith("https://") ? value:"http://" + value; 182const parsedUrl=new URL(url); 183const hostname=parsedUrl.hostname; 184if(!/^.+\..+$/.test(hostname)){ 185throw new Error("Hostname must contain at least one dot with characters on both sides."); 186}} catch (error){ 187showFieldError($field, getFieldMessage($field, "invalid", window.rne_translations.forms.invalidUrl)); 188$field.addClass("not-valid"); 189return false; 190} 191break; 192case "text": 193if($input.hasClass("air-datepicker-input")){ 194const dateFormat=$input.data("date-format")||"MM/dd/yyyy"; 195let datePattern; 196let dayIndex, monthIndex, yearIndex; 197switch (dateFormat){ 198case "dd.MM.yyyy": 199datePattern=/^(\d{2})\.(\d{2})\.(\d{4})$/; 200dayIndex=1; 201monthIndex=2; 202yearIndex=3; 203break; 204case "MM/dd/yyyy": 205datePattern=/^(\d{2})\/(\d{2})\/(\d{4})$/; 206monthIndex=1; 207dayIndex=2; 208yearIndex=3; 209break; 210default: 211showFieldError($field, getFieldMessage($field, "invalid", window.rne_translations.forms.invalidDate)); 212$field.addClass("not-valid"); 213return false; 214} 215const dateParts=value.match(datePattern); 216if(!dateParts){ 217showFieldError($field, getFieldMessage($field, "invalid", window.rne_translations.forms.invalidDate)); 218$field.addClass("not-valid"); 219return false; 220} 221const day=parseInt(dateParts[dayIndex], 10); 222const month=parseInt(dateParts[monthIndex], 10) - 1; 223const year=parseInt(dateParts[yearIndex], 10); 224const date=new Date(year, month, day); 225if(date.getFullYear()!==year||date.getMonth()!==month||date.getDate()!==day){ 226showFieldError($field, getFieldMessage($field, "invalid", window.rne_translations.forms.invalidDate)); 227$field.addClass("not-valid"); 228return false; 229}} 230break; 231} 232$field.addClass("is-valid"); 233} 234return true; 235} 236function updateConditionalFields(){ 237$form.find("[data-condition]").each(function (){ 238const $field=$(this); 239const conditions=$field.data("condition"); 240const conditionsArray=Array.isArray(conditions) ? conditions:[conditions]; 241const show=conditionsArray.every(function (condition){ 242const $triggerField=$form.find('[name="' + condition.field + '"]'); 243let triggerValue; 244if($triggerField.attr("type")==="checkbox"){ 245triggerValue=$triggerField.prop("checked"); 246}else if($triggerField.attr("type")==="radio"){ 247triggerValue=$triggerField.filter(":checked").val(); 248}else{ 249triggerValue=$triggerField.val(); 250} 251return Array.isArray(condition.value) ? condition.value.includes(triggerValue):triggerValue==condition.value; 252}); 253$field.toggle(show); 254updateFieldRequired($field, show); 255if(show){ 256initializeDatePickers(); 257}}); 258} 259function updateFieldRequired($field, show){ 260const $inputs=$field.find("input, select, textarea"); 261const isRequired=$field.data("required")==="conditional" ? show:$field.data("required")===true; 262$inputs.prop("required", isRequired); 263const $label=$field.find("label"); 264if(isRequired){ 265if(!$label.find(".required-asterisk").length){ 266$label.append('<span class="required-asterisk" aria-hidden="true">*</span>'); 267}}else{ 268$label.find(".required-asterisk").remove(); 269}} 270function validateForm(){ 271let isValid=true; 272const $fieldsToValidate=hasSteps ? $form.find(`.form-step[data-step="${currentStep}"] :input:visible`):$form.find(":input:visible"); 273$fieldsToValidate.each(function (){ 274if(!validateField($(this))){ 275isValid=false; 276}}); 277return isValid; 278} 279function focusFirstInvalidField(){ 280const $item=$form.find(".form-item.not-valid:visible").first(); 281if(!$item.length) return false;
282const $control=$item.find("input:not([type='hidden']), textarea, .rne-select-trigger").first(); 283if(!$control.length) return false; 284$control.trigger("focus"); 285return true; 286} 287function clearFormError(){ 288$form.find(".form-error").first().empty().hide(); 289} 290function showFormError(message){ 291const $formError=$form.find(".form-error").first(); 292$formError.attr({ role: "alert", tabindex: "-1" }).text(message).show(); 293$formError.focus(); 294} 295function showSuccess($target, html){ 296const $success=$(html); 297const $root=$success.filter("*").first(); 298$root.attr({ role: "status", tabindex: "-1" }); 299$target.replaceWith($success); 300$root.focus(); 301} 302function updateStepperUI(){ 303if(!hasSteps) return; 304$(".step").removeClass("active").removeAttr("aria-current"); 305$(`.step[data-step="${currentStep}"]`).addClass("active").attr("aria-current", "step"); 306$form.find(".prev-step").toggle(currentStep > 1); 307$form.find(".next-step").toggle(currentStep < totalSteps); 308$submitButton.toggle(currentStep===totalSteps); 309} 310function goToStep(step, direction){ 311if(!hasSteps) return; 312const $currentStep=$formSteps.filter(".active"); 313const $targetStep=$formSteps.filter(`[data-step="${step}"]`); 314const $stepperOverview=$form.find(".stepper.container"); 315$currentStep.removeClass("active"); 316$targetStep.addClass("active"); 317if(direction==="forward"){ 318$currentStep.addClass("previous").removeClass("next"); 319$targetStep.addClass("next").removeClass("previous"); 320$stepperOverview.find(`.step[data-step="${currentStep}"]`).addClass("done"); 321}else{ 322$currentStep.addClass("next").removeClass("previous"); 323$targetStep.addClass("previous").removeClass("next"); 324$stepperOverview.find(`.step[data-step="${step}"]`).removeClass("done"); 325} 326$targetStep[0].offsetWidth; 327$currentStep.removeClass("previous next"); 328$targetStep.removeClass("previous next"); 329currentStep=step; 330updateStepperUI(); 331const SCROLL_TOP_OFFSET=340; 332$("html, body").animate({ 333scrollTop: $(".stepper.container").offset().top - SCROLL_TOP_OFFSET 334}, 335500 336); 337const $firstInput=$targetStep.find("input, select, textarea").filter(":visible").first(); 338if($firstInput.length){ 339$firstInput.focus(); 340}} 341function setLoadingState($button, isLoading){ 342if(isLoading){ 343$button.addClass("btn-loading").prop("disabled", true).find(".btn-text").after('<span class="spinner"></span>'); 344}else{ 345$button.removeClass("btn-loading").prop("disabled", false).find(".spinner").remove(); 346}} 347const NAV_SVG=` 348<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 349<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M1.64592 4.64592C1.69236 4.59935 1.74754 4.56241 1.80828 4.5372C1.86903 4.512 1.93415 4.49902 1.99992 4.49902C2.06568 4.49902 2.13081 4.512 2.19155 4.5372C2.2523 4.56241 2.30747 4.59935 2.35392 4.64592L7.99992 10.2929L13.6459 4.64592C13.6924 4.59943 13.7476 4.56255 13.8083 4.53739C13.8691 4.51223 13.9342 4.49929 13.9999 4.49929C14.0657 4.49929 14.1308 4.51223 14.1915 4.53739C14.2522 4.56255 14.3074 4.59943 14.3539 4.64592C14.4004 4.6924 14.4373 4.74759 14.4624 4.80833C14.4876 4.86907 14.5005 4.93417 14.5005 4.99992C14.5005 5.06566 14.4876 5.13076 14.4624 5.1915C14.4373 5.25224 14.4004 5.30743 14.3539 5.35392L8.35392 11.3539C8.30747 11.4005 8.2523 11.4374 8.19155 11.4626C8.13081 11.4878 8.06568 11.5008 7.99992 11.5008C7.93415 11.5008 7.86903 11.4878 7.80828 11.4626C7.74754 11.4374 7.69236 11.4005 7.64592 11.3539L1.64592 5.35392C1.59935 5.30747 1.56241 5.2523 1.5372 5.19155C1.512 5.13081 1.49902 5.06568 1.49902 4.99992C1.49902 4.93415 1.512 4.86903 1.5372 4.80828C1.56241 4.74754 1.59935 4.69236 1.64592 4.64592Z" fill="#1A1A1A"/> 350</svg> 351`; 352const isMobile=document.body.classList.contains("touch-device"); 353function initializeDatePickers(){ 354const $form=$("form"); 355$form.find("input.air-datepicker-input").each(function (){ 356if(this._datepicker){ 357this._datepicker.destroy(); 358} 359const $input=$(this); 360const minDateStr=$input.data("min-date"); 361const maxDateStr=$input.data("max-date"); 362const config={ 363isMobile: isMobile, 364autoClose: true, 365prevHtml: NAV_SVG, 366nextHtml: NAV_SVG, 367onSelect: ({ formattedDate })=> { 368$input.val(formattedDate); 369validateField($input);
370const changeEvent=new Event("change", { bubbles: true }); 371$input[0].dispatchEvent(changeEvent); 372}}; 373if(minDateStr){ 374if(minDateStr==="today"){ 375config.minDate=new Date(); 376}else{ 377config.minDate=new Date(minDateStr); 378}} 379if(maxDateStr){ 380if(maxDateStr==="today"){ 381config.maxDate=new Date(); 382}else{ 383config.maxDate=new Date(maxDateStr); 384}} 385this._datepicker=window.initializeLocalizedDatepicker(this, config); 386}); 387} 388function attachDatepickerButtonListeners(){ 389$form.find(".datepicker-toggle").each(function (){ 390$(this).on("click", function (){ 391var $wrapper=$(this).closest(".datepicker-wrapper"); 392var $input=$wrapper.find("input"); 393if($input.length > 0&&$input[0]._datepicker){ 394$input[0].focus(); 395}}); 396}); 397} 398function initializeEvents(){ 399$form.on("change", "input, select, textarea", function (){ 400updateConditionalFields(); 401if($(this).attr("type")==="checkbox"){ 402validateCheckbox($(this)); 403}}); 404$form.on("rne-select-change", function (e){ 405const $hiddenInput=$(e.target); 406validateSelect($hiddenInput); 407}); 408$form.on("blur", ":input", function (){ 409validateField($(this)); 410}); 411if(hasSteps){ 412$form.on("click", ".next-step", function (e){ 413e.preventDefault(); 414if(validateForm()){ 415clearFormError(); 416if(currentStep < totalSteps){ 417goToStep(currentStep + 1, "forward"); 418}}else{ 419focusFirstInvalidField(); 420}}); 421$form.on("click", ".prev-step", function (e){ 422e.preventDefault(); 423if(currentStep > 1){ 424goToStep(currentStep - 1, "backward"); 425}}); 426} 427$form.on("submit", async function (e){ 428e.preventDefault(); 429updateConditionalFields(); 430$form.find(".rne-select-container input[type='hidden']").each(function (){ 431validateSelect($(this)); 432}); 433if(validateForm()){ 434setLoadingState($submitButton, true); 435try { 436const sol=await ensureFreshCaptcha(); 437if(!captchaTimer) startCaptchaWatchdog(sol); 438} catch (err){ 439console.error("Captcha refresh failed", err); 440setLoadingState($submitButton, false); 441return; 442} 443let formData=$form.serialize(); 444formData +="&action=handle_form"; 445clearFormError(); 446$.post(window.rne_translations.common.ajax_url, formData, function (response){ 447$form.find(".form-errors").remove(); 448if(response.success){ 449clearFormError(); 450const isEventSuggestionForm=$form.hasClass("form-event-suggestion"); 451const isNewsletterSubscribeForm=$form.attr("id")==="form_newsletter_subscribe"; 452const isNewsletterUnsubscribeForm=$form.attr("id")==="form_newsletter_unsubscribe"; 453if(isNewsletterSubscribeForm||isNewsletterUnsubscribeForm){ 454$form.siblings(".form-description").remove(); 455showSuccess($form, response.data.html); 456}else if(isEventSuggestionForm){ 457$(".entry-title").remove(); 458showSuccess($form.closest('[data-module="form-event-suggestion"]'), response.data.html); 459window.scrollTo({ top: 0, behavior: "smooth" }); 460}else{ 461showSuccess($form, response.data.html); 462}}else{ 463let fieldFocused=false; 464if(response.data.errors){ 465$.each(response.data.errors, function (field, error){ 466let $item=$form.find('[data-field-id="' + field + '"]').first(); 467if(!$item.length){ 468$item=$form.find('[data-field-name="' + field + '"]').first(); 469} 470if($item.length){ 471showFieldError($item, error); 472$item.removeClass("is-valid").addClass("not-valid"); 473$item.find(".rne-select-trigger").removeClass("is-valid").addClass("not-valid"); 474}}); 475fieldFocused=focusFirstInvalidField(); 476} 477if(response.data.form_error){ 478if(!fieldFocused){ 479showFormError(response.data.form_error); 480} 481fetchCaptcha().catch((err)=> console.error("Captcha retrieval error:", err)); 482}} 483}) 484.fail(function (){ 485showFormError(window.rne_translations.forms.genericError); 486}) 487.always(function (){ 488setLoadingState($submitButton, false); 489}); 490}else{ 491focusFirstInvalidField(); 492}}); 493} 494updateConditionalFields(); 495if(hasSteps){ 496updateStepperUI(); 497}else{ 498$submitButton.show(); 499} 500initializeEvents(); 501initializeDatePickers(); 502attachDatepickerButtonListeners(); 503} 504$(".rne-form").each(function (){ 505initializeForm("#" + $(this).attr("id")); 506var $form=$(this); 507var actionValue=$form.find('input[name="form_action"]').val(); 508if(actionValue){ 509$.post(window.rne_translations.common.ajax_url, 510{ 511action: "generate_form_nonce", 512nonce_action: actionValue 513}, 514function (response){ 515if(response.success){ 516$form.find(".nonce-field").html('<input type="hidden" name="security" value="' + response.data.nonce + '">'); 517}else{ 518console.error("Failed to fetch nonce for action: " + actionValue); 519}} 520); 521}}); 522$(".rne-form").on("keydown", "input", function (event){ 523if(event.keyCode===13||event.key==="Enter"){ 524event.preventDefault(); 525return false;
526}}); 527const customSelectTriggers=document.querySelectorAll(".rne-select-trigger"); 528customSelectTriggers.forEach((trigger)=> { 529const container=trigger.closest(".rne-select-container"); 530const listbox=container.querySelector('[role="listbox"]'); 531const hiddenInput=container.querySelector('input[type="hidden"]'); 532const options=Array.from(listbox.querySelectorAll('[role="option"]')); 533let expanded=false; 534function openListbox(){ 535listbox.hidden=false; 536trigger.setAttribute("aria-expanded", "true"); 537expanded=true; 538trigger.focus(); 539} 540function closeListbox(){ 541listbox.hidden=true; 542trigger.setAttribute("aria-expanded", "false"); 543expanded=false; 544} 545function selectOption(option){ 546const value=option.getAttribute("data-value"); 547const label=option.textContent; 548hiddenInput.value=value; 549container.querySelector(".rne-select-selected-value").textContent=label; 550options.forEach((opt)=> { 551opt.classList.remove("selected"); 552opt.setAttribute("aria-selected", "false"); 553}); 554option.classList.add("selected"); 555option.setAttribute("aria-selected", "true"); 556closeListbox(); 557const event=new CustomEvent("rne-select-change", { 558bubbles: true, 559detail: { value }}); 560hiddenInput.dispatchEvent(event); 561} 562trigger.addEventListener("click", (e)=> { 563e.preventDefault(); 564expanded ? closeListbox():openListbox(); 565}); 566document.addEventListener("click", (e)=> { 567if(!container.contains(e.target)&&expanded){ 568closeListbox(); 569}}); 570trigger.addEventListener("keydown", (e)=> { 571const currentIndex=options.findIndex((opt)=> opt.classList.contains("selected")); 572let newIndex=currentIndex; 573if(e.key==="ArrowDown"){ 574e.preventDefault(); 575if(!expanded){ 576openListbox(); 577}else{ 578newIndex=currentIndex + 1 < options.length ? currentIndex + 1:0; 579options[newIndex].focus(); 580}}else if(e.key==="ArrowUp"){ 581e.preventDefault(); 582if(!expanded){ 583openListbox(); 584}else{ 585newIndex=currentIndex - 1 >=0 ? currentIndex - 1:options.length - 1; 586options[newIndex].focus(); 587}}else if(e.key==="Enter"||e.key===" "){ 588e.preventDefault(); 589if(!expanded){ 590openListbox(); 591}else if(currentIndex > -1){ 592selectOption(options[currentIndex]); 593}}else if(e.key==="Escape"){ 594e.preventDefault(); 595if(expanded) closeListbox(); 596}}); 597options.forEach((option, index)=> { 598option.setAttribute("tabindex", "-1"); 599option.addEventListener("click", ()=> selectOption(option)); 600option.addEventListener("keydown", (e)=> { 601if(e.key==="Enter"||e.key===" "){ 602e.preventDefault(); 603selectOption(option); 604}else if(e.key==="Escape"){ 605e.preventDefault(); 606closeListbox(); 607}else if(e.key==="ArrowDown"){ 608e.preventDefault(); 609const nextIndex=index + 1 < options.length ? index + 1:0; 610options[nextIndex].focus(); 611}else if(e.key==="ArrowUp"){ 612e.preventDefault(); 613const prevIndex=index - 1 >=0 ? index - 1:options.length - 1; 614options[prevIndex].focus(); 615}}); 616}); 617}); 618}); 619document.addEventListener("DOMContentLoaded", function (){ 620Array.prototype.forEach.call(document.querySelectorAll(".accordion__content"), (el)=> new SimpleBar(el)); 621function toggleAccordion(el){ 622const button=el.closest(".accordion__toggle"); 623if(!button) return; 624const isExpanded=button.getAttribute("aria-expanded")==="true"; 625const contentId=button.getAttribute("aria-controls"); 626const content=document.getElementById(contentId); 627if(!content) return; 628if(isExpanded){ 629button.setAttribute("aria-expanded", "false"); 630content.classList.remove("show"); 631content.hidden=true; 632}else{ 633button.setAttribute("aria-expanded", "true"); 634content.classList.add("show"); 635content.hidden=false; 636}} 637function closeAllAccordions(container){ 638if(!container) return; 639const expandedButtons=container.querySelectorAll('.accordion__toggle[aria-expanded="true"]'); 640expandedButtons.forEach((button)=> toggleAccordion(button)); 641} 642document.querySelectorAll(".accordion__toggle").forEach(function (button){ 643button.addEventListener("click", function (e){ 644e.stopPropagation(); 645toggleAccordion(button); 646}); 647}); 648const resetButton=document.getElementById("media-filter__reset"); 649if(resetButton){ 650resetButton.addEventListener("click", function (){ 651const container=document.querySelector(".media-filter-container"); 652if(container){ 653const checkboxes=container.querySelectorAll('input[type="checkbox"]');
654checkboxes.forEach(function (checkbox){ 655checkbox.checked=false; 656}); 657}}); 658resetButton.addEventListener("keydown", function (e){ 659if(e.key==="Enter"||e.key===" "){ 660e.preventDefault(); 661resetButton.click(); 662}}); 663} 664window.closeAllAccordions=closeAllAccordions; 665window.toggleAccordion=toggleAccordion; 666}); 667class ContentFilter { 668constructor(options){ 669this.options=options; 670this.root=options.root||null; 671this.data=options.data||[]; 672this.hasMediaPlayers=options.hasMediaPlayers||false; 673this.templates=options.templates||{}; 674this.state={ 675currentPage: 1, 676itemsPerPage: options.itemsPerPage||10, 677isMobileFilterOpen: false 678}; 679this.totalItems=options.totalItems||(this.data ? this.data.length:0); 680if(!this.root){ 681return; 682} 683this.indices={ 684titleIndex: new Map(), 685dateIndex: new Map(), 686sdgIndex: new Map(), 687typeIndex: new Map(), 688termIndex: new Map(), 689eventCityIndex: new Map(), 690postTermIndex: new Map(), 691postCategoryIndex: new Map() 692}; 693this.init(); 694} 695init(){ 696this.cacheElements(); 697this.bindEvents(); 698this.buildIndices(); 699this.initTemplates(); 700if(this.totalItems > 0){ 701this.updatePaginationControls(this.totalItems); 702} 703this.updateResetButtonVisibility(); 704this.observeMobileFilterOverlay(); 705} 706cacheElements(){ 707this.elements={ 708itemContainer: document.querySelector(".filtered-items"), 709archiveFilters: document.querySelectorAll(".accordion__item"), 710searchInput: document.getElementById("item_text_search"), 711startDateInput: document.getElementById("start_date_input"), 712startDateInputMobile: document.getElementById("start_date_mobile_input"), 713endDateInput: document.getElementById("end_date_input"), 714endDateInputMobile: document.getElementById("end_date_mobile_input"), 715sortBySelect: document.getElementById("sort_by"), 716sdgCheckboxes: document.querySelectorAll('input[name="sdg_terms[]"]'), 717eventCityCheckboxes: document.querySelectorAll('input[name="event_cities[]"]'), 718postTypeCheckboxes: document.querySelectorAll('input[name="post_terms[]"]'), 719postTypeButtons: document.querySelectorAll(".post-type-button"), 720postTypeDefaultButton: document.querySelector(".post-type-button[data-value='all']"), 721documentTermCheckboxes: document.querySelectorAll(".term-checkbox input[type='checkbox']"), 722documentTypeCheckboxes: document.querySelectorAll('input[name="pdf"], input[name="audio"], input[name="video"]'), 723filterResetButtons: document.querySelectorAll(".filter-reset-button"), 724paginationContainer: document.getElementById("pagination-controls"), 725mobileFilterOverlay: document.querySelector(".mobile-filter-overlay"), 726applyFilterButton: document.getElementById("apply-filter-button"), 727filterHeadingText: document.querySelector(".filter-heading.item-filter-text"), 728postCategoryButtons: document.querySelectorAll(".post-category-button"), 729postCategoryDefaultButton: document.querySelector(".post-category-button[data-value='meldung']") 730};} 731debounce(func, delay){ 732let timeoutId; 733return (...args)=> { 734if(timeoutId){ 735clearTimeout(timeoutId); 736} 737timeoutId=setTimeout(()=> { 738func.apply(this, args); 739}, delay); 740};} 741bindEvents(){ 742if(this.elements.mobileFilterOverlay){ 743window.bindMobileFilterMenuEvents(this.root, this.elements.mobileFilterOverlay); 744} 745if(!this.data){ 746return; 747} 748this.debouncedHandleFilterChange=this.debounce(()=> this.handleFilterChange(), 300); 749if(this.elements.searchInput){ 750this.elements.searchInput.addEventListener("input", this.debouncedHandleFilterChange); 751} 752if(this.elements.startDateInput){ 753this.elements.startDateInput.addEventListener("change", ()=> this.handleFilterChange()); 754} 755if(this.elements.startDateInputMobile){ 756this.elements.startDateInputMobile.addEventListener("change", ()=> this.handleFilterChange()); 757} 758if(this.elements.endDateInput){ 759this.elements.endDateInput.addEventListener("change", ()=> this.handleFilterChange()); 760} 761if(this.elements.endDateInputMobile){ 762this.elements.endDateInputMobile.addEventListener("change", ()=> this.handleFilterChange()); 763} 764if(this.elements.sdgCheckboxes){ 765this.elements.sdgCheckboxes.forEach((cb)=> cb.addEventListener("change", ()=> this.handleFilterChange())); 766} 767if(this.elements.eventCityCheckboxes){ 768this.elements.eventCityCheckboxes.forEach((cb)=> cb.addEventListener("change", ()=> this.handleFilterChange())); 769} 770if(this.elements.postTypeCheckboxes){
771this.elements.postTypeCheckboxes.forEach((cb)=> cb.addEventListener("change", ()=> this.handleFilterChange())); 772} 773if(this.elements.sortBySelect){ 774this.elements.sortBySelect.addEventListener("rne-select-change", ()=> this.handleFilterChange()); 775} 776if(this.elements.postTypeButtons){ 777this.elements.postTypeButtons.forEach((btn)=> { 778btn.addEventListener("click", ()=> { 779this.elements.postTypeButtons.forEach((b)=> { 780b.classList.remove("embla__slide--active"); 781b.setAttribute("aria-checked", "false"); 782}); 783btn.classList.add("embla__slide--active"); 784btn.setAttribute("aria-checked", "true"); 785const filterValue=btn.dataset.value; 786const filterFunctions={ 787newsletter_post: ()=> false, 788all: (item)=> item.getAttribute("data-value")==="sdgs", 789newsposts: (item)=> item.getAttribute("data-value")==="newsposts", 790project: (item)=> item.getAttribute("data-value")==="sdgs", 791event: (item)=> ["sdgs", "event"].includes(item.getAttribute("data-value")), 792default: (item)=> { 793const itemValue=item.getAttribute("data-value"); 794return !itemValue||itemValue===filterValue; 795}}; 796if(filterValue==="newsletter_post"&&this.elements.filterHeadingText){ 797this.elements.filterHeadingText.style.display="none"; 798}else{ 799this.elements.filterHeadingText.style.display="block"; 800} 801const filterFunction=filterFunctions[filterValue]||filterFunctions.default; 802if(this.elements.archiveFilters){ 803this.elements.archiveFilters.forEach((item)=> { 804item.style.display=filterFunction(item) ? "block":"none"; 805}); 806} 807this.handleFilterChange(); 808}); 809}); 810} 811if(this.elements.postCategoryButtons){ 812this.elements.postCategoryButtons.forEach((btn)=> { 813btn.addEventListener("click", ()=> { 814this.elements.postCategoryButtons.forEach((b)=> { 815b.classList.remove("embla__slide--active"); 816b.setAttribute("aria-checked", "false"); 817}); 818btn.classList.add("embla__slide--active"); 819btn.setAttribute("aria-checked", "true"); 820this.handleFilterChange(); 821}); 822}); 823} 824if(this.elements.documentTypeCheckboxes){ 825this.elements.documentTypeCheckboxes.forEach((cb)=> { 826cb.addEventListener("change", ()=> { 827if(!cb.checked){ 828const mediaType=cb.name; 829this.elements.documentTermCheckboxes.forEach((termCb)=> { 830if(termCb.name.startsWith(mediaType)){ 831termCb.checked=false; 832}}); 833} 834if(cb.checked){ 835const mediaType=cb.name; 836this.elements.documentTermCheckboxes.forEach((termCb)=> { 837if(termCb.name.startsWith(mediaType)){ 838termCb.checked=true; 839}}); 840} 841this.handleFilterChange(); 842}); 843}); 844} 845if(this.elements.postTypeCheckboxes){ 846this.elements.postTypeCheckboxes.forEach((cb)=> { 847cb.addEventListener("change", ()=> { 848this.handleFilterChange(); 849}); 850}); 851} 852if(this.elements.documentTermCheckboxes){ 853this.elements.documentTermCheckboxes.forEach((cb)=> { 854cb.addEventListener("change", ()=> { 855const mediaType=cb.name.split("_")[0]; 856const mediaTypeCheckbox=document.querySelector(`input[name="${mediaType}"]`); 857if(cb.checked){ 858if(mediaTypeCheckbox&&!mediaTypeCheckbox.checked){ 859mediaTypeCheckbox.checked=true; 860}} 861this.handleFilterChange(); 862}); 863}); 864} 865if(this.elements.filterResetButtons){ 866this.elements.filterResetButtons.forEach((btn)=> btn.addEventListener("click", ()=> this.resetFilters())); 867} 868if(this.elements.applyFilterButton){ 869this.elements.applyFilterButton.addEventListener("click", ()=> { 870this.resetPageAndFilter(); 871if(this.elements.mobileFilterOverlay){ 872this.elements.mobileFilterOverlay.setAttribute("data-open", "false"); 873document.body.style.overflow="auto"; 874this.scrollToMediaItems(); 875}}); 876}} 877observeMobileFilterOverlay(){ 878if(this.elements.mobileFilterOverlay){ 879const observer=new MutationObserver((mutations)=> { 880mutations.forEach((mutation)=> { 881if(mutation.attributeName==="data-open"){ 882const dataOpen=mutation.target.getAttribute("data-open"); 883this.state.isMobileFilterOpen=dataOpen==="true"; 884}}); 885}); 886observer.observe(this.elements.mobileFilterOverlay, { attributes: true, attributeFilter: ["data-open"] }); 887}} 888handleFilterChange(){ 889if(!this.state.isMobileFilterOpen){ 890this.resetPageAndFilter(); 891}} 892resetPageAndFilter(){ 893this.state.currentPage=1; 894this.filterAndUpdateUI(); 895this.updateResetButtonVisibility(); 896} 897resetSdgCheckboxes(){ 898if(this.elements.sdgCheckboxes){
899this.elements.sdgCheckboxes.forEach((cb)=> (cb.checked=false)); 900}} 901resetPostTypeCheckboxes(){ 902if(this.elements.postTypeCheckboxes){ 903this.elements.postTypeCheckboxes.forEach((cb)=> (cb.checked=false)); 904}} 905resetEventCityCheckboxes(){ 906if(this.elements.eventCityCheckboxes){ 907this.elements.eventCityCheckboxes.forEach((cb)=> (cb.checked=false)); 908}} 909resetDocumentTermCheckboxes(){ 910if(this.elements.documentTermCheckboxes){ 911this.elements.documentTermCheckboxes.forEach((cb)=> (cb.checked=false)); 912}} 913resetDocumentTypeCheckboxes(){ 914if(this.elements.documentTypeCheckboxes){ 915this.elements.documentTypeCheckboxes.forEach((cb)=> (cb.checked=false)); 916}} 917resetPostTypeButtons(){ 918if(this.elements.postTypeButtons){ 919this.elements.postTypeButtons.forEach((btn)=> { 920btn.classList.remove("embla__slide--active"); 921btn.setAttribute("aria-checked", "false"); 922}); 923if(this.elements.postTypeDefaultButton){ 924this.elements.postTypeDefaultButton.classList.add("embla__slide--active"); 925this.elements.postTypeDefaultButton.setAttribute("aria-checked", "true"); 926}} 927} 928resetPostCategoryButtons(){ 929if(this.elements.postCategoryButtons){ 930this.elements.postCategoryButtons.forEach((btn)=> { 931btn.classList.remove("embla__slide--active"); 932btn.setAttribute("aria-checked", "false"); 933}); 934if(this.elements.postCategoryDefaultButton){ 935this.elements.postCategoryDefaultButton.classList.add("embla__slide--active"); 936this.elements.postCategoryDefaultButton.setAttribute("aria-checked", "true"); 937}} 938} 939resetSearchInput(){ 940if(this.elements.searchInput){ 941this.elements.searchInput.value=""; 942}} 943resetStartDateInputs(){ 944if(this.elements.startDateInput){ 945this.elements.startDateInput.value=""; 946} 947if(this.elements.startDateInputMobile){ 948this.elements.startDateInputMobile.value=""; 949}} 950resetEndDateInputs(){ 951if(this.elements.endDateInput){ 952this.elements.endDateInput.value=""; 953} 954if(this.elements.endDateInputMobile){ 955this.elements.endDateInputMobile.value=""; 956}} 957resetFilters(){ 958console.log("RESET CLICKED"); 959this.resetSearchInput(); 960this.resetStartDateInputs(); 961this.resetEndDateInputs(); 962this.resetSdgCheckboxes(); 963this.resetPostTypeCheckboxes(); 964this.resetEventCityCheckboxes(); 965this.resetDocumentTermCheckboxes(); 966this.resetDocumentTypeCheckboxes(); 967this.resetPostCategoryButtons(); 968if(!this.state.isMobileFilterOpen){ 969this.resetPageAndFilter(); 970}else{ 971this.updateResetButtonVisibility(); 972}} 973getFilterState(){ 974const selectedTerms={}; 975if(this.elements.documentTermCheckboxes){ 976this.elements.documentTermCheckboxes.forEach((cb)=> { 977if(cb.checked){ 978const mediaType=cb.name.split("_")[0]; 979if(!selectedTerms[mediaType]){ 980selectedTerms[mediaType]=[]; 981} 982selectedTerms[mediaType].push(parseInt(cb.value, 10)); 983}}); 984} 985return { 986searchText: this.elements.searchInput?.value?.toLowerCase()||"", 987startDate: this.elements.startDateInput?.value ? window.parseDateString(this.elements.startDateInput.value):this.elements.startDateInputMobile?.value ? window.parseDateString(this.elements.startDateInputMobile.value):null, 988endDate: this.elements.endDateInput?.value ? window.parseDateString(this.elements.endDateInput.value):this.elements.endDateInputMobile?.value ? window.parseDateString(this.elements.endDateInputMobile.value):null, 989selectedSdgTerms: this.elements.sdgCheckboxes 990? Array.from(this.elements.sdgCheckboxes) 991.filter((cb)=> cb.checked) 992.map((cb)=> parseInt(cb.value, 10)) 993: [], 994selectedEventCities: this.elements.eventCityCheckboxes 995? Array.from(this.elements.eventCityCheckboxes) 996.filter((cb)=> cb.checked) 997.map((cb)=> cb.value) 998: [], 999selectedMediaTypes: this.elements.documentTypeCheckboxes 1000? Array.from(this.elements.documentTypeCheckboxes) 1001.filter((cb)=> cb.checked) 1002.map((cb)=> cb.value) 1003: [], 1004selectedTerms: selectedTerms, 1005sortingOption: this.elements.sortBySelect?.value||"date_newest", 1006selectedPostTerms: this.elements.postTypeCheckboxes 1007? Array.from(this.elements.postTypeCheckboxes) 1008.filter((cb)=> cb.checked) 1009.map((cb)=> cb.value) 1010: [], 1011postType: this.elements.postTypeButtons ? Array.from(this.elements.postTypeButtons).find((btn)=> btn.classList.contains("embla__slide--active"))?.dataset?.value||"all":"", 1012postCategory: this.elements.postCategoryButtons ? Array.from(this.elements.postCategoryButtons).find((btn)=> btn.classList.contains("embla__slide--active"))?.dataset?.value:"" 1013};} 1014filterPosts(filters){ 1015let matchingIndices=new Set(Array.from({ length: this.data.length }, (_, i)=> i));
1016if(filters.postCategory==="meldung"){ 1017matchingIndices=new Set( 1018[...matchingIndices].filter((idx)=> { 1019return this.data[idx].post_term_ids.includes(0); 1020}) 1021); 1022}else if(filters.postCategory==="pressemitteilung"){ 1023matchingIndices=new Set( 1024[...matchingIndices].filter((idx)=> { 1025return this.data[idx].post_term_ids.includes(1); 1026}) 1027); 1028} 1029if(filters.postType!=="all"){ 1030matchingIndices=new Set( 1031[...matchingIndices].filter((idx)=> { 1032return this.data[idx].post_type===filters.postType; 1033}) 1034); 1035} 1036if(filters.startDate||filters.endDate){ 1037const filterStartDate=filters.startDate ? filters.startDate.getTime() / 1000:0; 1038const filterEndDate=filters.endDate ? filters.endDate.getTime() / 1000:Number.MAX_SAFE_INTEGER; 1039matchingIndices=new Set( 1040[...matchingIndices].filter((idx)=> { 1041const postDate=this.data[idx].post_filtering_date; 1042return (!filterStartDate||postDate >=filterStartDate)&&(!filterEndDate||postDate <=filterEndDate); 1043}) 1044); 1045} 1046if(filters.searchText){ 1047const searchText=filters.searchText.trim().toLowerCase(); 1048const titleMatches=new Set(); 1049for (const [title, indices] of this.indices.titleIndex){ 1050const normalizedTitle=title.toLowerCase(); 1051if(normalizedTitle.includes(searchText)){ 1052indices.forEach((idx)=> titleMatches.add(idx)); 1053}} 1054matchingIndices=new Set([...matchingIndices].filter((idx)=> titleMatches.has(idx))); 1055} 1056if(filters.postType==="newsletter_post"){ 1057return matchingIndices; 1058} 1059if(filters.selectedPostTerms.length > 0&&["newsposts", "all"].includes(filters.postType)){ 1060const postTermMatches=new Set(); 1061filters.selectedPostTerms.forEach((term)=> { 1062const indices=this.indices.postTermIndex.get(term); 1063if(indices) indices.forEach((idx)=> postTermMatches.add(idx)); 1064}); 1065matchingIndices=new Set([...matchingIndices].filter((idx)=> postTermMatches.has(idx))); 1066} 1067if(filters.selectedSdgTerms.length > 0&&!["newsposts"].includes(filters.postType)){ 1068const sdgMatches=new Set(); 1069filters.selectedSdgTerms.forEach((termId)=> { 1070const indices=this.indices.sdgIndex.get(termId); 1071if(indices) indices.forEach((idx)=> sdgMatches.add(idx)); 1072}); 1073matchingIndices=new Set([...matchingIndices].filter((idx)=> sdgMatches.has(idx))); 1074} 1075if(filters.selectedEventCities.length > 0&&["event", "all"].includes(filters.postType)){ 1076const eventCityMatches=new Set(); 1077filters.selectedEventCities.forEach((city)=> { 1078const indices=this.indices.eventCityIndex.get(city.toLowerCase()); 1079if(indices) indices.forEach((idx)=> eventCityMatches.add(idx)); 1080}); 1081matchingIndices=new Set([...matchingIndices].filter((idx)=> eventCityMatches.has(idx))); 1082} 1083if(filters.selectedMediaTypes.length > 0){ 1084const mediaTypeMatchingIndices=new Set(); 1085filters.selectedMediaTypes.forEach((type)=> { 1086if(filters.selectedTerms[type]&&filters.selectedTerms[type].length > 0){ 1087filters.selectedTerms[type].forEach((termId)=> { 1088if(termId===0){ 1089for (let i=0; i < this.data.length; i++){ 1090const doc=this.data[i]; 1091if(doc.post_type===type&&doc.term_ids.length===0){ 1092mediaTypeMatchingIndices.add(i); 1093}} 1094}else{ 1095const termIndices=this.indices.termIndex.get(type)?.get(termId); 1096if(termIndices){ 1097termIndices.forEach((idx)=> mediaTypeMatchingIndices.add(idx)); 1098}} 1099}); 1100}else{ 1101const typeIndices=this.indices.typeIndex.get(type); 1102if(typeIndices){ 1103typeIndices.forEach((idx)=> mediaTypeMatchingIndices.add(idx)); 1104}} 1105}); 1106matchingIndices=new Set([...matchingIndices].filter((x)=> mediaTypeMatchingIndices.has(x))); 1107} 1108return matchingIndices; 1109} 1110filterAndUpdateUI(){ 1111const filterState=this.getFilterState(); 1112let matchingIndices=this.filterPosts(filterState); 1113let matchingPosts=Array.from(matchingIndices).map((idx)=> this.data[idx]); 1114if(filterState.sortingOption!=="date_newest"){ 1115this.sortPosts(matchingPosts, filterState.sortingOption); 1116} 1117const totalItems=matchingPosts.length; 1118const totalPages=Math.ceil(totalItems / this.state.itemsPerPage); 1119if(this.state.currentPage > totalPages) this.state.currentPage=totalPages; 1120if(this.state.currentPage < 1) this.state.currentPage=1; 1121const startIndex=(this.state.currentPage - 1) * this.state.itemsPerPage; 1122const paginatedPosts=matchingPosts.slice(startIndex, startIndex + this.state.itemsPerPage); 1123this.updatePostsUI(paginatedPosts); 1124this.updatePaginationControls(totalItems); 1125} 1126sortPosts(postsArray, sortingOption){ 1127switch (sortingOption){ 1128case "date_oldest": 1129postsArray.reverse(); 1130break; 1131default: 1132break; 1133}} 1134updatePostsUI(posts){ 1135const container=this.elements.itemContainer; 1136if(!container){ 1137console.warn("DEBUG: No item container found."); 1138return; 1139} 1140if(this.hasMediaPlayers){ 1141if(window.PlyrInit&&typeof window.PlyrInit.destroyAllPlayers==="function"){ 1142window.PlyrInit.destroyAllPlayers(); 1143}} 1144while (container.firstChild){ 1145container.removeChild(container.firstChild); 1146} 1147const fragment=document.createDocumentFragment();
1148posts.forEach((post)=> { 1149const element=this.createPostElement(post); 1150fragment.appendChild(element); 1151if(post.post_type==="audio"){ 1152window.initSinglePlayer(element); 1153}else if(post.post_type==="video"){ 1154const blockedElem=element.querySelector("[consent-required]"); 1155if(blockedElem&&window.consentApi?.unblock){ 1156window.consentApi.unblock(blockedElem).then(()=> { 1157window.initSinglePlayer(element); 1158}); 1159}else{ 1160window.initSinglePlayer(element); 1161}} 1162}); 1163container.appendChild(fragment); 1164} 1165createPostElement(post){ 1166const templateString=this.templates[post.post_type]; 1167const filterState=this.getFilterState(); 1168const selectedSdgTerms=Array.isArray(filterState.selectedSdgTerms) ? filterState.selectedSdgTerms.map(Number):[]; 1169if(!templateString){ 1170const postContainer=document.createElement("div"); 1171postContainer.textContent="Unknown document type."; 1172return postContainer; 1173} 1174let badgeContainerKey=null; 1175if(post.badges?.badges?.sdg){ 1176badgeContainerKey="badges"; 1177}else if(post.badges_sdgs?.badges?.sdg){ 1178badgeContainerKey="badges_sdgs"; 1179}else if(post.badges_event_details?.badges?.sdg){ 1180badgeContainerKey="badges_event_details"; 1181} 1182if(!badgeContainerKey){ 1183return this.populateTemplate(templateString, post); 1184} 1185const sdgBadges=Array.isArray(post[badgeContainerKey]?.badges?.sdg) ? [...post[badgeContainerKey].badges.sdg]:[]; 1186const rawMaxShownSdgs=post[badgeContainerKey]?.max_shown_sdgs; 1187const MAX_SHOWN_SDGS=typeof rawMaxShownSdgs==="string"&&!isNaN(parseInt(rawMaxShownSdgs, 10)) ? parseInt(rawMaxShownSdgs, 10):typeof rawMaxShownSdgs==="number" ? rawMaxShownSdgs:2; 1188const rearrangedSdgBadges=this.rearrangeSdgBadges(sdgBadges, selectedSdgTerms, MAX_SHOWN_SDGS); 1189const clonedPost=JSON.parse(JSON.stringify(post)); 1190if(clonedPost[badgeContainerKey]?.badges?.sdg){ 1191clonedPost[badgeContainerKey].badges.sdg=rearrangedSdgBadges; 1192} 1193return this.populateTemplate(templateString, clonedPost); 1194} 1195rearrangeSdgBadges(sdgBadges, selectedSdgTerms, maxShownSdgs){ 1196const selectedSdgsSet=new Set(selectedSdgTerms); 1197if(selectedSdgsSet.size===0){ 1198return sdgBadges.slice(0, maxShownSdgs); 1199} 1200const selectedBadges=[]; 1201const nonSelectedBadges=[]; 1202sdgBadges.forEach((badge)=> { 1203const badgeTermId=parseInt(badge.term_id, 10); 1204if(selectedSdgsSet.has(badgeTermId)){ 1205selectedBadges.push(badge); 1206}else{ 1207nonSelectedBadges.push(badge); 1208}}); 1209const rearrangedSdgBadges=selectedBadges.concat(nonSelectedBadges); 1210return rearrangedSdgBadges.slice(0, maxShownSdgs); 1211} 1212generateBadges(badges, badgeClass){ 1213return badges 1214.map((badge)=> { 1215let content=""; 1216let extraClass=""; 1217switch (badge.type){ 1218case "sdg": 1219content=badge.name; 1220return `<li class="${badgeClass}" data-sdg-id="${badge.term_id}">${content}</li>`; 1221case "more_sdgs": 1222const remainingSdgsJson=JSON.stringify(badge.remaining_sdgs); 1223const moreSdgsTemplate=(window.rne_translations&&window.rne_translations.badges&&window.rne_translations.badges.moreSdgs)||"%d weitere Nachhaltigkeitsziele anzeigen"; 1224const moreSdgsLabel=moreSdgsTemplate.replace(/%d/g, badge.remaining_count); 1225return ` 1226<li> 1227<button type="button" class="${badgeClass} more-sdgs-badge" data-remaining-sdgs='${remainingSdgsJson}' data-badge-class="${badgeClass}" aria-label="${moreSdgsLabel}"> 1228<svg class="icon"><use href="#icon-plus"></use></svg> 1229<span class="more-sdgs-text">${badge.remaining_count} Weitere</span> 1230</button> 1231</li> 1232`; 1233case "date": 1234case "event_date": 1235content=badge.value; 1236extraClass=badge.type==="event_date" ? " event-date":""; 1237break; 1238case "project": 1239case "category": 1240case "event_type": 1241case "document_term": 1242content=badge.name; 1243extraClass=badge.type==="event_type"&&badge.is_internal ? " rne-event":""; 1244break; 1245case "event_location": 1246content=badge.value; 1247extraClass=" event-location"; 1248break; 1249default: 1250content=badge.name||badge.value||""; 1251} 1252return `<span class="${badgeClass}${extraClass}">${content}</span>`; 1253}) 1254.join(""); 1255} 1256populateTemplate(templateString, data){ 1257let template=templateString; 1258template=template.replace(/{{(\w+)}}/g, (_, key)=> { 1259if(key.startsWith("badges")){ 1260const badgeData=data[key]; 1261if(badgeData&&badgeData.badges){ 1262let iconIncluded=false; 1263let badgesHtml=""; 1264if(badgeData.badges.sdg&&badgeData.badges.sdg.length > 0){ 1265badgesHtml +='<ul class="badge-list sdg-badge-list">'; 1266if(!iconIncluded&&badgeData.icon_name){ 1267badgesHtml +=window.getSvg(badgeData.icon_name); 1268iconIncluded=true; 1269} 1270badgesHtml +=this.generateBadges(badgeData.badges.sdg, badgeData.badge_class); 1271badgesHtml +="</ul>"; 1272} 1273if(badgeData.badges.others&&badgeData.badges.others.length > 0){ 1274badgesHtml +='<div class="badge-list">'; 1275if(!iconIncluded&&badgeData.icon_name){ 1276badgesHtml +=window.getSvg(badgeData.icon_name); 1277iconIncluded=true; 1278} 1279badgesHtml +=this.generateBadges(badgeData.badges.others, badgeData.badge_class); 1280badgesHtml +="</div>"; 1281} 1282return badgesHtml; 1283}else{ 1284return ""; 1285}}else if(key==="video_player_html_blocked"){ 1286const blocked=(data.video_player_html_blocked||"").trim(); 1287if(blocked===""){ 1288return data.video_player_html ?? ""; 1289}else{ 1290return blocked; 1291}}else{ 1292return data[key]!=null ? data[key]:""; 1293}}); 1294const tempDiv=document.createElement("div"); 1295tempDiv.innerHTML=template.trim(); 1296tempDiv.querySelectorAll("[data-src]").forEach((element)=> { 1297element.setAttribute("src", element.dataset.src); 1298element.removeAttribute("data-src"); 1299}); 1300return tempDiv.firstChild; 1301} 1302updatePaginationControls(totalItems){ 1303this.announceResults(totalItems); 1304const container=this.elements.paginationContainer; 1305if(!container) return; 1306container.innerHTML=""; 1307const totalPages=Math.ceil(totalItems / this.state.itemsPerPage); 1308if(totalPages <=1) return; 1309const currentPage=this.state.currentPage; 1310if(currentPage > 1){ 1311const prevContent=window.getSvg("icon-arrow"); 1312this.createPaginationButton(prevContent, 1313()=> { 1314this.state.currentPage--; 1315this.filterAndUpdateUI(); 1316this.scrollToMediaItems(); 1317}, 1318container, 1319false, 1320"pagination__button--prev", 1321"prev" 1322); 1323} 1324let pageNumbers=[]; 1325if(totalPages <=5){ 1326for (let i=1; i <=totalPages; i++){ 1327pageNumbers.push(i); 1328}}else{ 1329pageNumbers.push(1); 1330if(currentPage > 3){ 1331pageNumbers.push("..."); 1332} 1333let startPage=Math.max(2, currentPage - 1); 1334let endPage=Math.min(totalPages - 1, currentPage + 1); 1335for (let i=startPage; i <=endPage; i++){ 1336pageNumbers.push(i); 1337} 1338if(currentPage < totalPages - 2){ 1339pageNumbers.push("..."); 1340} 1341pageNumbers.push(totalPages); 1342}
1343pageNumbers.forEach((page)=> { 1344if(page==="..."){ 1345const ellipsis=document.createElement("span"); 1346ellipsis.textContent="..."; 1347ellipsis.classList.add("ellipsis"); 1348container.appendChild(ellipsis); 1349}else{ 1350const pageContent=page.toString(); 1351this.createPaginationButton(pageContent, 1352()=> { 1353this.state.currentPage=page; 1354this.filterAndUpdateUI(); 1355this.scrollToMediaItems(); 1356}, 1357container, 1358page===currentPage, 1359"", 1360"page" 1361); 1362}}); 1363if(currentPage < totalPages){ 1364const nextContent=window.getSvg("icon-arrow"); 1365this.createPaginationButton(nextContent, 1366()=> { 1367this.state.currentPage++; 1368this.filterAndUpdateUI(); 1369this.scrollToMediaItems(); 1370}, 1371container, 1372false, 1373"pagination__button--next", 1374"next" 1375); 1376}} 1377createPaginationButton(content, onClick, container, isActive=false, extraClasses="", direction="page"){ 1378const button=document.createElement("button"); 1379button.type="button"; 1380button.innerHTML=content; 1381button.classList.add("pagination__button"); 1382const t=(window.rne_translations&&window.rne_translations.pagination)||{}; 1383if(direction==="prev"){ 1384button.setAttribute("rel", "prev"); 1385button.setAttribute("aria-label", t.prevPage||"Vorherige Seite"); 1386}else if(direction==="next"){ 1387button.setAttribute("rel", "next"); 1388button.setAttribute("aria-label", t.nextPage||"Nächste Seite"); 1389}else{ 1390button.setAttribute("aria-label", (t.page||"Seite %d").replace(/%d/g, content)); 1391} 1392if(isActive){ 1393button.classList.add("pagination__button--active"); 1394button.setAttribute("aria-current", "page"); 1395} 1396if(extraClasses){ 1397extraClasses.split(" ").forEach((cls)=> button.classList.add(cls)); 1398} 1399button.addEventListener("click", onClick); 1400container.appendChild(button); 1401} 1402announceResults(totalItems){ 1403if(!this._announceReady){ 1404this._announceReady=true; 1405return; 1406} 1407const region=document.querySelector(".filter-live-region"); 1408if(!region) return; 1409const t=(window.rne_translations&&window.rne_translations.pagination)||{}; 1410const template=t.resultsFound||"%d Ergebnisse gefunden"; 1411region.textContent=""; 1412window.setTimeout(()=> { 1413region.textContent=template.replace(/%d/g, totalItems); 1414}, 50); 1415} 1416scrollToMediaItems(){ 1417if(this.elements.itemContainer){ 1418const yOffset=-240; 1419const element=this.elements.itemContainer; 1420const yPosition=element.getBoundingClientRect().top + window.scrollY + yOffset; 1421window.scrollTo({ top: yPosition, behavior: "smooth" }); 1422}} 1423buildIndices(){ 1424Object.values(this.indices).forEach((index)=> index.clear()); 1425this.data.forEach((post, idx)=> { 1426if(post.post_title){ 1427const normalizedTitle=post.post_title.trim().toLowerCase(); 1428if(!this.indices.titleIndex.has(normalizedTitle)){ 1429this.indices.titleIndex.set(normalizedTitle, new Set()); 1430} 1431this.indices.titleIndex.get(normalizedTitle).add(idx); 1432} 1433if(post.post_filtering_date){ 1434const dateKey=post.post_filtering_date; 1435if(!this.indices.dateIndex.has(dateKey)){ 1436this.indices.dateIndex.set(dateKey, new Set()); 1437} 1438this.indices.dateIndex.get(dateKey).add(idx); 1439} 1440if(Array.isArray(post.sdg_ids)){ 1441post.sdg_ids.forEach((sdgId)=> { 1442if(!this.indices.sdgIndex.has(sdgId)){ 1443this.indices.sdgIndex.set(sdgId, new Set()); 1444} 1445this.indices.sdgIndex.get(sdgId).add(idx); 1446}); 1447} 1448if(post.post_type){ 1449const mediaType=post.post_type.toLowerCase(); 1450if(!this.indices.typeIndex.has(mediaType)){ 1451this.indices.typeIndex.set(mediaType, new Set()); 1452} 1453this.indices.typeIndex.get(mediaType).add(idx); 1454} 1455if(Array.isArray(post.terms)&&Array.isArray(post.term_ids)){ 1456const mediaType=post.post_type.toLowerCase(); 1457post.term_ids.forEach((termId)=> { 1458if(!this.indices.termIndex.has(mediaType)){ 1459this.indices.termIndex.set(mediaType, new Map()); 1460} 1461const mediaTypeMap=this.indices.termIndex.get(mediaType); 1462if(!mediaTypeMap.has(termId)){ 1463mediaTypeMap.set(termId, new Set()); 1464} 1465const termSet=mediaTypeMap.get(termId); 1466termSet.add(idx); 1467}); 1468} 1469if(Array.isArray(post.post_terms)){ 1470post.post_term_ids.forEach((term)=> { 1471const termKey=term.toString(); 1472if(!this.indices.postTermIndex.has(termKey)){ 1473this.indices.postTermIndex.set(termKey, new Set()); 1474} 1475this.indices.postTermIndex.get(termKey).add(idx); 1476}); 1477} 1478if(post.event_city){ 1479const eventCity=post.event_city.toLowerCase(); 1480if(!this.indices.eventCityIndex.has(eventCity)){ 1481this.indices.eventCityIndex.set(eventCity, new Set()); 1482} 1483this.indices.eventCityIndex.get(eventCity).add(idx); 1484}}); 1485} 1486initTemplates(){ 1487if(this.options.templates){ 1488this.templates=this.options.templates; 1489}else{ 1490console.warn("No templates provided."); 1491}} 1492updateResetButtonVisibility(){ 1493let anyFilterActive=false;
vendor: 11,436 bytes, lines 1494-1539
1494this.elements.archiveFilters.forEach((accordionItem)=> { 1495const inputs=accordionItem.querySelectorAll("input, select, textarea"); 1496inputs.forEach((input)=> { 1497if(input.type==="checkbox"||input.type==="radio"){ 1498if(input.checked){ 1499anyFilterActive=true; 1500}}else if(input.tagName==="SELECT"&&input.value!==""){ 1501anyFilterActive=true; 1502}else if(input.tagName==="INPUT"&&input.value!==""){ 1503anyFilterActive=true; 1504}}); 1505}); 1506if(this.elements.mobileFilterOverlay){ 1507const mobileInputs=this.elements.mobileFilterOverlay.querySelectorAll("input, select, textarea"); 1508mobileInputs.forEach((input)=> { 1509if(input.type==="checkbox"||input.type==="radio"){ 1510if(input.checked){ 1511anyFilterActive=true; 1512}}else if(input.tagName==="SELECT"&&input.value!==""){ 1513anyFilterActive=true; 1514}else if(input.tagName==="INPUT"&&input.value!==""){ 1515anyFilterActive=true; 1516}}); 1517} 1518this.elements.filterResetButtons.forEach((btn)=> { 1519btn.style.display=anyFilterActive ? "block":"none"; 1520}); 1521} 1522filterAndUpdateUI(){ 1523const filterState=this.getFilterState(); 1524let matchingIndices=this.filterPosts(filterState); 1525let matchingPosts=Array.from(matchingIndices).map((idx)=> this.data[idx]); 1526if(filterState.sortingOption!=="date_newest"){ 1527this.sortPosts(matchingPosts, filterState.sortingOption); 1528} 1529const totalItems=matchingPosts.length; 1530const totalPages=Math.ceil(totalItems / this.state.itemsPerPage); 1531if(this.state.currentPage > totalPages) this.state.currentPage=totalPages; 1532if(this.state.currentPage < 1) this.state.currentPage=1; 1533const startIndex=(this.state.currentPage - 1) * this.state.itemsPerPage; 1534const paginatedPosts=matchingPosts.slice(startIndex, startIndex + this.state.itemsPerPage); 1535this.updatePostsUI(paginatedPosts); 1536this.updatePaginationControls(totalItems); 1537}} 1538window.ContentFilter=ContentFilter; 1539var SimpleBar=function(){"use strict";var t=function(e,i){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])},t(e,i)};var e="object"==typeof global&&global&&global.Object===Object&&global,i="object"==typeof self&&self&&self.Object===Object&&self,s=e||i||Function("return this")(),r=s.Symbol,l=Object.prototype,o=l.hasOwnProperty,n=l.toString,a=r?r.toStringTag:void 0;var c=Object.prototype.toString;var h=r?r.toStringTag:void 0;function u(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":h&&h in Object(t)?function(t){var e=o.call(t,a),i=t[a];try{t[a]=void 0;var s=!0}catch(t){}var r=n.call(t);return s&&(e?t[a]=i:delete t[a]),r}(t):function(t){return c.call(t)}(t)}var d=/\s/;var p=/^\s+/;function v(t){return t?t.slice(0,function(t){for(var e=t.length;e--&&d.test(t.charAt(e)););return e}(t)+1).replace(p,""):t}function f(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}var m=/^[-+]0x[0-9a-f]+$/i,b=/^0b[01]+$/i,g=/^0o[0-7]+$/i,x=parseInt;function y(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return null!=t&&"object"==typeof t}(t)&&"[object Symbol]"==u(t)}(t))return NaN;if(f(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=f(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=v(t);var i=b.test(t);return i||g.test(t)?x(t.slice(2),i?2:8):m.test(t)?NaN:+t}var E=function(){return s.Date.now()},O=Math.max,w=Math.min;function S(t,e,i){var s,r,l,o,n,a,c=0,h=!1,u=!1,d=!0;if("function"!=typeof t)throw new TypeError("Expected a function");function p(e){var i=s,l=r;return s=r=void 0,c=e,o=t.apply(l,i)}function v(t){return c=t,n=setTimeout(b,e),h?p(t):o}function m(t){var i=t-a;return void 0===a||i>=e||i<0||u&&t-c>=l}function b(){var t=E();if(m(t))return g(t);n=setTimeout(b,function(t){var i=e-(t-a);return u?w(i,l-(t-c)):i}(t))}function g(t){return n=void 0,d&&s?p(t):(s=r=void 0,o)}function x(){var t=E(),i=m(t);if(s=arguments,r=this,a=t,i){if(void 0===n)return v(a);if(u)return clearTimeout(n),n=setTimeout(b,e),p(a)}return void 0===n&&(n=setTimeout(b,e)),o}return e=y(e)||0,f(i)&&(h=!!i.leading,l=(u="maxWait"in i)?O(y(i.maxWait)||0,e):l,d="trailing"in i?!!i.trailing:d),x.cancel=function(){void 0!==n&&clearTimeout(n),c=0,s=a=r=n=void 0},x.flush=function(){return void 0===n?o:g(E())},x}var A=function(){return A=Object.assign||function(t){for(var e,i=1,s=arguments.length;i<s;i++)for(var r in e=arguments[i])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t},A.apply(this,arguments)};function k(t){return t&&t.ownerDocument&&t.ownerDocument.defaultView?t.ownerDocument.defaultView:window}function W(t){return t&&t.ownerDocument?t.ownerDocument:document}var M=function(t){return Array.prototype.reduce.call(t,(function(t,e){var i=e.name.match(/data-simplebar-(.+)/);if(i){var s=i[1].replace(/\W+(.)/g,(function(t,e){return e.toUpperCase()}));switch(e.value){case"true":t[s]=!0;break;case"false":t[s]=!1;break;case void 0:t[s]=!0;break;default:t[s]=e.value}}return t}),{})};function N(t,e){var i;t&&(i=t.classList).add.apply(i,e.split(" "))}function L(t,e){t&&e.split(" ").forEach((function(e){t.classList.remove(e)}))}function z(t){return".".concat(t.split(" ").join("."))}var C=!("undefined"==typeof window||!window.document||!window.document.createElement),T=Object.freeze({__proto__:null,addClasses:N,canUseDOM:C,classNamesToQuery:z,getElementDocument:W,getElementWindow:k,getOptions:M,removeClasses:L}),D=null,R=null;function V(){if(null===D){if("undefined"==typeof document)return D=0;var t=document.body,e=document.createElement("div");e.classList.add("simplebar-hide-scrollbar"),t.appendChild(e);var i=e.getBoundingClientRect().right;t.removeChild(e),D=i}return D}C&&window.addEventListener("resize",(function(){R!==window.devicePixelRatio&&(R=window.devicePixelRatio,D=null)}));var H=k,j=W,B=M,_=N,q=L,P=z,X=function(){function t(e,i){void 0===i&&(i={});var s=this;if(this.removePreventClickId=null,this.minScrollbarWidth=20,this.stopScrollDelay=175,this.isScrolling=!1,this.isMouseEntering=!1,this.isDragging=!1,this.scrollXTicking=!1,this.scrollYTicking=!1,this.wrapperEl=null,this.contentWrapperEl=null,this.contentEl=null,this.offsetEl=null,this.maskEl=null,this.placeholderEl=null,this.heightAutoObserverWrapperEl=null,this.heightAutoObserverEl=null,this.rtlHelpers=null,this.scrollbarWidth=0,this.resizeObserver=null,this.mutationObserver=null,this.elStyles=null,this.isRtl=null,this.mouseX=0,this.mouseY=0,this.onMouseMove=function(){},this.onWindowResize=function(){},this.onStopScrolling=function(){},this.onMouseEntered=function(){},this.onScroll=function(){var t=H(s.el);s.scrollXTicking||(t.requestAnimationFrame(s.scrollX),s.scrollXTicking=!0),s.scrollYTicking||(t.requestAnimationFrame(s.scrollY),s.scrollYTicking=!0),s.isScrolling||(s.isScrolling=!0,_(s.el,s.classNames.scrolling)),s.showScrollbar("x"),s.showScrollbar("y"),s.onStopScrolling()},this.scrollX=function(){s.axis.x.isOverflowing&&s.positionScrollbar("x"),s.scrollXTicking=!1},this.scrollY=function(){s.axis.y.isOverflowing&&s.positionScrollbar("y"),s.scrollYTicking=!1},this._onStopScrolling=function(){q(s.el,s.classNames.scrolling),s.options.autoHide&&(s.hideScrollbar("x"),s.hideScrollbar("y")),s.isScrolling=!1},this.onMouseEnter=function(){s.isMouseEntering||(_(s.el,s.classNames.mouseEntered),s.showScrollbar("x"),s.showScrollbar("y"),s.isMouseEntering=!0),s.onMouseEntered()},this._onMouseEntered=function(){q(s.el,s.classNames.mouseEntered),s.options.autoHide&&(s.hideScrollbar("x"),s.hideScrollbar("y")),s.isMouseEntering=!1},this._onMouseMove=function(t){s.mouseX=t.clientX,s.mouseY=t.clientY,(s.axis.x.isOverflowing||s.axis.x.forceVisible)&&s.onMouseMoveForAxis("x"),(s.axis.y.isOverflowing||s.axis.y.forceVisible)&&s.onMouseMoveForAxis("y")},this.onMouseLeave=function(){s.onMouseMove.cancel(),(s.axis.x.isOverflowing||s.axis.x.forceVisible)&&s.onMouseLeaveForAxis("x"),(s.axis.y.isOverflowing||s.axis.y.forceVisible)&&s.onMouseLeaveForAxis("y"),s.mouseX=-1,s.mouseY=-1},this._onWindowResize=function(){s.scrollbarWidth=s.getScrollbarWidth(),s.hideNativeScrollbar()},this.onPointerEvent=function(t){var e,i;s.axis.x.track.el&&s.axis.y.track.el&&s.axis.x.scrollbar.el&&s.axis.y.scrollbar.el&&(s.axis.x.track.rect=s.axis.x.track.el.getBoundingClientRect(),s.axis.y.track.rect=s.axis.y.track.el.getBoundingClientRect(),(s.axis.x.isOverflowing||s.axis.x.forceVisible)&&(e=s.isWithinBounds(s.axis.x.track.rect)),(s.axis.y.isOverflowing||s.axis.y.forceVisible)&&(i=s.isWithinBounds(s.axis.y.track.rect)),(e||i)&&(t.stopPropagation(),"pointerdown"===t.type&&"touch"!==t.pointerType&&(e&&(s.axis.x.scrollbar.rect=s.axis.x.scrollbar.el.getBoundingClientRect(),s.isWithinBounds(s.axis.x.scrollbar.rect)?s.onDragStart(t,"x"):s.onTrackClick(t,"x")),i&&(s.axis.y.scrollbar.rect=s.axis.y.scrollbar.el.getBoundingClientRect(),s.isWithinBounds(s.axis.y.scrollbar.rect)?s.onDragStart(t,"y"):s.onTrackClick(t,"y")))))},this.drag=function(e){var i,r,l,o,n,a,c,h,u,d,p;if(s.draggedAxis&&s.contentWrapperEl){var v=s.axis[s.draggedAxis].track,f=null!==(r=null===(i=v.rect)||void 0===i?void 0:i[s.axis[s.draggedAxis].sizeAttr])&&void 0!==r?r:0,m=s.axis[s.draggedAxis].scrollbar,b=null!==(o=null===(l=s.contentWrapperEl)||void 0===l?void 0:l[s.axis[s.draggedAxis].scrollSizeAttr])&&void 0!==o?o:0,g=parseInt(null!==(a=null===(n=s.elStyles)||void 0===n?void 0:n[s.axis[s.draggedAxis].sizeAttr])&&void 0!==a?a:"0px",10);e.preventDefault(),e.stopPropagation();var x=("y"===s.draggedAxis?e.pageY:e.pageX)-(null!==(h=null===(c=v.rect)||void 0===c?void 0:c[s.axis[s.draggedAxis].offsetAttr])&&void 0!==h?h:0)-s.axis[s.draggedAxis].dragOffset,y=(x="x"===s.draggedAxis&&s.isRtl?(null!==(d=null===(u=v.rect)||void 0===u?void 0:u[s.axis[s.draggedAxis].sizeAttr])&&void 0!==d?d:0)-m.size-x:x)/(f-m.size)*(b-g);"x"===s.draggedAxis&&s.isRtl&&(y=(null===(p=t.getRtlHelpers())||void 0===p?void 0:p.isScrollingToNegative)?-y:y),s.contentWrapperEl[s.axis[s.draggedAxis].scrollOffsetAttr]=y}},this.onEndDrag=function(t){s.isDragging=!1;var e=j(s.el),i=H(s.el);t.preventDefault(),t.stopPropagation(),q(s.el,s.classNames.dragging),s.onStopScrolling(),e.removeEventListener("mousemove",s.drag,!0),e.removeEventListener("mouseup",s.onEndDrag,!0),s.removePreventClickId=i.setTimeout((function(){e.removeEventListener("click",s.preventClick,!0),e.removeEventListener("dblclick",s.preventClick,!0),s.removePreventClickId=null}))},this.preventClick=function(t){t.preventDefault(),t.stopPropagation()},this.el=e,this.options=A(A({},t.defaultOptions),i),this.classNames=A(A({},t.defaultOptions.classNames),i.classNames),this.axis={x:{scrollOffsetAttr:"scrollLeft",sizeAttr:"width",scrollSizeAttr:"scrollWidth",offsetSizeAttr:"offsetWidth",offsetAttr:"left",overflowAttr:"overflowX",dragOffset:0,isOverflowing:!0,forceVisible:!1,track:{size:null,el:null,rect:null,isVisible:!1},scrollbar:{size:null,el:null,rect:null,isVisible:!1}},y:{scrollOffsetAttr:"scrollTop",sizeAttr:"height",scrollSizeAttr:"scrollHeight",offsetSizeAttr:"offsetHeight",offsetAttr:"top",overflowAttr:"overflowY",dragOffset:0,isOverflowing:!0,forceVisible:!1,track:{size:null,el:null,rect:null,isVisible:!1},scrollbar:{size:null,el:null,rect:null,isVisible:!1}}},"object"!=typeof this.el||!this.el.nodeName)throw new Error("Argument passed to SimpleBar must be an HTML element instead of ".concat(this.el));this.onMouseMove=function(t,e,i){var s=!0,r=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return f(i)&&(s="leading"in i?!!i.leading:s,r="trailing"in i?!!i.trailing:r),S(t,e,{leading:s,maxWait:e,trailing:r
vendor: 17,391 bytes, line 1539
1539})}(this._onMouseMove,64),this.onWindowResize=S(this._onWindowResize,64,{leading:!0}),this.onStopScrolling=S(this._onStopScrolling,this.stopScrollDelay),this.onMouseEntered=S(this._onMouseEntered,this.stopScrollDelay),this.init()}return t.getRtlHelpers=function(){if(t.rtlHelpers)return t.rtlHelpers;var e=document.createElement("div");e.innerHTML='<div class="simplebar-dummy-scrollbar-size"><div></div></div>';var i=e.firstElementChild,s=null==i?void 0:i.firstElementChild;if(!s)return null;document.body.appendChild(i),i.scrollLeft=0;var r=t.getOffset(i),l=t.getOffset(s);i.scrollLeft=-999;var o=t.getOffset(s);return document.body.removeChild(i),t.rtlHelpers={isScrollOriginAtZero:r.left!==l.left,isScrollingToNegative:l.left!==o.left},t.rtlHelpers},t.prototype.getScrollbarWidth=function(){try{return this.contentWrapperEl&&"none"===getComputedStyle(this.contentWrapperEl,"::-webkit-scrollbar").display||"scrollbarWidth"in document.documentElement.style||"-ms-overflow-style"in document.documentElement.style?0:V()}catch(t){return V()}},t.getOffset=function(t){var e=t.getBoundingClientRect(),i=j(t),s=H(t);return{top:e.top+(s.pageYOffset||i.documentElement.scrollTop),left:e.left+(s.pageXOffset||i.documentElement.scrollLeft)}},t.prototype.init=function(){C&&(this.initDOM(),this.rtlHelpers=t.getRtlHelpers(),this.scrollbarWidth=this.getScrollbarWidth(),this.recalculate(),this.initListeners())},t.prototype.initDOM=function(){var t,e;this.wrapperEl=this.el.querySelector(P(this.classNames.wrapper)),this.contentWrapperEl=this.options.scrollableNode||this.el.querySelector(P(this.classNames.contentWrapper)),this.contentEl=this.options.contentNode||this.el.querySelector(P(this.classNames.contentEl)),this.offsetEl=this.el.querySelector(P(this.classNames.offset)),this.maskEl=this.el.querySelector(P(this.classNames.mask)),this.placeholderEl=this.findChild(this.wrapperEl,P(this.classNames.placeholder)),this.heightAutoObserverWrapperEl=this.el.querySelector(P(this.classNames.heightAutoObserverWrapperEl)),this.heightAutoObserverEl=this.el.querySelector(P(this.classNames.heightAutoObserverEl)),this.axis.x.track.el=this.findChild(this.el,"".concat(P(this.classNames.track)).concat(P(this.classNames.horizontal))),this.axis.y.track.el=this.findChild(this.el,"".concat(P(this.classNames.track)).concat(P(this.classNames.vertical))),this.axis.x.scrollbar.el=(null===(t=this.axis.x.track.el)||void 0===t?void 0:t.querySelector(P(this.classNames.scrollbar)))||null,this.axis.y.scrollbar.el=(null===(e=this.axis.y.track.el)||void 0===e?void 0:e.querySelector(P(this.classNames.scrollbar)))||null,this.options.autoHide||(_(this.axis.x.scrollbar.el,this.classNames.visible),_(this.axis.y.scrollbar.el,this.classNames.visible))},t.prototype.initListeners=function(){var t,e=this,i=H(this.el);if(this.el.addEventListener("mouseenter",this.onMouseEnter),this.el.addEventListener("pointerdown",this.onPointerEvent,!0),this.el.addEventListener("mousemove",this.onMouseMove),this.el.addEventListener("mouseleave",this.onMouseLeave),null===(t=this.contentWrapperEl)||void 0===t||t.addEventListener("scroll",this.onScroll),i.addEventListener("resize",this.onWindowResize),this.contentEl){if(window.ResizeObserver){var s=!1,r=i.ResizeObserver||ResizeObserver;this.resizeObserver=new r((function(){s&&i.requestAnimationFrame((function(){e.recalculate()}))})),this.resizeObserver.observe(this.el),this.resizeObserver.observe(this.contentEl),i.requestAnimationFrame((function(){s=!0}))}this.mutationObserver=new i.MutationObserver((function(){i.requestAnimationFrame((function(){e.recalculate()}))})),this.mutationObserver.observe(this.contentEl,{childList:!0,subtree:!0,characterData:!0})}},t.prototype.recalculate=function(){if(this.heightAutoObserverEl&&this.contentEl&&this.contentWrapperEl&&this.wrapperEl&&this.placeholderEl){var t=H(this.el);this.elStyles=t.getComputedStyle(this.el),this.isRtl="rtl"===this.elStyles.direction;var e=this.contentEl.offsetWidth,i=this.heightAutoObserverEl.offsetHeight<=1,s=this.heightAutoObserverEl.offsetWidth<=1||e>0,r=this.contentWrapperEl.offsetWidth,l=this.elStyles.overflowX,o=this.elStyles.overflowY;this.contentEl.style.padding="".concat(this.elStyles.paddingTop," ").concat(this.elStyles.paddingRight," ").concat(this.elStyles.paddingBottom," ").concat(this.elStyles.paddingLeft),this.wrapperEl.style.margin="-".concat(this.elStyles.paddingTop," -").concat(this.elStyles.paddingRight," -").concat(this.elStyles.paddingBottom," -").concat(this.elStyles.paddingLeft);var n=this.contentEl.scrollHeight,a=this.contentEl.scrollWidth;this.contentWrapperEl.style.height=i?"auto":"100%",this.placeholderEl.style.width=s?"".concat(e||a,"px"):"auto",this.placeholderEl.style.height="".concat(n,"px");var c=this.contentWrapperEl.offsetHeight;this.axis.x.isOverflowing=0!==e&&a>e,this.axis.y.isOverflowing=n>c,this.axis.x.isOverflowing="hidden"!==l&&this.axis.x.isOverflowing,this.axis.y.isOverflowing="hidden"!==o&&this.axis.y.isOverflowing,this.axis.x.forceVisible="x"===this.options.forceVisible||!0===this.options.forceVisible,this.axis.y.forceVisible="y"===this.options.forceVisible||!0===this.options.forceVisible,this.hideNativeScrollbar();var h=this.axis.x.isOverflowing?this.scrollbarWidth:0,u=this.axis.y.isOverflowing?this.scrollbarWidth:0;this.axis.x.isOverflowing=this.axis.x.isOverflowing&&a>r-u,this.axis.y.isOverflowing=this.axis.y.isOverflowing&&n>c-h,this.axis.x.scrollbar.size=this.getScrollbarSize("x"),this.axis.y.scrollbar.size=this.getScrollbarSize("y"),this.axis.x.scrollbar.el&&(this.axis.x.scrollbar.el.style.width="".concat(this.axis.x.scrollbar.size,"px")),this.axis.y.scrollbar.el&&(this.axis.y.scrollbar.el.style.height="".concat(this.axis.y.scrollbar.size,"px")),this.positionScrollbar("x"),this.positionScrollbar("y"),this.toggleTrackVisibility("x"),this.toggleTrackVisibility("y")}},t.prototype.getScrollbarSize=function(t){var e,i;if(void 0===t&&(t="y"),!this.axis[t].isOverflowing||!this.contentEl)return 0;var s,r=this.contentEl[this.axis[t].scrollSizeAttr],l=null!==(i=null===(e=this.axis[t].track.el)||void 0===e?void 0:e[this.axis[t].offsetSizeAttr])&&void 0!==i?i:0,o=l/r;return s=Math.max(~~(o*l),this.options.scrollbarMinSize),this.options.scrollbarMaxSize&&(s=Math.min(s,this.options.scrollbarMaxSize)),s},t.prototype.positionScrollbar=function(e){var i,s,r;void 0===e&&(e="y");var l=this.axis[e].scrollbar;if(this.axis[e].isOverflowing&&this.contentWrapperEl&&l.el&&this.elStyles){var o=this.contentWrapperEl[this.axis[e].scrollSizeAttr],n=(null===(i=this.axis[e].track.el)||void 0===i?void 0:i[this.axis[e].offsetSizeAttr])||0,a=parseInt(this.elStyles[this.axis[e].sizeAttr],10),c=this.contentWrapperEl[this.axis[e].scrollOffsetAttr];c="x"===e&&this.isRtl&&(null===(s=t.getRtlHelpers())||void 0===s?void 0:s.isScrollOriginAtZero)?-c:c,"x"===e&&this.isRtl&&(c=(null===(r=t.getRtlHelpers())||void 0===r?void 0:r.isScrollingToNegative)?c:-c);var h=c/(o-a),u=~~((n-l.size)*h);u="x"===e&&this.isRtl?-u+(n-l.size):u,l.el.style.transform="x"===e?"translate3d(".concat(u,"px, 0, 0)"):"translate3d(0, ".concat(u,"px, 0)")}},t.prototype.toggleTrackVisibility=function(t){void 0===t&&(t="y");var e=this.axis[t].track.el,i=this.axis[t].scrollbar.el;e&&i&&this.contentWrapperEl&&(this.axis[t].isOverflowing||this.axis[t].forceVisible?(e.style.visibility="visible",this.contentWrapperEl.style[this.axis[t].overflowAttr]="scroll",this.el.classList.add("".concat(this.classNames.scrollable,"-").concat(t))):(e.style.visibility="hidden",this.contentWrapperEl.style[this.axis[t].overflowAttr]="hidden",this.el.classList.remove("".concat(this.classNames.scrollable,"-").concat(t))),this.axis[t].isOverflowing?i.style.display="block":i.style.display="none")},t.prototype.showScrollbar=function(t){void 0===t&&(t="y"),this.axis[t].isOverflowing&&!this.axis[t].scrollbar.isVisible&&(_(this.axis[t].scrollbar.el,this.classNames.visible),this.axis[t].scrollbar.isVisible=!0)},t.prototype.hideScrollbar=function(t){void 0===t&&(t="y"),this.isDragging||this.axis[t].isOverflowing&&this.axis[t].scrollbar.isVisible&&(q(this.axis[t].scrollbar.el,this.classNames.visible),this.axis[t].scrollbar.isVisible=!1)},t.prototype.hideNativeScrollbar=function(){this.offsetEl&&(this.offsetEl.style[this.isRtl?"left":"right"]=this.axis.y.isOverflowing||this.axis.y.forceVisible?"-".concat(this.scrollbarWidth,"px"):"0px",this.offsetEl.style.bottom=this.axis.x.isOverflowing||this.axis.x.forceVisible?"-".concat(this.scrollbarWidth,"px"):"0px")},t.prototype.onMouseMoveForAxis=function(t){void 0===t&&(t="y");var e=this.axis[t];e.track.el&&e.scrollbar.el&&(e.track.rect=e.track.el.getBoundingClientRect(),e.scrollbar.rect=e.scrollbar.el.getBoundingClientRect(),this.isWithinBounds(e.track.rect)?(this.showScrollbar(t),_(e.track.el,this.classNames.hover),this.isWithinBounds(e.scrollbar.rect)?_(e.scrollbar.el,this.classNames.hover):q(e.scrollbar.el,this.classNames.hover)):(q(e.track.el,this.classNames.hover),this.options.autoHide&&this.hideScrollbar(t)))},t.prototype.onMouseLeaveForAxis=function(t){void 0===t&&(t="y"),q(this.axis[t].track.el,this.classNames.hover),q(this.axis[t].scrollbar.el,this.classNames.hover),this.options.autoHide&&this.hideScrollbar(t)},t.prototype.onDragStart=function(t,e){var i;void 0===e&&(e="y"),this.isDragging=!0;var s=j(this.el),r=H(this.el),l=this.axis[e].scrollbar,o="y"===e?t.pageY:t.pageX;this.axis[e].dragOffset=o-((null===(i=l.rect)||void 0===i?void 0:i[this.axis[e].offsetAttr])||0),this.draggedAxis=e,_(this.el,this.classNames.dragging),s.addEventListener("mousemove",this.drag,!0),s.addEventListener("mouseup",this.onEndDrag,!0),null===this.removePreventClickId?(s.addEventListener("click",this.preventClick,!0),s.addEventListener("dblclick",this.preventClick,!0)):(r.clearTimeout(this.removePreventClickId),this.removePreventClickId=null)},t.prototype.onTrackClick=function(t,e){var i,s,r,l,o=this;void 0===e&&(e="y");var n=this.axis[e];if(this.options.clickOnTrack&&n.scrollbar.el&&this.contentWrapperEl){t.preventDefault();var a=H(this.el);this.axis[e].scrollbar.rect=n.scrollbar.el.getBoundingClientRect();var c=null!==(s=null===(i=this.axis[e].scrollbar.rect)||void 0===i?void 0:i[this.axis[e].offsetAttr])&&void 0!==s?s:0,h=parseInt(null!==(l=null===(r=this.elStyles)||void 0===r?void 0:r[this.axis[e].sizeAttr])&&void 0!==l?l:"0px",10),u=this.contentWrapperEl[this.axis[e].scrollOffsetAttr],d=("y"===e?this.mouseY-c:this.mouseX-c)<0?-1:1,p=-1===d?u-h:u+h,v=function(){o.contentWrapperEl&&(-1===d?u>p&&(u-=40,o.contentWrapperEl[o.axis[e].scrollOffsetAttr]=u,a.requestAnimationFrame(v)):u<p&&(u+=40,o.contentWrapperEl[o.axis[e].scrollOffsetAttr]=u,a.requestAnimationFrame(v)))};v()}},t.prototype.getContentElement=function(){return this.contentEl},t.prototype.getScrollElement=function(){return this.contentWrapperEl},t.prototype.removeListeners=function(){var t=H(this.el);this.el.removeEventListener("mouseenter",this.onMouseEnter),this.el.removeEventListener("pointerdown",this.onPointerEvent,!0),this.el.removeEventListener("mousemove",this.onMouseMove),this.el.removeEventListener("mouseleave",this.onMouseLeave),this.contentWrapperEl&&this.contentWrapperEl.removeEventListener("scroll",this.onScroll),t.removeEventListener("resize",this.onWindowResize),this.mutationObserver&&this.mutationObserver.disconnect(),this.resizeObserver&&this.resizeObserver.disconnect(),this.onMouseMove.cancel(),this.onWindowResize.cancel(),this.onStopScrolling.cancel(),this.onMouseEntered.cancel()},t.prototype.unMount=function(){this.removeListeners()},t.prototype.isWithinBounds=function(t){return this.mouseX>=t.left&&this.mouseX<=t.left+t.width&&this.mouseY>=t.top&&this.mouseY<=t.top+t.height},t.prototype.findChild=function(t,e){var i=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.msMatchesSelector;return Array.prototype.filter.call(t.children,(function(t){return i.call(t,e)}))[0]},t.rtlHelpers=null,t.defaultOptions={forceVisible:!1,clickOnTrack:!0,scrollbarMinSize:25,scrollbarMaxSize:0,ariaLabel:"scrollable content",tabIndex:0,classNames:{contentEl:"simplebar-content",contentWrapper:"simplebar-content-wrapper",offset:"simplebar-offset",mask:"simplebar-mask",wrapper:"simplebar-wrapper",placeholder:"simplebar-placeholder",scrollbar:"simplebar-scrollbar",track:"simplebar-track",heightAutoObserverWrapperEl:"simplebar-height-auto-observer-wrapper",heightAutoObserverEl:"simplebar-height-auto-observer",visible:"simplebar-visible",horizontal:"simplebar-horizontal",vertical:"simplebar-vertical",hover:"simplebar-hover",dragging:"simplebar-dragging",scrolling:"simplebar-scrolling",scrollable:"simplebar-scrollable",mouseEntered:"simplebar-mouse-entered"},scrollableNode:null,contentNode:null,autoHide:!0},t.getOptions=B,t.helpers=T,t}(),Y=X.helpers,F=Y.getOptions,I=Y.addClasses,U=Y.canUseDOM,$=function(e){function i(){for(var t=[],s=0;s<arguments.length;s++)t[s]=arguments[s];var r=e.apply(this,t)||this;return i.instances.set(t[0],r),r}return function(e,i){if("function"!=typeof i&&null!==i)throw new TypeError("Class extends value "+String(i)+" is not a constructor or null");function s(){this.constructor=e}t(e,i),e.prototype=null===i?Object.create(i):(s.prototype=i.prototype,new s)}(i,e),i.initDOMLoadedElements=function(){document.removeEventListener("DOMContentLoaded",this.initDOMLoadedElements),window.removeEventListener("load",this.initDOMLoadedElements),Array.prototype.forEach.call(document.querySelectorAll("[data-simplebar]"),(function(t){"init"===t.getAttribute("data-simplebar")||i.instances.has(t)||new i(t,F(t.attributes))}))},i.removeObserver=function(){var t;null===(t=i.globalObserver)||void 0===t||t.disconnect()},i.prototype.initDOM=function(){var t,e,i,s=this;if(!Array.prototype.filter.call(this.el.children,(function(t){return t.classList.contains(s.classNames.wrapper)})).length){for(this.wrapperEl=document.createElement("div"),this.contentWrapperEl=document.createElement("div"),this.offsetEl=document.createElement("div"),this.maskEl=document.createElement("div"),this.contentEl=document.createElement("div"),this.placeholderEl=document.createElement("div"),this.heightAutoObserverWrapperEl=document.createElement("div"),this.heightAutoObserverEl=document.createElement("div"),I(this.wrapperEl,this.classNames.wrapper),I(this.contentWrapperEl,this.classNames.contentWrapper),I(this.offsetEl,this.classNames.offset),I(this.maskEl,this.classNames.mask),I(this.contentEl,this.classNames.contentEl),I(this.placeholderEl,this.classNames.placeholder),I(this.heightAutoObserverWrapperEl,this.classNames.heightAutoObserverWrapperEl),I(this.heightAutoObserverEl,this.classNames.heightAutoObserverEl);this.el.firstChild;)this.contentEl.appendChild(this.el.firstChild);this.contentWrapperEl.appendChild(this.contentEl),this.offsetEl.appendChild(this.contentWrapperEl),this.maskEl.appendChild(this.offsetEl),this.heightAutoObserverWrapperEl.appendChild(this.heightAutoObserverEl),this.wrapperEl.appendChild(this.heightAutoObserverWrapperEl),this.wrapperEl.appendChild(this.maskEl),this.wrapperEl.appendChild(this.placeholderEl),this.el.appendChild(this.wrapperEl),null===(t=this.contentWrapperEl)||void 0===t||t.setAttribute("tabindex",this.options.tabIndex.toString()),null===(e=this.contentWrapperEl)||void 0===e||e.setAttribute("role","region"),null===(i=this.contentWrapperEl)||void 0===i||i.setAttribute("aria-label",this.options.ariaLabel)}if(!this.axis.x.track.el||!this.axis.y.track.el){var r=document.createElement("div"),l=document.createElement("div");I(r,this.classNames.track),I(l,this.classNames.scrollbar),r.appendChild(l),this.axis.x.track.el=r.cloneNode(!0),I(this.axis.x.track.el,this.classNames.horizontal),this.axis.y.track.el=r.cloneNode(!0),I(this.axis.y.track.el,this.classNames.vertical),this.el.appendChild(this.axis.x.track.el),this.el.appendChild(this.axis.y.track.el)}X.prototype.initDOM.call(this),this.el.setAttribute("data-simplebar","init")},i.prototype.unMount=function(){X.prototype.unMount.call(this),i.instances.delete(this.el)},i.initHtmlApi=function(){this.initDOMLoadedElements=this.initDOMLoadedElements.bind(this),"undefined"!=typeof MutationObserver&&(this.globalObserver=new MutationObserver(i.handleMutations),this.globalObserver.observe(document,{childList:!0,subtree:!0})),"complete"===document.readyState||"loading"!==document.readyState&&!document.documentElement.doScroll?window.setTimeout(this.initDOMLoadedElements):(document.addEventListener("DOMContentLoaded",this.initDOMLoadedElements),window.addEventListener("load",this.initDOMLoadedElements))},i.handleMutations=function(t){t.forEach((function(t){t.addedNodes.forEach((function(t){1===t.nodeType&&(t.hasAttribute("data-simplebar")?!i.instances.has(t)&&document.documentElement.contains(t)&&new i(t,F(t.attributes)):t.querySelectorAll("[data-simplebar]").forEach((function(t){"init"!==t.getAttribute("data-simplebar")&&!i.instances.has(t)&&document.documentElement.contains(t)&&new i(t,F(t.attributes))})))})),t.removedNodes.forEach((function(t){var e;1===t.nodeType&&("init"===t.getAttribute("data-simplebar")?!document.documentElement.contains(t)&&(null===(e=i.instances.get(t))||void 0===e||e.unMount()):Array.prototype.forEach.call(t.querySelectorAll('[data-simplebar="init"]'),(function(t){var e;!document.documentElement.contains(t)&&(null===(e=i.instances.get(t))||void 0===e||e.unMount())})))}))}))},i.instances=new WeakMap,i}(X);return U&&$.initHtmlApi(),$}();
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.