1+function (w, d) { 2 const convertDate = (obj) => { 3 if (!obj) { 4 return null 5 } 6 7 return new Date(Date.parse( 8 obj.date.replace(/\.0+$/, '') + ' ' + (obj.timezone) 9 )) 10 } 11 12 const PageState = { 13 CLS_NO_DISPLAY: 'no-display', 14 CLS_SHOW: 'show', 15 resizeTm: null, 16 resizeHandler: [], 17 scrollHandler: [], 18 swapNodes: [], 19 scrollYDiffHeight: 0, 20 lastScrollY: 0, 21 22 get defaultStorage() { 23 return this.template('default-storage', true) 24 }, 25 26 get viewportWidth() { 27 return parseFloat(getComputedStyle( 28 d.querySelector('html'), null).width.replace('px', '') 29 ) 30 }, 31 32 get viewportHeight() { 33 return parseFloat(getComputedStyle( 34 d.querySelector('html'), null).height.replace('px', '') 35 ) 36 }, 37 38 get scrollBarHeight() { 39 return d.querySelector('html').scrollHeight 40 }, 41 42 get scrollBarDiffHeight() { 43 const el = d.querySelector('html') 44 return el.scrollBarHeight - el.clientHeight 45 }, 46 47 get isMobileWidth() { 48 return this.viewportWidth < +d.querySelector('body').dataset.navbarBreakpointwidth 49 }, 50 51 get mainNavBarContainer() { 52 return d.querySelector('#main-navbar') 53 }, 54 55 get mainNav() { 56 return d.querySelector('.main-navbarnav') 57 }, 58 59 get isScrolledDown() { 60 return this.scrollY > this.lastScrollY 61 }, 62 63 get scrollY() { 64 return w.scrollY ?? w.pageYOffset 65 }, 66 67 addResizeHandler(scope, fn) { 68 this.resizeHandler.push([scope, fn]) 69 }, 70 71 addScollHandler(scope, fn) { 72 this.scrollHandler.push([scope, fn]) 73 }, 74 75 resize(e) { 76 clearTimeout(this.resizeTm) 77 setTimeout(() => { 78 this.scrollYDiffHeight = this.scrollBarDiffHeight 79 80 81 for (const handler of this.resizeHandler) { 82 const fn = handler[1] 83 fn.call(handler[0], this.isMobileWidth) 84 } 85 }, 300) 86 }, 87 88 scroll(e) { 89 for (const handler of this.scrollHandler) { 90 const fn = handler[1] 91 fn.call(handler[0]) 92 } 93 this.lastScrollY = this.scrollY 94 }, 95 96 template(id, toString) { 97 const target = (typeof id === 'string') 98 ? d.getElementById(id) 99 : id; 100 101 const content = target.content.children.length 102 ? target.content.children[0] 103 : target.content.childNodes[0] 104 105 const cloned = content.cloneNode(true) 106 107 if (toString) { 108 return cloned.textContent.trim() 109 } 110 111 return cloned 112 }, 113 114 siblingsOf(v, sel) { 115 return [...v.parentElement.children] 116 .filter(n => { 117 if (n === v) return false 118 if (sel && !n.matches(sel)) return false 119 return true 120 }) 121 }, 122 123 removeHide(n) { 124 n.style.display = '' 125 }, 126 127 hide(n) { 128 n.style.setProperty('display', 'none', 'important'); 129 } 130 } 131 132 const NavBar = { 133 CLS_STICKY: ['position-fixed', 'top-0'], 134 CLS_CONTAINER: ['me-auto', 'container'], 135 CLS_OFFSET: 'nav-offscrolled', 136 mainBar: null, 137 refNode: null, 138 refNodeHeight: 0, 139 refNodeRect: {}, 140 itemsBar: null, 141 itemsBarCont: null, 142 itemsRect: null, 143 itemsBarHeight: 0, 144 lastScrollY: 0, 145 isOffScrolled: null, 146 isLocked: false, 147 enabled: true, 148 parentContainer: null, 149 hasMobileWidth: false, 150 151 setup() { 152 w.NavBar = this 153 154 this.hasMobileWidth = PageState.isMobileWidth 155 this.mainBar = PageState.mainNavBarContainer 156 this.itemsBar = PageState.mainNav 157 this.itemsBarCont = this.itemsBar.closest('.nav-next') 158 this.parentContainer = this.mainBar.closest('.container') 159 this.refNode = d.querySelector('#main-navbar .nav-first') 160 this.refNodeRect = this.refNode.getBoundingClientRect() 161 this.refNodeHeight = this.refNodeRect.height 162 163 PageState.addResizeHandler(this, this.resize) 164 PageState.addScollHandler(this, this.scroll) 165 this.trigger() 166 }, 167 168 get isMainNavOffScrolled() { 169 // return this.mainBar.getBoundingClientRect().bottom - (!this.isOffScrolled ? this.itemsBarHeight : 0) <= 0 170 return PageState.scrollY > this.refNodeRect.height 171 }, 172 173 get isNavOffScrollAvailable() { 174 return PageState.scrollYDiffHeight > this.refNodeRect.height 175 }, 176 177 getNextUseableContainer() { 178 let cont 179 180 if (this.parentContainer) { 181 cont = this.parentContainer.nextSibling 182 } else { 183 cont = this.mainBar.nextSibling 184 } 185 186 while (cont) { 187 if (cont instanceof HTMLElement && cont.getBoundingClientRect().height > 0) { 188 return cont 189 } 190 191 cont = cont.nextSibling 192 } 193 }, 194 195 toggleSticky(mode) { 196 const bodyCls = d.body.classList 197 const itemsBarCls = this.itemsBar.classList 198 const itemsBarContCls = this.itemsBarCont.classList 199 const nextUsableCt = this.getNextUseableContainer() 200 const nextContSt = nextUsableCt.style 201 202 if (mode) { 203 // preserve height of to be removed space 204 this.mainBar.style.height = this.mainBar.getBoundingClientRect().height + 'px' 205 206 bodyCls.add(this.CLS_OFFSET) 207 itemsBarCls.add(...this.CLS_CONTAINER) 208 itemsBarContCls.add(...this.CLS_STICKY) 209 210 this.isOffScrolled = true 211 this.toggleElements(this.isOffScrolled) 212 } else { 213 this.mainBar.style.height = "" 214 215 bodyCls.remove(this.CLS_OFFSET) 216 itemsBarCls.remove(...this.CLS_CONTAINER) 217 itemsBarContCls.remove(...this.CLS_STICKY) 218 219 this.isOffScrolled = false 220 this.toggleElements(this.isOffScrolled) 221 } 222 }, 223 224 scroll() { 225 const locked = !this.enabled 226 || (PageState.isScrolledDown && this.isOffScrolled) 227 || (!PageState.isScrolledDown && !this.isOffScrolled) 228 229 if (locked) { 230 return 231 } 232 233 this.trigger() 234 }, 235 236 trigger() { 237 if (this.hasMobileWidth) { 238 if (this.isOffScrolled) { 239 this.toggleSticky(false) 240 } 241 return 242 } 243 244 if (this.isMainNavOffScrolled) { 245 if (!this.isOffScrolled) { 246 this.toggleSticky(true) 247 } 248 } else { 249 if (this.isOffScrolled) { 250 this.toggleSticky(false) 251 } 252 } 253 }, 254 255 toggleElements(offScrolled) { 256 for (const n of d.querySelectorAll('[data-nav-sticky]')) { 257 if (offScrolled) { 258 PageState.removeHide(n) 259 } else { 260 PageState.hide(n) 261 } 262 } 263 }, 264 265 resize(isMobileWidth) { 266 if (!this.isOffScrolled) { 267 this.itemsBarHeight = this.itemsBar.getBoundingClientRect().height 268 } 269 270 const rect = this.mainBar.getBoundingClientRect() 271 const nextUsableCt = this.getNextUseableContainer() 272 const nextContSt = nextUsableCt.style 273 274 if (isMobileWidth) { 275 this.toggleElements(false) 276 nextContSt.marginTop = '' 277 } else { 278 this.toggleElements(this.isOffScrolled) 279 } 280 281 this.hasMobileWidth = isMobileWidth 282 } 283 } 284 285 const MobileMenu = { 286 isMegaDropdown(node) { 287 return node.classList.contains('mega-dropdown-menu') 288 }, 289 290 isNavItem(node) { 291 return node.classList.contains('nav-item') 292 }, 293 294 isDropdown(node) { 295 return node.classList.contains('dropdown') 296 }, 297 298 resetMenu() { 299 PageState.mainNav 300 .querySelectorAll('*') 301 .forEach(n => { 302 const cl = n.classList 303 304 cl.remove(PageState.CLS_SHOW) 305 cl.remove(PageState.CLS_NO_DISPLAY) 306 }) 307 }, 308 309 toggleMenu(target, select) { 310 const parent = target.parentElement 311 312 const hide = (n, mode) => { 313 const cl = n.classList 314 315 if (mode) { 316 cl.add(PageState.CLS_NO_DISPLAY) 317 } else { 318 cl.remove(PageState.CLS_NO_DISPLAY) 319 } 320 } 321 322 if (this.isDropdown(parent)) { 323 let toggleParent = parent.parentElement 324 325 if (toggleParent.matches('.d-mobile-only')) { 326 toggleParent = toggleParent.parentElement 327 } 328 329 PageState 330 .siblingsOf(toggleParent, '[data-bs-toggle=dropdown]') 331 .forEach(n => hide(n, select)) 332 333 PageState.siblingsOf(parent) 334 .forEach(n => { 335 hide(n, select) 336 }) 337 } 338 }, 339 340 findLinkBefore(node, selector) { 341 let sib = node 342 343 while (sib = sib.previousSibling) { 344 if (sib instanceof HTMLElement && sib.matches(selector)) { 345 return sib 346 } 347 } 348 }, 349 350 resize(isMobileWidth) { 351 for (const link of PageState.mainNav.querySelectorAll('a.nav
351-link, a.dropdown-toggle')) { 352 if (link.matches('.root-node')) { 353 continue 354 } 355 356 if (isMobileWidth) { 357 if (!link.setup) { 358 link.setup = true 359 link.dataset.href = link.href 360 link.href = '#' 361 } 362 } else { 363 if (link.setup && 'href' in link.dataset) { 364 link.href = link.dataset.href 365 delete link.dataset.href 366 } 367 } 368 } 369 370 for (const node of PageState.mainNav.querySelectorAll('.mega-dropdown-menu')) { 371 if (isMobileWidth) { 372 PageState.hide(node) 373 } else { 374 PageState.removeHide(node) 375 } 376 } 377 378 this.resetMenu() 379 }, 380 381 setup() { 382 const mainNav = PageState.mainNav 383 console.log('mobile menu', mainNav) 384 385 mainNav.addEventListener('shown.bs.dropdown', e => { 386 if (PageState.isMobileWidth) { 387 MobileMenu.toggleMenu(e.target, true) 388 } 389 }) 390 391 mainNav.addEventListener('hidden.bs.dropdown', e => { 392 if (PageState.isMobileWidth) { 393 MobileMenu.toggleMenu(e.target, false) 394 } 395 }) 396 397 PageState.mainNavBarContainer.addEventListener('hidden.bs.collapse', e => { 398 if (e.target.matches('#navbarToggler')) { 399 this.resetMenu() 400 } 401 }) 402 403 PageState.addResizeHandler(this, this.resize) 404 } 405 } 406 407 const Donation = { 408 rules: [], 409 410 setup() { 411 const now = new Date() 412 413 setup: 414 for (const cfg of w.donationConfig) { 415 const rule = { 416 selector: cfg.selector, 417 url: cfg.url.replace('$DOMAIN', location.host), 418 dateStart: convertDate(cfg.date_start), 419 dateEnd: convertDate(cfg.date_end), 420 class: cfg.link_class, 421 title: cfg.link_title, 422 full: !!(cfg.settings & 1), 423 ignoreYear: !!(cfg.settings & 2), 424 appendNav: !!(cfg.settings & 4), 425 activateDom: !!(cfg.settings & 8), 426 mode: +cfg.responsive, 427 position: +cfg.position 428 } 429 430 if (cfg.host_filter) { 431 for (const n of cfg.host_filter.split(';')) { 432 const host = n.trim().split('/', 2) 433 434 if (host[0] !== location.host) { 435 continue setup 436 } 437 438 if (host.length === 2 && location.pathname.replace(/^\/|\/$/, '') !== host[1]) { 439 continue setup 440 } 441 442 break 443 } 444 } 445 446 const add = (!rule.dateStart && !rule.dateEnd) 447 || (!rule.dateStart && rule.dateEnd >= now) 448 || (!rule.dateEnd && rule.dateStart <= now) 449 450 if (add) { 451 this.rules.push(rule) 452 continue 453 } 454 455 if (rule.ignoreYear) { 456 rule.dateStart.setFullYear(now.getFullYear()) 457 rule.dateEnd.setFullYear(now.getFullYear()) 458 } 459 460 if (rule.dateStart <= now || rule.dateEnd >= now) { 461 this.rules.push(rule) 462 } 463 } 464 465 PageState.addResizeHandler(this, this.resize) 466 }, 467 468 createLink(rule) { 469 const el = d.createElement('a') 470 471 el.href = rule.url
472 el.title = rule.title 473 el.origHref = rule.url 474 el.textContent = rule.title 475 el.classList.add('nav-link') 476 return el 477 }, 478 479 process(rule, restore) { 480 const _update = (n, val, full) => { 481 if (full) { 482 n.href = val 483 } else { 484 const p = val.split('?', 2)[1] ?? val 485 486 if (n.href.includes('?')) { 487 n.href = n.href.replace(/\?.+/, '?' + p) 488 } else { 489 n.href += '?' + p 490 } 491 } 492 } 493 494 if (rule.appendNav) { 495 const mainNav = PageState.mainNav 496 497 if (!rule.element) { 498 const item = d.createElement('div') 499 item.classList.add('nav-item', ...rule.class.split(' ')) 500 item.append(this.createLink(rule)) 501 502 rule.element = item 503 504 if (rule.position === 0) { 505 mainNav.append(rule.element) 506 } else if (rule.position < 0) { 507 const ref = mainNav.children[mainNav.children.length - Math.abs(rule.position)] 508 if (ref) { 509 mainNav.insertBefore(rule.element, ref) 510 } else { 511 console.warn(`Cannot insert rule in navigation position ${rule.position}`, rule) 512 mainNav.append(rule.element) 513 } 514 } 515 } 516 517 if (restore) { 518 rule.element.classList.add(PageState.CLS_NO_DISPLAY) 519 } else { 520 rule.element.classList.remove(PageState.CLS_NO_DISPLAY) 521 } 522 } 523 524 if (rule.selector) { 525 for (const n of d.querySelectorAll(rule.selector)) { 526 if (n instanceof HTMLAnchorElement) { 527 const dt = n.dataset 528 529 if (!dt.origHref) { 530 dt.origHref = n.href 531 } 532 533 if (restore) { 534 _update(n, dt.origHref, true) 535 } else { 536 _update(n, rule.url, rule.full) 537 } 538 } 539 540 if (rule.activateDom) { 541 if (restore) { 542 n.classList.add(PageState.CLS_NO_DISPLAY) 543 } else { 544 n.classList.remove(PageState.CLS_NO_DISPLAY) 545 } 546 } 547 } 548 } 549 }, 550 551 resize(isMobileWidth) { 552 for (const rule of this.rules) { 553 switch (rule.mode) { 554 case 0: 555 // all modes 556 this.process(rule, false) 557 break 558 559 case 1: 560 // mobile only or restore 561 this.process(rule, !isMobileWidth) 562 break 563 564 case 2: 565 // desktop only or restore 566 this.process(rule, isMobileWidth) 567 break 568 } 569 570 if (rule.mobileOnly) { 571 this.process(rule, !isMobileWidth) 572 } else { 573 this.process(rule) 574 } 575 } 576 } 577 } 578 579 const Legacy = { 580 setupPlugins() { 581 const $ = w.jQuery 582 const defaultStorage = PageState.defaultStorage 583 584 $.fn.dkaMaxHeight = function () { 585 let a = []; 586 this.each(function () { 587 a.push($(this).height()); 588 }); 589 a.sort(function (a, b) { 590 return b - a; 591 }); 592 return a[0]; 593 }; 594 595 $.fn.dkaSlider = function () { 596 this.on('init', function () { 597 let x = 12; 598 if (PageState.isMobileWidth) { 599 x = -6; 600 } 601 a = $(this).find('.slide-desc').dkaMaxHeight() - x; 602 $(this).find('.slick-dots').css('bottom', a + 'px'); 603 }).slick({ 604 dots: true,
605 arrows: false, 606 slide: '.slide', 607 accessibility: true, 608 responsive: [ 609 { 610 breakpoint: 991, 611 settings: { 612 arrows: false 613 } 614 } 615 ] 616 }); 617 618 $(this).dkaSliderArrows(); 619 }; 620 621 $.fn.dkaSliderArrows = function () { 622 //this.append("<span class='cb-sld-prev'><span><</span></span>"); 623 this.append(`<span class='cb-sld-prev'><button><img class='noclo' src='${defaultStorage}/custom/assets/pfeil_links_1.svg' alt='zurück'></button></span>`); 624 //this.append("<span class='cb-sld-next'><span>></span></span>"); 625 this.append(`<span class='cb-sld-next'><button title='weiter'><img class='noclo' src='${defaultStorage}/custom/assets/pfeil_rechts_1.svg' alt='weiter'></button></span>`); 626 this.find('.cb-sld-prev').click(function () { 627 $(this).parent().slick('slickPrev'); 628 }); 629 this.find('.cb-sld-next').click(function () { 630 $(this).parent().slick('slickNext'); 631 }); 632 }; 633 }, 634 635 slideToggle(v) { 636 v.forEach(el => { 637 w.jQuery(el) 638 .slideToggle(); 639 }) 640 }, 641 642 slickSlide(n, enable) { 643 const el = w.jQuery(n) 644 645 if (n.classList.contains('slick-initialized')) { 646 if (!enable) el.slick('unslick') 647 } else if (enable) { 648 el.slick({ 649 dots: true, 650 arrows: false, 651 accesibility: true 652 }); 653 } 654 }, 655 656 siblings(v, sel) { 657 return PageState.siblingsOf(v, sel) 658 }, 659 660 fadeIn(v) { 661 w.jQuery(v).fadeIn() 662 }, 663 664 fadeOut(v) { 665 w.jQuery(v).fadeOut() 666 }, 667 668 wrapLabel(v) { 669 const wrap = d.createElement('div') 670 const label = d.createElement('div') 671 672 label.className = 'label' 673 674 wrap.className = 'dka-input-field' 675 wrap.append(label, v.cloneNode(true)) 676 677 v = v.replaceWith(wrap) 678 }, 679 680 setup() { 681 const donationVal = d.querySelector('input[name=spendenbetrag]') 682 const donationValCustom = d.querySelector('input[name=mailformprice][type=text]') 683 const donationInfo = d.querySelector('div.spendenverwendung') 684 685 const donationBtnToggle = (ctx) => { 686 const btn = ctx.closest('.btn-spenden') 687 const input = btn.querySelector('input[type=radio]') 688 const customVal = btn.querySelector('input[type=text]') 689 const text = PageState.template(btn.querySelector('template')) 690 691 if(text && donationInfo) { 692 donationInfo.innerHTML = "" 693 donationInfo.append(text) 694 } 695 696 Legacy.siblings(btn, '.btn-spenden') 697 .forEach(s => { 698 s.classList.remove('active') 699 700 const input = s.querySelector('input') 701 input.checked = false 702 input.removeAttribute('checked') 703 }) 704 705 input.checked = true 706 btn.classList.add('active') 707 708 if(customVal) { 709 donationVal.value = customVal.value 710 } else { 711 donationVal.value = input.value 712 } 713 } 714 715 if (donationVal) { 716 for (const n of d.querySelectorAll('.spenden')) { 717 n.addEventListener('click', e => { 718 if (e.target.classList.contains('btn-spenden')) { 719 donationBtnToggle(e.target) 720 } 721 }) 722 723 n.addEventListener('change', e => { 724 donationBtnToggle(e.target) 725 }) 726 } 727 728 donationValCustom.addEventListener('focus', e => { 729 donationBtnToggle(e.target) 730 }) 731 } 732 733 for (const n of d.querySelectorAll('.element-klappe-group')) { 734 n.addEventListener('click', e => { 735 const el = e.target.closest('.element-klappe') 736 737 if (el) { 738 el.classList.toggle('ausgeklappt') 739 Legacy.slideToggle(el.querySelectorAll('.ausklapp-text')) 740 } 741 }) 742 } 743 744 d.querySelectorAll('input.inp').forEach(n => this.wrapLabel(n)) 745 746 d.addEventListener('keyup', (e) => { 747 const el = e.target 748 749 if (!el.matches('input.inp')) { 750 return 751 } 752 753 const sib = this.siblings(el, 'div.label') 754 755 if (el.value) { 756 sib.forEach(n => { 757 n.textContent = el.placeholder 758 this.fadeIn(n) 759 }) 760 } else { 761 sib 762 .forEach(n => this.fadeOut(n)) 763 } 764 }) 765 766 this.setupPlugins() 767 w.jQuery('.element-slider').dkaSlider(); 768 } 769 } 770 771 d.addEventListener('DOMContentLoaded', () => { 772 w.addEventListener('resize', e => PageState.resize(e)) 773 w.addEventListener('scroll', e => PageState.scroll(e), {passive: true}) 774 775 for (const n of d.querySelectorAll('template[data-cm-tpl]')) { 776 const content = PageState.template(n) 777 content.classList.add(PageState.CLS_NO_DISPLAY) 778 content.dataset.cmTpl = n.dataset.cmTpl 779 n.replaceWith(content) 780 } 781 782 NavBar.setup() 783 MobileMenu.setup() 784 Donation.setup() 785 Legacy.setup() 786 787 PageState.addResizeHandler(this, isMobileWith => { 788 d.querySelectorAll('.element-teaser-2') 789 .forEach(n => Legacy.slickSlide(n, isMobileWith)) 790 }) 791 PageState.resize() 792 }) 793}(window, document);
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.