PageSourceSearch

https://www.dka.at/_assets/dc85f6343a3dc6533e0c4391b2c16fbe/JS/theme.js?1790786901

js dka.at collected 2026-10-02 04:24:01 UTC 25,149 bytes, 793 lines download raw bytes

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.